vicky469_aside/tests/commentSessionController.test.ts

203 lines
8.9 KiB
TypeScript
Raw Normal View History

2026-03-31 04:32:58 +00:00
import * as assert from "node:assert/strict";
import test from "node:test";
2026-05-04 19:40:03 +00:00
import { CommentSessionController } from "../src/comments/commentSessionController";
2026-03-31 04:32:58 +00:00
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,
};
}
2026-04-13 01:57:48 +00:00
test("comment session controller refreshes comment views when nested comments are toggled", async () => {
2026-04-07 06:40:07 +00:00
const harness = createHarness();
2026-04-30 05:25:16 +00:00
assert.equal(harness.controller.shouldShowNestedComments(), true);
2026-05-05 16:39:14 +00:00
assert.equal(await harness.controller.setShowNestedComments(false), true);
assert.equal(harness.controller.shouldShowNestedComments(), false);
2026-04-07 06:40:07 +00:00
assert.equal(harness.getRefreshCommentViewsCount(), 1);
assert.equal(harness.getRefreshEditorDecorationsCount(), 0);
assert.equal(harness.getRefreshMarkdownPreviewsCount(), 0);
2026-05-05 16:39:14 +00:00
assert.equal(await harness.controller.setShowNestedComments(false), false);
2026-04-13 01:57:48 +00:00
assert.equal(harness.getRefreshCommentViewsCount(), 1);
2026-04-07 06:40:07 +00:00
});
test("comment session controller can override nested comment visibility per thread and reset with show all", async () => {
const harness = createHarness();
2026-04-30 05:25:16 +00:00
assert.equal(harness.controller.shouldShowNestedCommentsForThread("thread-1"), true);
2026-05-05 16:39:14 +00:00
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);
2026-05-05 16:39:14 +00:00
assert.equal(await harness.controller.setShowNestedCommentsForThread("thread-1", false), false);
assert.equal(harness.getRefreshCommentViewsCount(), 1);
2026-04-30 05:25:16 +00:00
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);
2026-04-30 05:25:16 +00:00
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);
2026-04-30 05:25:16 +00:00
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);
2026-05-05 16:39:14 +00:00
assert.equal(await harness.controller.setShowNestedCommentsForThread("thread-1", false, {
skipCommentViewRefresh: true,
}), true);
2026-05-05 16:39:14 +00:00
assert.equal(harness.controller.shouldShowNestedCommentsForThread("thread-1"), false);
assert.equal(harness.getRefreshCommentViewsCount(), 0);
});
2026-03-31 04:32:58 +00:00
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(
2026-05-13 18:44:11 +00:00
harness.controller.setRevealedCommentState("Aside index.md", "comment-7", {
refreshMarkdownPreviews: false,
}),
true,
);
2026-05-13 18:44:11 +00:00
assert.equal(harness.controller.getRevealedCommentId("Aside index.md"), "comment-7");
assert.equal(harness.getRefreshEditorDecorationsCount(), 1);
assert.equal(harness.getRefreshMarkdownPreviewsCount(), 0);
});
2026-03-31 04:32:58 +00:00
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();
2026-05-13 18:44:11 +00:00
await harness.controller.setDraftComment(draft, "Aside index.md");
2026-03-31 04:32:58 +00:00
assert.deepEqual(harness.controller.getDraftForFile(draft.filePath), draft);
2026-05-13 18:44:11 +00:00
assert.deepEqual(harness.controller.getDraftForView("Aside index.md"), draft);
assert.equal(harness.controller.getDraftHostFilePath(), "Aside index.md");
2026-03-31 04:32:58 +00:00
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);
});