import * as assert from "node:assert/strict"; import test from "node:test"; import type { Comment } from "../src/commentManager"; import { findClickedHighlightCommentId } from "../src/comments/commentHighlightClickTarget"; import { findClickedIndexLivePreviewTarget, isIndexNativeCollapseControlTarget, shouldBlockIndexPreviewBackgroundTarget, shouldUseIndexPreviewRowActivator, shouldUseIndexLivePreviewLineFallback, } from "../src/comments/commentIndexClickTarget"; import { buildPreviewHighlightWraps } from "../src/comments/commentHighlightPlanner"; function createComment(overrides: Partial = {}): Comment { return { id: "comment-1", filePath: "note.md", startLine: 0, startChar: 0, endLine: 0, endChar: 4, selectedText: "beta", selectedTextHash: "hash-beta", comment: "note", timestamp: 1710000000000, ...overrides, }; } test("buildPreviewHighlightWraps follows the source occurrence when rendered text repeats", () => { const wraps = buildPreviewHighlightWraps( "beta one beta", 0, "beta one beta", [createComment({ startChar: 9, endChar: 13, selectedText: "beta", })], ); assert.equal(wraps.length, 1); assert.equal(wraps[0].start, 9); assert.equal(wraps[0].end, 13); assert.equal(wraps[0].comment.id, "comment-1"); }); test("buildPreviewHighlightWraps respects section line offsets for later lines", () => { const wraps = buildPreviewHighlightWraps( "alpha beta\nsecond beta", 10, "alpha beta\nsecond beta", [createComment({ id: "comment-2", startLine: 11, startChar: 7, endLine: 11, endChar: 11, selectedText: "beta", })], ); assert.equal(wraps.length, 1); assert.equal(wraps[0].start, 18); assert.equal(wraps[0].end, 22); assert.equal(wraps[0].comment.id, "comment-2"); }); test("findClickedHighlightCommentId returns the clicked highlight comment id", () => { const target = { closest: (selector: string) => { assert.equal(selector, ".aside-highlight"); return { getAttribute: (name: string) => { assert.equal(name, "data-comment-id"); return "comment-7"; }, }; }, }; assert.equal(findClickedHighlightCommentId(target), "comment-7"); }); test("findClickedHighlightCommentId returns null when the target is not inside a highlight", () => { const target = { closest: () => null, }; assert.equal(findClickedHighlightCommentId(target), null); assert.equal(findClickedHighlightCommentId(null), null); }); test("findClickedIndexLivePreviewTarget resolves comment links from live preview DOM", () => { const target = { closest: (selector: string) => { if (selector === "a.aside-index-comment-link[data-aside-comment-url]") { return { dataset: { asideCommentUrl: "obsidian://aside-comment?vault=public&file=books%2FNote.md&commentId=comment-7", }, getAttribute: () => null, }; } return null; }, }; assert.deepEqual(findClickedIndexLivePreviewTarget(target), { kind: "comment", filePath: "books/Note.md", commentId: "comment-7", }); }); test("findClickedIndexLivePreviewTarget resolves file headings from live preview DOM", () => { const target = { closest: (selector: string) => { if (selector === "a.aside-index-comment-link[data-aside-comment-url]") { return null; } if (selector.includes(".aside-index-heading-label[title]")) { return { dataset: {}, getAttribute: (name: string) => { assert.equal(name, "title"); return "books/Note.md"; }, }; } return null; }, }; assert.deepEqual(findClickedIndexLivePreviewTarget(target), { kind: "file", filePath: "books/Note.md", }); }); test("findClickedIndexLivePreviewTarget resolves plain generated file links", () => { const target = { closest: (selector: string) => { if (selector.includes("a[href^=\"obsidian://open\"]")) { return { dataset: {}, getAttribute: (name: string) => { assert.equal(name, "href"); return "obsidian://open?vault=public&file=books%2FNote.md"; }, }; } return null; }, }; assert.deepEqual(findClickedIndexLivePreviewTarget(target), { kind: "file", filePath: "books/Note.md", }); }); test("findClickedIndexLivePreviewTarget leaves native collapse controls alone", () => { const target = { closest: (selector: string) => { if (selector.includes(".collapse-indicator")) { return { dataset: {}, getAttribute: () => null, }; } if (selector === "a.aside-index-comment-link[data-aside-comment-url]") { return { dataset: { asideCommentUrl: "obsidian://aside-comment?vault=public&file=books%2FNote.md&commentId=comment-7", }, getAttribute: () => null, }; } return null; }, }; assert.equal(isIndexNativeCollapseControlTarget(target), true); assert.equal(findClickedIndexLivePreviewTarget(target), null); }); test("findClickedIndexLivePreviewTarget returns null for non-index elements", () => { const target = { closest: () => null, }; assert.equal(findClickedIndexLivePreviewTarget(target), null); assert.equal(findClickedIndexLivePreviewTarget(null), null); }); test("index live preview line fallback ignores clicks on blank line space", () => { const lineEl = {}; const childTarget = {}; assert.equal(shouldUseIndexLivePreviewLineFallback(lineEl, lineEl), false); assert.equal(shouldUseIndexLivePreviewLineFallback(childTarget, lineEl), false); }); test("index preview row activator ignores clicks on blank row space", () => { const rowEl = {}; const childTarget = {}; assert.equal(shouldUseIndexPreviewRowActivator(rowEl, rowEl), false); assert.equal(shouldUseIndexPreviewRowActivator(childTarget, rowEl), false); }); test("index preview background clicks are blocked only on generated index rows", () => { const generatedRow = { getAttribute: () => null, querySelector: (selector: string) => selector.includes("a[href^=\"obsidian://open\"]") ? { getAttribute: () => "obsidian://open?vault=dev&file=test.md" } : null, }; const rowBackgroundTarget = { closest: (selector: string) => selector === "p, li" ? generatedRow : null, }; const linkTarget = { closest: (selector: string) => { if (selector.includes("a[href^=\"obsidian://open\"]")) { return { dataset: {}, getAttribute: () => "obsidian://open?vault=dev&file=test.md", }; } if (selector === "p, li") { return generatedRow; } return null; }, }; const normalRowTarget = { closest: (selector: string) => selector === "p, li" ? { getAttribute: () => null, querySelector: () => null } : null, }; assert.equal(shouldBlockIndexPreviewBackgroundTarget(rowBackgroundTarget), true); assert.equal(shouldBlockIndexPreviewBackgroundTarget(linkTarget), false); assert.equal(shouldBlockIndexPreviewBackgroundTarget(normalRowTarget), false); }); test("index preview background clicks are blocked on the generated preview surface", () => { const indexPreviewBackgroundTarget = { closest: () => null, matches: (selector: string) => selector.includes(".aside-index-note-view .markdown-preview-sizer"), }; const normalPreviewBackgroundTarget = { closest: () => null, matches: () => false, }; assert.equal(shouldBlockIndexPreviewBackgroundTarget(indexPreviewBackgroundTarget), true); assert.equal(shouldBlockIndexPreviewBackgroundTarget(normalPreviewBackgroundTarget), false); });