/* tslint:disable:typedef space-before-function-paren */ import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import * as sinon from "sinon"; import * as fflate from "fflate"; import { File } from "@file/file"; import { Footer, Header } from "@file/header"; import { ImageRun, Paragraph } from "@file/paragraph"; import * as convenienceFunctions from "@util/convenience-functions"; import { Compiler } from "./next-compiler"; const unzip = (zipFile: Uint8Array): Promise> => { const set = new Set(); const unzipper = new fflate.Unzip((file) => { set.add(file.name); }); return new Promise>((resolve) => { setTimeout(() => { resolve(set); }, 1000); unzipper.push(zipFile, true); }); }; describe("Compiler", () => { let compiler: Compiler; beforeEach(() => { compiler = new Compiler(); }); beforeAll(() => { vi.spyOn(convenienceFunctions, "uniqueId").mockReturnValue("test"); }); afterAll(() => { vi.resetAllMocks(); }); describe("#compile()", () => { it( "should pack all the content", async () => { const file = new File({ sections: [], comments: { children: [], }, }); const zipFile = await compiler.compile(file); const fileNames = await unzip(zipFile); expect(fileNames).has.length(13); expect(fileNames).to.include("word/document.xml"); expect(fileNames).to.include("word/document.xml"); expect(fileNames).to.include("word/styles.xml"); expect(fileNames).to.include("docProps/core.xml"); expect(fileNames).to.include("docProps/custom.xml"); expect(fileNames).to.include("docProps/app.xml"); expect(fileNames).to.include("word/numbering.xml"); expect(fileNames).to.include("word/footnotes.xml"); expect(fileNames).to.include("word/_rels/footnotes.xml.rels"); expect(fileNames).to.include("word/settings.xml"); expect(fileNames).to.include("word/comments.xml"); expect(fileNames).to.include("word/_rels/document.xml.rels"); expect(fileNames).to.include("[Content_Types].xml"); expect(fileNames).to.include("_rels/.rels"); }, { timeout: 99999999, }, ); it( "should pack all additional headers and footers", async () => { const file = new File({ sections: [ { headers: { default: new Header({ children: [new Paragraph("test")], }), }, footers: { default: new Footer({ children: [new Paragraph("test")], }), }, children: [], }, { headers: { default: new Header({ children: [new Paragraph("test")], }), }, footers: { default: new Footer({ children: [new Paragraph("test")], }), }, children: [], }, ], }); const zipFile = await compiler.compile(file); const fileNames = await unzip(zipFile); expect(fileNames).has.length(21); expect(fileNames).to.include("word/header1.xml"); expect(fileNames).to.include("word/_rels/header1.xml.rels"); expect(fileNames).to.include("word/header2.xml"); expect(fileNames).to.include("word/_rels/header2.xml.rels"); expect(fileNames).to.include("word/footer1.xml"); expect(fileNames).to.include("word/_rels/footer1.xml.rels"); expect(fileNames).to.include("word/footer2.xml"); expect(fileNames).to.include("word/_rels/footer2.xml.rels"); }, { timeout: 99999999, }, ); it("should call the format method X times equalling X files to be formatted", () => { // This test is required because before, there was a case where Document was formatted twice, which was inefficient // This also caused issues such as running prepForXml multiple times as format() was ran multiple times. const paragraph = new Paragraph(""); const file = new File({ sections: [ { properties: {}, children: [paragraph], }, ], }); // tslint:disable-next-line: no-string-literal const spy = sinon.spy(compiler["formatter"], "format"); compiler.compile(file); expect(spy.callCount).to.equal(13); }); it("should work with media datas", () => { // This test is required because before, there was a case where Document was formatted twice, which was inefficient // This also caused issues such as running prepForXml multiple times as format() was ran multiple times. const file = new File({ sections: [ { headers: { default: new Header({ children: [new Paragraph("test")], }), }, footers: { default: new Footer({ children: [new Paragraph("test")], }), }, children: [ new Paragraph({ children: [ new ImageRun({ data: Buffer.from("", "base64"), transformation: { width: 100, height: 100, }, }), ], }), ], }, ], }); // tslint:disable-next-line: no-string-literal sinon.stub(compiler["imageReplacer"], "getMediaData").returns([ { stream: Buffer.from(""), fileName: "test", transformation: { pixels: { x: 100, y: 100, }, emus: { x: 100, y: 100, }, }, }, ]); compiler.compile(file); }); }); });