UNPKG

insta-toc

Version:

Simultaneously generate, update, and maintain a table of contents for your notes in real time.

91 lines (67 loc) 3.97 kB
import type { HeadingCache } from "obsidian"; import { describe, expect, test, vi } from "vitest"; import { ManageToc } from "../src/ManageToc"; import { getDefaultLocalSettings } from "../src/settings/Settings"; import { createEditor, createPluginMock, createValidatorMock } from "./mocks/pluginClassMocks"; function getEndPosition(text: string): { line: number; ch: number; } { const lines = text.split("\n"); return { line: lines.length - 1, ch: lines[lines.length - 1]?.length ?? 0 }; } describe("ManageToc global/local setting precedence", () => { test("falls back to global tocTitle when local title.name is null", async () => { const localSettings = getDefaultLocalSettings(); localSettings.title.name = null; localSettings.title.level = null; localSettings.title.center = null; const fileHeadings = [ { heading: "Heading 1", level: 1 }, { heading: "Heading 2", level: 2 } ] as HeadingCache[]; const { validator } = createValidatorMock(localSettings, fileHeadings); const pluginMock = createPluginMock({ tocTitle: "Global Table of Contents" }); await ManageToc.run(pluginMock.plugin.editorService, pluginMock.plugin.settings, validator); const generatedTocBlock = pluginMock.getCapturedContent(); expect(generatedTocBlock).toContain("Global Table of Contents"); expect(generatedTocBlock).not.toContain("null Global Table of Contents"); expect(generatedTocBlock).toContain("\n - Heading 2"); }); test("prefers local title settings over global defaults when provided", async () => { const localSettings = getDefaultLocalSettings(); localSettings.title.name = "Local TOC"; localSettings.title.level = 2; localSettings.title.center = true; const fileHeadings = [ { heading: "Heading 1", level: 1 } ] as HeadingCache[]; const { validator } = createValidatorMock(localSettings, fileHeadings); const pluginMock = createPluginMock({ tocTitle: "Global Table of Contents" }); await ManageToc.run(pluginMock.plugin.editorService, pluginMock.plugin.settings, validator); const generatedTocBlock = pluginMock.getCapturedContent(); expect(generatedTocBlock).toContain("## Local TOC"); expect(generatedTocBlock).not.toContain("Global Table of Contents"); }); test("updates only the minimal changed range for an existing toc block", async () => { const localSettings = getDefaultLocalSettings(); const initialHeadings = [ { heading: "Heading 1", level: 1 }, { heading: "Old Heading 2", level: 1 } ] as HeadingCache[]; const updatedHeadings = [ { heading: "Heading 1", level: 1 }, { heading: "Heading 2", level: 1 } ] as HeadingCache[]; const { validator } = createValidatorMock(localSettings, initialHeadings); const pluginMock = createPluginMock(undefined, createEditor([])); await ManageToc.run(pluginMock.plugin.editorService, pluginMock.plugin.settings, validator); const initialTocBlock = pluginMock.getCapturedContent(); validator.fileHeadings = updatedHeadings; validator.tocInsertPos = { from: { line: 0, ch: 0 }, to: getEndPosition(initialTocBlock) }; const applySpy = vi.spyOn(pluginMock.plugin.editorService, "applyEditorChange"); await ManageToc.run(pluginMock.plugin.editorService, pluginMock.plugin.settings, validator); expect(pluginMock.getCapturedContent()).toContain("- Heading 2"); expect(pluginMock.getCapturedContent()).not.toContain("- Old Heading 2"); expect(applySpy).toHaveBeenCalledTimes(1); const [ from, to, insert ] = applySpy.mock.calls[0] ?? []; expect(from).toEqual({ line: 16, ch: 2 }); expect(to).toEqual({ line: 16, ch: 6 }); expect(insert).toBe(""); }); });