import { describe, expect, it } from "vitest";
import { zipSync } from "fflate";
import { inspectDocxAcceptance } from "../src/index.js";
const encoder = new TextEncoder();
const word =
"http://schemas.openxmlformats.org/wordprocessingml/2006/main";
const relationships =
"http://schemas.openxmlformats.org/officeDocument/2006/relationships";
const packageRelationships =
"http://schemas.openxmlformats.org/package/2006/relationships";
const math =
"http://schemas.openxmlformats.org/officeDocument/2006/math";
const drawing =
"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing";
const png = Uint8Array.of(
0x89,
0x50,
0x4e,
0x47,
0x0d,
0x0a,
0x1a,
0x0a,
0,
0,
0,
0
);
function xml(value: string) {
return encoder.encode(value);
}
function createAcceptanceDocx(
overrides: {
altChunk?: boolean;
duplicateText?: boolean;
internalMarker?: boolean;
invalidPropertyOrder?: boolean;
} = {}
) {
return zipSync({
"[Content_Types].xml": xml(
'
整体 HTML
") } : {}) }); } const expectation = { id: "unit-fixture", page: { widthTwips: 11906, heightTwips: 16838, orientation: "portrait" as const, marginsTwips: { top: 907, right: 907, bottom: 907, left: 907 } }, requiredText: ["可编辑正文", "原生表格"], requiredFootnoteText: ["脚注"], minimumParagraphs: 3, minimumTextRuns: 2, minimumTables: 1, minimumNumberedParagraphs: 1, minimumHyperlinks: 1, minimumFootnoteReferences: 1, minimumMathObjects: 1, minimumPngImages: 1, requiredImageAltText: ["普通图片"], requiredStyleIds: ["Normal", "Heading1", "SourceCode", "Table"], requiredParagraphStyleIds: ["Heading1"], requirePageField: true, minimumSections: 2, requireFirstSectionWithoutHeaderFooter: true, finalPageNumberStart: 1, requireSectionPagesField: true, minimumFullWidthTables: 1, maximumTextOccurrences: { 可编辑正文: 1 }, forbidInternalMarkers: true }; describe("DOCX 自动验收器", () => { it("验证纸张、可编辑结构、关系、PNG 和字段", () => { const report = inspectDocxAcceptance( createAcceptanceDocx(), expectation ); expect(report.page.orientation).toBe("portrait"); expect(report.structure).toMatchObject({ tableCount: 1, numberedParagraphCount: 1, hyperlinkCount: 1, footnoteReferenceCount: 1, mathObjectCount: 1, pngImageCount: 1, pageFieldCount: 1, sectionPageFieldCount: 1, sectionCount: 2, fullWidthTableCount: 1, internalMarkerCount: 0, altChunkCount: 0 }); expect(report.checks).toEqual( expect.objectContaining({ editableStructure: true, pngMedia: true, noAltChunk: true }) ); }); it("拒绝通过 altChunk 嵌入的正文 HTML", () => { expect(() => inspectDocxAcceptance( createAcceptanceDocx({ altChunk: true }), expectation ) ).toThrow("altChunk"); }); it("拒绝重复文本和未清理的内部标记", () => { expect(() => inspectDocxAcceptance( createAcceptanceDocx({ duplicateText: true }), expectation ) ).toThrow("最多允许 1 次"); expect(() => inspectDocxAcceptance( createAcceptanceDocx({ internalMarker: true }), expectation ) ).toThrow("internal-markers"); }); it("拒绝 WordprocessingML 属性子节点乱序", () => { expect(() => inspectDocxAcceptance( createAcceptanceDocx({ invalidPropertyOrder: true }), expectation ) ).toThrow("w:pPr 子节点顺序无效"); }); });