功能(文档与桌面):完善文件预览下载与客户端构建基线
- 保存文档版本原始文件名,规范下载响应并持久化上传目录\n- 增加 PDF.js 预览、桌面保存打开流程及统一错误反馈\n- 统一 Node.js 22.13 构建基线并收紧临时文件权限门禁\n- 补充迁移、单元测试、发布检查与运维文档
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
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");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user