Files
MorphDoc/packages/preview-engine/tests/semantic-cover-fit.test.ts
T
SkyJourney b275c671fc fix: 修复DOCX独立封面视觉门禁
统一 Chromium 与 DOCX 的受限高度封面布局,补齐可编辑边框、装饰边和 Office 页面舍入适配。

按四套独立封面主题、纵横方向及五组页边距执行 40 个 Word/WPS 真实视觉场景,严格失败为 0,并保留正文诊断供 D4 修复。
2026-08-03 18:15:21 +08:00

90 lines
3.5 KiB
TypeScript

// @vitest-environment happy-dom
import { describe, expect, it } from "vitest";
import { constrainSemanticCoversToPage } from "../src/semantic-cover-fit.js";
function createCover(height: number) {
const root = document.createElement("div");
root.innerHTML = `
<header
data-semantic-region="cover"
data-semantic-break-after="next-page"
>封面</header>
`;
const cover = root.querySelector<HTMLElement>("header")!;
cover.getBoundingClientRect = () =>
({ height } as DOMRect);
document.body.append(root);
return { root, cover };
}
describe("语义封面页面适配", () => {
it("只将超过横向页面内容区的封面收束为单页高度", () => {
const { root, cover } = createCover(900);
cover.style.display = "flex";
cover.style.flexDirection = "column";
cover.style.alignItems = "center";
cover.style.justifyContent = "center";
expect(constrainSemanticCoversToPage(root, 680)).toBe(1);
expect(cover.style.boxSizing).toBe("border-box");
expect(cover.style.height).toBe("672px");
expect(cover.style.minHeight).toBe("672px");
expect(cover.style.maxHeight).toBe("672px");
expect(cover.style.overflow).toBe("hidden");
expect(cover.style.display).toBe("block");
expect(cover.style.getPropertyValue("break-inside")).toBe("auto");
expect(cover.style.getPropertyPriority("break-inside")).toBe("important");
expect(cover.dataset.semanticCoverFit).toBe("constrained");
expect(cover.dataset.semanticCoverPageBreak).toBe("natural");
expect(cover.hasAttribute("data-semantic-break-after")).toBe(false);
const anchor = cover.nextElementSibling as HTMLElement | null;
expect(anchor?.dataset.semanticCoverPageBreakAnchor).toBe("true");
expect(anchor?.style.height).toBe("0px");
expect(anchor?.style.getPropertyValue("break-after")).toBe("page");
expect(anchor?.style.getPropertyPriority("break-after")).toBe(
"important"
);
const layout = cover.querySelector<HTMLElement>(
'[data-semantic-cover-layout="flex"]'
);
expect(layout?.style.display).toBe("flex");
expect(layout?.style.flexDirection).toBe("column");
expect(layout?.style.alignItems).toBe("center");
expect(layout?.style.justifyContent).toBe("center");
});
it("纵向页面可以容纳主题封面时保持主题原始高度", () => {
const { root, cover } = createCover(680);
expect(constrainSemanticCoversToPage(root, 900)).toBe(0);
expect(cover.getAttribute("style")).toBeNull();
expect(cover.dataset.semanticCoverFit).toBeUndefined();
});
it("横向页面按同一比例压缩封面子元素纵向间距", () => {
const { root, cover } = createCover(900);
cover.style.display = "flex";
cover.style.flexDirection = "column";
cover.innerHTML = `
<p style="margin-top: 50px; margin-bottom: 50px">标题</p>
<p style="margin-top: 50px; margin-bottom: 50px">日期</p>
`;
for (const child of Array.from(cover.children)) {
Object.defineProperty(child, "getBoundingClientRect", {
value: () => ({ height: 100 } as DOMRect),
});
}
expect(constrainSemanticCoversToPage(root, 300)).toBe(1);
expect(cover.dataset.semanticCoverSpacingScale).toBe("0.460000");
const layout = cover.querySelector<HTMLElement>(
'[data-semantic-cover-layout="flex"]'
)!;
for (const child of Array.from(layout.children)) {
expect((child as HTMLElement).style.marginTop).toBe("23px");
expect((child as HTMLElement).style.marginBottom).toBe("23px");
}
});
});