Files
paseo/packages/app/src/stores/draft-store.migration.test.ts
T
Mohamed BoudraandGitHub 92afb826d9 Add inline review comments to git diff pane (#530)
* Add inline git diff review comments

Adds a review draft store keyed per diff target, inline gutter + thread
rendering in the diff pane, and a generated review attachment that flows
through the composer and agent providers.

* Strip generated review attachments before saving to draft store

Drafts persist only UserComposerAttachment (no review kind), so filter the
auto-generated review attachment out when seeding the draft or restoring
after a failed auto-submit.

* Fix inline review typecheck and test harness drift

* Unslop inline review feature

- Fix stale-closure bug in composer queueMessage: clear drafts for the
  actually-queued attachments, not the latest props
- Drop dead useEffect mirroring initialBody in inline review editor
  (parent already remounts via key)
- Restore typed AgentAttachment signature on renderPromptAttachmentAsText;
  delete schema redispatch helper and drop null-checks across 5 providers
- Inline single-use review prompt formatters and replace marker switch
  with const map
- Drop normalizeComment field-copy redundancy after type guard
- Remove __reviewDraftStoreTestUtils export; test migration via
  rehydrate() public path
- Refactor findTarget to return the target line directly (no non-null
  assertion at call site)
- Drop redundant isGeneratedReviewAttachment helper; inline kind check

* Update review pill to withUnistyles after rebase

Main's unistyles refactor stripped useUnistyles in favor of withUnistyles +
StyleSheet. Convert ReviewAttachmentPill to use ThemedCircleDot + ICON_SIZE so
the icon picks up the foreground-muted mapping like the other pills.

* Fix lint and typecheck after rebase onto main

Resolve drift after main's withUnistyles refactor:
- Composer complexity: dedup voice?.isVoiceSwitching to drop to 20
- Move per-comment Pressable handlers in git-diff-inline-review into
  CommentRow subcomponent so callbacks are stable
- Hoist style/onPress factories to module level (iconButton,
  iconButtonDestructive, ghostButton)
- Memoize style arrays in git-diff-pane review wrappers
- Replace inline {} placeholders with useMemo styles
- review-draft-store: extract applyCommentUpdates to avoid map-spread,
  include input.key in useMemo deps
- Test fixtures: hoist EMPTY_COMMENTS, add buildReviewActions helper

* Drop GitDiffPane default param to keep complexity at 20

After the rebase, main's `enabled = true` default param combined with the
inline review additions pushed cyclomatic complexity to 21. Drop the
default and resolve `enabled !== false` at the call site (comparison
doesn't count toward complexity).

* Reshape inline review behind @/review module

Drop the `generated: true` attachment flag and consolidate inline-review
logic behind a deep `@/review` module so composer and git-diff-pane stop
hand-composing review primitives. Workspace-scoped review snapshots are
now derived at submit/queue time rather than persisted in the draft
store. Composer review references drop from 51 to 4; git-diff-pane drops
~108 lines and now consumes a controller hook + slot components.

* Fix optimistic review attachments
2026-04-30 21:35:58 +08:00

148 lines
4.0 KiB
TypeScript

import "@/test/window-local-storage";
import { beforeEach, describe, expect, it } from "vitest";
import type { ComposerAttachment } from "@/attachments/types";
import { __draftStoreTestUtils, useDraftStore } from "./draft-store";
function workspaceReviewAttachment(): Extract<ComposerAttachment, { kind: "review" }> {
return {
kind: "review",
reviewDraftKey: "review:key",
commentCount: 1,
attachment: {
type: "review",
mimeType: "application/paseo-review",
cwd: "/repo",
mode: "uncommitted",
baseRef: null,
comments: [
{
filePath: "src/example.ts",
side: "new",
lineNumber: 41,
body: "Please simplify this.",
context: {
hunkHeader: "@@ -40,1 +40,1 @@",
targetLine: {
oldLineNumber: null,
newLineNumber: 41,
type: "add",
content: "const value = newValue;",
},
lines: [
{
oldLineNumber: null,
newLineNumber: 41,
type: "add",
content: "const value = newValue;",
},
],
},
},
],
},
};
}
describe("draft-store migration", () => {
beforeEach(() => {
useDraftStore.setState({ drafts: {}, createModalDraft: null });
});
it("normalizes legacy image metadata into image attachments and strips persisted preview URLs", async () => {
const migrated = await __draftStoreTestUtils.migratePersistedState({
drafts: {
"agent:server:agent": {
input: {
text: "hello",
images: [
{
id: "att-1",
mimeType: "image/png",
storageType: "desktop-file",
storageKey: "/tmp/att-1.png",
createdAt: 1700000000000,
previewUri: "asset://should-not-persist",
},
],
},
lifecycle: "active",
updatedAt: 1700000000001,
version: 1,
},
},
createModalDraft: null,
});
expect(migrated.drafts["agent:server:agent"]?.input).toEqual({
text: "hello",
attachments: [
{
kind: "image",
metadata: {
id: "att-1",
mimeType: "image/png",
storageType: "desktop-file",
storageKey: "/tmp/att-1.png",
createdAt: 1700000000000,
},
},
],
cwd: "",
});
});
it("is idempotent for already-migrated shapes", async () => {
const original = {
drafts: {
"agent:server:agent": {
input: {
text: "hello",
attachments: [
{
kind: "image",
metadata: {
id: "att-1",
mimeType: "image/jpeg",
storageType: "web-indexeddb",
storageKey: "att-1",
createdAt: 1700000000000,
},
},
],
cwd: "/repo",
},
lifecycle: "active",
updatedAt: 1700000000001,
version: 2,
},
},
createModalDraft: null,
};
const once = await __draftStoreTestUtils.migratePersistedState(original);
const twice = await __draftStoreTestUtils.migratePersistedState(once);
expect(twice).toEqual(once);
});
it("rejects workspace review attachments from migrated draft attachments", async () => {
const migrated = await __draftStoreTestUtils.migratePersistedState({
drafts: {
"agent:server:agent": {
input: {
text: "hello",
attachments: [workspaceReviewAttachment()],
cwd: "/repo",
},
lifecycle: "active",
updatedAt: 1700000000001,
version: 2,
},
},
createModalDraft: null,
});
expect(migrated.drafts["agent:server:agent"]?.input.attachments).toEqual([]);
});
});