diff --git a/VueApp/src/CMS/__tests__/content-block-edit-diff.test.ts b/VueApp/src/CMS/__tests__/content-block-edit-diff.test.ts new file mode 100644 index 000000000..6d6418450 --- /dev/null +++ b/VueApp/src/CMS/__tests__/content-block-edit-diff.test.ts @@ -0,0 +1,166 @@ +import ContentBlockEdit from "@/CMS/pages/ContentBlockEdit.vue" +import { mountCms, flushPromises, createTestRouter } from "./test-utils" + +/** + * Diff additions to ContentBlockEdit: selecting a version only sets selectedHistory (it no longer + * auto-loads), the "Diff vs current" / "Load into editor" buttons are disabled until a version is + * selected, and diffAgainstCurrent POSTs the editor's CURRENT content to the diff endpoint, opens + * ContentDiffDialog with the returned HTML, and notifies + closes on failure. Mock ViperFetch. + */ + +const mockGet = vi.fn<(...args: unknown[]) => unknown>() +const mockPost = vi.fn<(...args: unknown[]) => unknown>() +const mockPut = vi.fn<(...args: unknown[]) => unknown>() +vi.mock("@/composables/ViperFetch", () => ({ + useFetch: () => ({ + get: (...args: unknown[]) => mockGet(...args), + post: (...args: unknown[]) => mockPost(...args), + put: (...args: unknown[]) => mockPut(...args), + createUrlSearchParams: (obj: Record) => { + const params = new URLSearchParams() + for (const [k, v] of Object.entries(obj)) { + if (v !== null && v !== undefined) { + params.append(k, v.toString()) + } + } + return params + }, + }), +})) + +const BLOCK = { + contentBlockId: 7, + content: "

current editor content

", + title: "Welcome", + system: "Viper", + application: null, + page: null, + viperSectionPath: null, + blockOrder: 1, + friendlyName: "welcome", + allowPublicAccess: false, + modifiedOn: "2024-03-01T12:00:00", + modifiedBy: "editor", + deletedOn: null, + permissions: [], + files: [], +} + +const HISTORY = [ + { contentHistoryId: 91, modifiedOn: "2024-02-01T10:00:00", modifiedBy: "bob" }, + { contentHistoryId: 92, modifiedOn: "2024-01-01T09:00:00", modifiedBy: "amy" }, +] + +function routeGet() { + mockGet.mockReset() + mockPost.mockReset() + mockGet.mockImplementation((...args: unknown[]) => { + const url = args[0] as string + if (url.includes("/section-paths")) { + return Promise.resolve({ success: true, result: [] }) + } + if (url.includes("/history")) { + return Promise.resolve({ success: true, result: HISTORY }) + } + // The single-block load (.../content/7). + return Promise.resolve({ success: true, result: { ...BLOCK } }) + }) +} + +// QEditor relies on document.execCommand and rich-text DOM that happy-dom lacks; stub it with a +// minimal v-model textarea so block.content still binds without exercising the real editor. +const qEditorStub = { + name: "QEditor", + props: ["modelValue"], + emits: ["update:modelValue"], + methods: { + getContentEl() { + return null + }, + }, + template: `