Files
MorphDoc/apps/web/tests/pdf-export.test.ts
T

177 lines
4.5 KiB
TypeScript

import { describe, expect, it, vi } from "vitest";
import { defaultExportConfig } from "@md-to-pdf/core";
import {
createPdfExportCacheKey,
getCachedPdfExport,
getOrRequestPdfExport,
parseContentDispositionFileName,
requestPdfExport,
type CachedPdfExport,
type PdfExportRequest
} from "../src/pdf-export";
describe("PDF 导出客户端", () => {
it("仅复用与当前文档和导出配置完全匹配的 PDF", () => {
const request: PdfExportRequest = {
markdown: "# 测试",
fileName: "测试.md",
language: "zh-CN",
exportConfig: defaultExportConfig
};
const key = createPdfExportCacheKey(request);
const result = {
blob: new Blob(["%PDF-test"]),
fileName: "测试.pdf",
pageCount: 1,
mermaidErrorCount: 0
};
const cache: CachedPdfExport = { key, result };
expect(getCachedPdfExport(cache, key)).toBe(result);
expect(
getCachedPdfExport(
cache,
createPdfExportCacheKey({
...request,
markdown: "# 已修改"
})
)
).toBeUndefined();
expect(
getCachedPdfExport(
cache,
createPdfExportCacheKey({
...request,
exportConfig: {
...defaultExportConfig,
paper: {
...defaultExportConfig.paper,
orientation: "landscape"
}
}
})
)
).toBeUndefined();
});
it("命中缓存时复用同一个 PDF Blob 且不重复请求", async () => {
const request: PdfExportRequest = {
markdown: "# 测试",
fileName: "测试.md",
language: "zh-CN",
exportConfig: defaultExportConfig
};
const result = {
blob: new Blob(["%PDF-cached"]),
fileName: "测试.pdf",
pageCount: 1,
mermaidErrorCount: 0
};
const cache: CachedPdfExport = {
key: createPdfExportCacheKey(request),
result
};
const requester = vi.fn();
const resolved = await getOrRequestPdfExport(
request,
cache,
requester
);
expect(requester).not.toHaveBeenCalled();
expect(resolved).toEqual(cache);
expect(resolved.result.blob).toBe(result.blob);
});
it("缓存失效时请求并保存当前 PDF", async () => {
const request: PdfExportRequest = {
markdown: "# 新内容",
fileName: "测试.md",
language: "zh-CN",
exportConfig: defaultExportConfig
};
const result = {
blob: new Blob(["%PDF-new"]),
fileName: "测试.pdf",
pageCount: 2,
mermaidErrorCount: 0
};
const requester = vi.fn(async () => result);
const resolved = await getOrRequestPdfExport(
request,
undefined,
requester
);
expect(requester).toHaveBeenCalledOnce();
expect(resolved.key).toBe(createPdfExportCacheKey(request));
expect(resolved.result).toBe(result);
});
it("优先解析 UTF-8 下载文件名", () => {
expect(
parseContentDispositionFileName(
"attachment; filename=\"document.pdf\"; " +
"filename*=UTF-8''%E6%B5%8B%E8%AF%95.pdf"
)
).toBe("测试.pdf");
});
it("请求 PDF 并读取生成信息", async () => {
const fetcher = vi.fn(async () => {
return new Response(new Blob(["%PDF-test"]), {
status: 200,
headers: {
"content-type": "application/pdf",
"content-disposition":
"attachment; filename=\"document.pdf\"",
"x-pdf-page-count": "4",
"x-mermaid-error-count": "1"
}
});
});
const result = await requestPdfExport(
{
markdown: "# 测试",
fileName: "测试.md",
language: "zh-CN",
exportConfig: defaultExportConfig
},
fetcher
);
expect(fetcher).toHaveBeenCalledWith(
"/api/pdf",
expect.objectContaining({ method: "POST" })
);
expect(result.fileName).toBe("document.pdf");
expect(result.pageCount).toBe(4);
expect(result.mermaidErrorCount).toBe(1);
expect(await result.blob.text()).toBe("%PDF-test");
});
it("显示服务端返回的错误信息", async () => {
const fetcher = vi.fn(async () => {
return Response.json(
{ message: "PDF 生成队列已满" },
{ status: 503 }
);
});
await expect(
requestPdfExport(
{
markdown: "# 测试",
fileName: "测试.md",
language: "zh-CN",
exportConfig: defaultExportConfig
},
fetcher
)
).rejects.toThrow("PDF 生成队列已满");
});
});