44db5db838
- 保存文档版本原始文件名,规范下载响应并持久化上传目录\n- 增加 PDF.js 预览、桌面保存打开流程及统一错误反馈\n- 统一 Node.js 22.13 构建基线并收紧临时文件权限门禁\n- 补充迁移、单元测试、发布检查与运维文档
120 lines
4.3 KiB
TypeScript
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");
|
|
});
|
|
});
|