vicky469_aside/tests/commentSessionController.test.ts
vicky469 0cdc6ca29d refactor(comments): remove resolved feature
Removes the resolved/unresolve comment feature entirely. Comments are
now always visible — there is no archived state or toggle.

- Removes `resolved?: boolean` from CommentThread, Comment, and all
  storage/normalization paths
- Removes resolveComment/unresolveComment from CommentManager,
  CommentMutationController, and public plugin API
- Removes shouldShowResolvedComments/setShowResolvedComments from
  session, mutation, and persistence controllers
- Removes sidebar resolve button, toolbar chip, and resolved empty
  states from AsideView
- Removes setThreadResolved sync event generation; keeps the op in the
  union type as a backward-compatible no-op so old stored events parse
  without error
- Deletes resolvedCommentVisibility.ts, commentSelectionVisibility.ts,
  and resolve-note-comment.mjs scripts
- Updates README to remove resolved feature mentions
- Updates all tests accordingly

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 18:11:45 +08:00

202 lines
8.9 KiB
TypeScript

import * as assert from "node:assert/strict";
import test from "node:test";
import { CommentSessionController } from "../src/comments/commentSessionController";
import type { DraftComment } from "../src/domain/drafts";
function createDraft(overrides: Partial<DraftComment> = {}): DraftComment {
return {
id: overrides.id ?? "draft-1",
filePath: overrides.filePath ?? "docs/architecture.md",
startLine: overrides.startLine ?? 10,
startChar: overrides.startChar ?? 2,
endLine: overrides.endLine ?? 10,
endChar: overrides.endChar ?? 18,
selectedText: overrides.selectedText ?? "Module Blueprint",
selectedTextHash: overrides.selectedTextHash ?? "hash:module-blueprint",
comment: overrides.comment ?? "Draft note",
timestamp: overrides.timestamp ?? 123,
anchorKind: overrides.anchorKind ?? "selection",
orphaned: overrides.orphaned ?? false,
mode: overrides.mode ?? "new",
};
}
function createHarness() {
let refreshCommentViewsCount = 0;
let refreshEditorDecorationsCount = 0;
let refreshMarkdownPreviewsCount = 0;
const clearedMarkdownSelections: string[] = [];
const controller = new CommentSessionController({
refreshCommentViews: async () => {
refreshCommentViewsCount += 1;
},
refreshEditorDecorations: () => {
refreshEditorDecorationsCount += 1;
},
refreshMarkdownPreviews: () => {
refreshMarkdownPreviewsCount += 1;
},
clearMarkdownSelection: (filePath) => {
clearedMarkdownSelections.push(filePath);
},
});
return {
controller,
getRefreshCommentViewsCount: () => refreshCommentViewsCount,
getRefreshEditorDecorationsCount: () => refreshEditorDecorationsCount,
getRefreshMarkdownPreviewsCount: () => refreshMarkdownPreviewsCount,
clearedMarkdownSelections,
};
}
test("comment session controller refreshes comment views when nested comments are toggled", async () => {
const harness = createHarness();
assert.equal(harness.controller.shouldShowNestedComments(), true);
assert.equal(await harness.controller.setShowNestedComments(false), true);
assert.equal(harness.controller.shouldShowNestedComments(), false);
assert.equal(harness.getRefreshCommentViewsCount(), 1);
assert.equal(harness.getRefreshEditorDecorationsCount(), 0);
assert.equal(harness.getRefreshMarkdownPreviewsCount(), 0);
assert.equal(await harness.controller.setShowNestedComments(false), false);
assert.equal(harness.getRefreshCommentViewsCount(), 1);
});
test("comment session controller can override nested comment visibility per thread and reset with show all", async () => {
const harness = createHarness();
assert.equal(harness.controller.shouldShowNestedCommentsForThread("thread-1"), true);
assert.equal(await harness.controller.setShowNestedCommentsForThread("thread-1", false), true);
assert.equal(harness.controller.shouldShowNestedCommentsForThread("thread-1"), false);
assert.equal(harness.controller.shouldShowNestedCommentsForThread("thread-2"), true);
assert.equal(harness.getRefreshCommentViewsCount(), 1);
assert.equal(await harness.controller.setShowNestedCommentsForThread("thread-1", false), false);
assert.equal(harness.getRefreshCommentViewsCount(), 1);
assert.equal(await harness.controller.setShowNestedComments(true), true);
assert.equal(harness.controller.shouldShowNestedCommentsForThread("thread-1"), true);
assert.equal(harness.controller.shouldShowNestedCommentsForThread("thread-2"), true);
assert.equal(harness.getRefreshCommentViewsCount(), 2);
assert.equal(await harness.controller.setShowNestedCommentsForThread("thread-1", false), true);
assert.equal(harness.controller.shouldShowNestedCommentsForThread("thread-1"), false);
assert.equal(harness.controller.shouldShowNestedCommentsForThread("thread-2"), true);
assert.equal(harness.getRefreshCommentViewsCount(), 3);
assert.equal(await harness.controller.setShowNestedComments(false), true);
assert.equal(harness.controller.shouldShowNestedCommentsForThread("thread-1"), false);
assert.equal(harness.controller.shouldShowNestedCommentsForThread("thread-2"), false);
assert.equal(harness.getRefreshCommentViewsCount(), 4);
});
test("comment session controller can skip sidebar rerenders for deleted and nested visibility updates", async () => {
const harness = createHarness();
assert.equal(await harness.controller.setShowDeletedComments(true, {
skipCommentViewRefresh: true,
}), true);
assert.equal(harness.getRefreshCommentViewsCount(), 0);
assert.equal(await harness.controller.setShowNestedCommentsForThread("thread-1", false, {
skipCommentViewRefresh: true,
}), true);
assert.equal(harness.controller.shouldShowNestedCommentsForThread("thread-1"), false);
assert.equal(harness.getRefreshCommentViewsCount(), 0);
});
test("comment session controller tracks revealed comments and clears markdown selections on reset", () => {
const harness = createHarness();
assert.equal(
harness.controller.setRevealedCommentState("docs/architecture.md", "comment-1"),
true,
);
assert.equal(
harness.controller.getRevealedCommentId("docs/architecture.md"),
"comment-1",
);
assert.equal(harness.getRefreshEditorDecorationsCount(), 1);
assert.equal(harness.getRefreshMarkdownPreviewsCount(), 1);
assert.equal(
harness.controller.setRevealedCommentState("docs/architecture.md", "comment-1"),
false,
);
assert.equal(harness.getRefreshEditorDecorationsCount(), 1);
assert.equal(harness.getRefreshMarkdownPreviewsCount(), 1);
harness.controller.clearRevealedCommentSelection();
assert.equal(harness.controller.getRevealedCommentId("docs/architecture.md"), null);
assert.equal(harness.getRefreshEditorDecorationsCount(), 2);
assert.equal(harness.getRefreshMarkdownPreviewsCount(), 2);
assert.deepEqual(harness.clearedMarkdownSelections, ["docs/architecture.md"]);
});
test("comment session controller can skip markdown preview rerender for a revealed comment update", () => {
const harness = createHarness();
assert.equal(
harness.controller.setRevealedCommentState("Aside index.md", "comment-7", {
refreshMarkdownPreviews: false,
}),
true,
);
assert.equal(harness.controller.getRevealedCommentId("Aside index.md"), "comment-7");
assert.equal(harness.getRefreshEditorDecorationsCount(), 1);
assert.equal(harness.getRefreshMarkdownPreviewsCount(), 0);
});
test("comment session controller still refreshes reveal state surfaces when no comment is active", () => {
const harness = createHarness();
harness.controller.clearRevealedCommentSelection();
assert.equal(harness.getRefreshEditorDecorationsCount(), 1);
assert.equal(harness.getRefreshMarkdownPreviewsCount(), 1);
assert.deepEqual(harness.clearedMarkdownSelections, []);
});
test("comment session controller manages draft state and refresh side effects", async () => {
const harness = createHarness();
const draft = createDraft();
await harness.controller.setDraftComment(draft, "Aside index.md");
assert.deepEqual(harness.controller.getDraftForFile(draft.filePath), draft);
assert.deepEqual(harness.controller.getDraftForView("Aside index.md"), draft);
assert.equal(harness.controller.getDraftHostFilePath(), "Aside index.md");
assert.equal(harness.getRefreshCommentViewsCount(), 1);
assert.equal(harness.getRefreshEditorDecorationsCount(), 1);
assert.equal(harness.controller.updateDraftCommentText(draft.id, "Updated draft"), true);
assert.equal(harness.controller.getDraftComment()?.comment, "Updated draft");
harness.controller.setSavingDraftCommentId(draft.id);
assert.equal(harness.controller.isSavingDraft(draft.id), true);
assert.equal(await harness.controller.cancelDraft("other-id"), false);
assert.equal(harness.getRefreshCommentViewsCount(), 1);
assert.equal(harness.getRefreshEditorDecorationsCount(), 1);
assert.equal(await harness.controller.cancelDraft(draft.id), true);
assert.equal(harness.controller.getDraftComment(), null);
assert.equal(harness.controller.getDraftHostFilePath(), null);
assert.equal(harness.getRefreshCommentViewsCount(), 2);
assert.equal(harness.getRefreshEditorDecorationsCount(), 2);
});
test("comment session controller can skip the initial comment view refresh when opening a draft", async () => {
const harness = createHarness();
const draft = createDraft();
await harness.controller.setDraftComment(draft, draft.filePath, {
skipCommentViewRefresh: true,
});
assert.deepEqual(harness.controller.getDraftForView(draft.filePath), draft);
assert.equal(harness.getRefreshCommentViewsCount(), 0);
assert.equal(harness.getRefreshEditorDecorationsCount(), 1);
});