Files
ctms/frontend/src/components/PdfViewer.test.ts
T
Cheng Zhou 44db5db838
Client Quality Gates / Shared client and Web (push) Has been cancelled
Client Quality Gates / macOS Desktop (push) Has been cancelled
功能(文档与桌面):完善文件预览下载与客户端构建基线
- 保存文档版本原始文件名,规范下载响应并持久化上传目录\n- 增加 PDF.js 预览、桌面保存打开流程及统一错误反馈\n- 统一 Node.js 22.13 构建基线并收紧临时文件权限门禁\n- 补充迁移、单元测试、发布检查与运维文档
2026-07-13 18:40:48 +08:00

120 lines
4.3 KiB
TypeScript

import { flushPromises, mount } from "@vue/test-utils";
import { beforeEach, describe, expect, it, vi } from "vitest";
const getDocumentMock = vi.hoisted(() => vi.fn());
const renderMock = vi.hoisted(() => vi.fn());
const destroyMock = vi.hoisted(() => vi.fn());
vi.mock("pdfjs-dist", () => ({
GlobalWorkerOptions: { workerSrc: "" },
getDocument: getDocumentMock,
}));
import PdfViewer from "./PdfViewer.vue";
describe("PdfViewer", () => {
beforeEach(() => {
vi.clearAllMocks();
renderMock.mockReturnValue({ promise: Promise.resolve(), cancel: vi.fn() });
destroyMock.mockResolvedValue(undefined);
getDocumentMock.mockReturnValue({
promise: Promise.resolve({
numPages: 2,
getPage: vi.fn().mockResolvedValue({
getViewport: ({ scale }: { scale: number }) => ({ width: 600 * scale, height: 800 * scale }),
render: renderMock,
}),
destroy: destroyMock,
}),
destroy: destroyMock,
});
});
it("renders PDF pages to canvas without an iframe", async () => {
const wrapper = mount(PdfViewer, { props: { src: "blob:test-pdf" } });
await flushPromises();
expect(getDocumentMock).toHaveBeenCalledWith({ url: "blob:test-pdf" });
expect(wrapper.findAll("canvas")).toHaveLength(2);
expect(wrapper.find("iframe").exists()).toBe(false);
expect(renderMock).toHaveBeenCalled();
expect(wrapper.text()).toContain("/ 2");
await wrapper.get("button:nth-of-type(2)").trigger("click");
await flushPromises();
expect(wrapper.text()).toContain("/ 2");
wrapper.unmount();
await flushPromises();
expect(destroyMock).toHaveBeenCalled();
});
it("integrates the dialog close action into the viewer toolbar", async () => {
const wrapper = mount(PdfViewer, { props: { src: "blob:test-pdf", showClose: true } });
await flushPromises();
await wrapper.get('[aria-label="关闭预览"]').trigger("click");
expect(wrapper.emitted("close")).toHaveLength(1);
});
it("keeps the visible document center anchored while zooming", async () => {
const wrapper = mount(PdfViewer, { props: { src: "blob:test-pdf" } });
await flushPromises();
const viewport = wrapper.get(".pdf-viewer__viewport").element as HTMLElement;
Object.defineProperties(viewport, {
clientWidth: { configurable: true, value: 800 },
clientHeight: { configurable: true, value: 600 },
scrollWidth: {
configurable: true,
get: () => Math.max(800, Number.parseInt(wrapper.get("canvas").element.style.width, 10) || 0),
},
scrollHeight: {
configurable: true,
get: () => Math.max(600, Number.parseInt(wrapper.get("canvas").element.style.height, 10) || 0),
},
});
await wrapper.get("button.is-active").trigger("click");
await flushPromises();
await wrapper.get('[aria-label="放大"]').trigger("click");
await flushPromises();
expect(viewport.scrollLeft).toBeGreaterThan(0);
expect(viewport.scrollTop).toBeGreaterThan(0);
});
it("shows the original filename in the center of the toolbar", async () => {
const wrapper = mount(PdfViewer, {
props: { src: "blob:test-pdf", filename: "研究方案最终版.pdf" },
});
await flushPromises();
expect(wrapper.get(".pdf-viewer__filename").text()).toBe("研究方案最终版.pdf");
expect(wrapper.text()).not.toContain("页文档");
});
it("updates the current page while scrolling through the continuous document", async () => {
const wrapper = mount(PdfViewer, { props: { src: "blob:test-pdf" } });
await flushPromises();
const viewport = wrapper.get(".pdf-viewer__viewport");
const pages = wrapper.findAll(".pdf-viewer__page");
Object.defineProperties(viewport.element, {
clientHeight: { configurable: true, value: 600 },
scrollTop: { configurable: true, writable: true, value: 850 },
});
Object.defineProperties(pages[0].element, {
offsetTop: { configurable: true, value: 0 },
offsetHeight: { configurable: true, value: 800 },
});
Object.defineProperties(pages[1].element, {
offsetTop: { configurable: true, value: 816 },
offsetHeight: { configurable: true, value: 800 },
});
await viewport.trigger("scroll");
expect((wrapper.get(".pdf-viewer__page-input").element as HTMLInputElement).value).toBe("2");
});
});