import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import * as chai from "chai"; import JSZip from "jszip"; import chaiAsPromised from "chai-as-promised"; import { ExternalHyperlink, ImageRun, Paragraph, TextRun } from "@file/paragraph"; import { patchDocument, PatchType } from "./from-docx"; chai.use(chaiAsPromised); const MOCK_XML = ` Hello World Hello {{name}}, how are you? {{paragraph_replace}} {{table}} {{table_heading_1}} Item: {{item_1}} {{image_test}} Thank you `; describe("from-docx", () => { describe("patchDocument", () => { describe("document.xml and [Content_Types].xml", () => { beforeEach(() => { vi.spyOn(JSZip, "loadAsync").mockReturnValue( new Promise((resolve) => { const zip = new JSZip(); zip.file("word/document.xml", MOCK_XML); zip.file("[Content_Types].xml", ``); resolve(zip); }), ); }); afterEach(() => { vi.restoreAllMocks(); }); it("should patch the document", async () => { const output = await patchDocument(Buffer.from(""), { patches: { name: { type: PatchType.PARAGRAPH, children: [new TextRun("Sir. "), new TextRun("John Doe"), new TextRun("(The Conqueror)")], }, item_1: { type: PatchType.PARAGRAPH, children: [ new TextRun("#657"), new ExternalHyperlink({ children: [ new TextRun({ text: "BBC News Link", }), ], link: "https://www.bbc.co.uk/news", }), ], }, // eslint-disable-next-line @typescript-eslint/naming-convention paragraph_replace: { type: PatchType.DOCUMENT, children: [ new Paragraph({ children: [ new TextRun("This is a "), new ExternalHyperlink({ children: [ new TextRun({ text: "Google Link", }), ], link: "https://www.google.co.uk", }), new ImageRun({ data: Buffer.from(""), transformation: { width: 100, height: 100 }, }), ], }), ], }, // eslint-disable-next-line @typescript-eslint/naming-convention image_test: { type: PatchType.PARAGRAPH, children: [ new ImageRun({ data: Buffer.from(""), transformation: { width: 100, height: 100 }, }), ], }, }, }); expect(output).to.not.be.undefined; }); it("should patch the document", async () => { const output = await patchDocument(Buffer.from(""), { patches: {}, }); expect(output).to.not.be.undefined; }); }); describe("document.xml and [Content_Types].xml with relationships", () => { beforeEach(() => { vi.spyOn(JSZip, "loadAsync").mockReturnValue( new Promise((resolve) => { const zip = new JSZip(); zip.file("word/document.xml", MOCK_XML); zip.file("word/_rels/document.xml.rels", ``); zip.file("[Content_Types].xml", ``); resolve(zip); }), ); }); afterEach(() => { vi.restoreAllMocks(); }); it("should use the relationships file rather than create one", async () => { const output = await patchDocument(Buffer.from(""), { patches: { // eslint-disable-next-line @typescript-eslint/naming-convention image_test: { type: PatchType.PARAGRAPH, children: [ new ImageRun({ data: Buffer.from(""), transformation: { width: 100, height: 100 }, }), new ExternalHyperlink({ children: [ new TextRun({ text: "Google Link", }), ], link: "https://www.google.co.uk", }), ], }, }, }); expect(output).to.not.be.undefined; }); }); describe("document.xml", () => { beforeEach(() => { vi.spyOn(JSZip, "loadAsync").mockReturnValue( new Promise((resolve) => { const zip = new JSZip(); zip.file("word/document.xml", MOCK_XML); resolve(zip); }), ); }); afterEach(() => { vi.restoreAllMocks(); }); it("should throw an error if the content types is not found", () => expect( patchDocument(Buffer.from(""), { patches: { // eslint-disable-next-line @typescript-eslint/naming-convention image_test: { type: PatchType.PARAGRAPH, children: [ new ImageRun({ data: Buffer.from(""), transformation: { width: 100, height: 100 }, }), ], }, }, }), ).to.eventually.be.rejected); }); describe("Images", () => { beforeEach(() => { vi.spyOn(JSZip, "loadAsync").mockReturnValue( new Promise((resolve) => { const zip = new JSZip(); zip.file("word/document.xml", MOCK_XML); zip.file("word/document.bmp", ""); resolve(zip); }), ); }); afterEach(() => { vi.restoreAllMocks(); }); it("should throw an error if the content types is not found", () => expect( patchDocument(Buffer.from(""), { patches: { // eslint-disable-next-line @typescript-eslint/naming-convention image_test: { type: PatchType.PARAGRAPH, children: [ new ImageRun({ data: Buffer.from(""), transformation: { width: 100, height: 100 }, }), ], }, }, }), ).to.eventually.be.rejected); }); }); });