import { describe, expect, it, vi, beforeEach } from "vitest"; import { render, screen, waitFor } from "@testing-library/react"; import { fireEvent } from "@testing-library/dom"; // خروجی قبلی کاغذِ [۲۱۰ × ارتفاعِ تصویر] می‌ساخت، یعنی ۲۱۰×۲۶۲٫۵ میلی‌متر. روی هیچ // پرینتری A4 حساب نمی‌شد. این تست همان قرارداد را قفل می‌کند: یک صفحهٔ A4. const jsPdfCalls = { ctor: [], addImage: [], save: [] }; vi.mock("jspdf", () => ({ default: class { constructor(options) { jsPdfCalls.ctor.push(options); } addImage(...args) { jsPdfCalls.addImage.push(args); } save(name) { jsPdfCalls.save.push(name); } }, })); vi.mock("html-to-image", () => ({ toPng: vi.fn(async () => "data:image/png;base64,AAAA"), })); vi.mock("html2canvas", () => ({ default: vi.fn() })); vi.mock("react-toastify", () => ({ toast: { info: vi.fn(), error: vi.fn(), success: vi.fn() }, })); // فونت وزیر با fetch به data-url تبدیل می‌شود؛ در jsdom باید تأمین شود وگرنه مسیر // جایگزینِ html2canvas اجرا می‌شود و تست چیز دیگری را می‌سنجد. vi.stubGlobal("fetch", vi.fn(async () => ({ blob: async () => new Blob(["x"]) }))); import List from "./List"; // پوستر A4 است: ۱۰۸۰×۱۵۲۷ فیزیکی، که با pixelRatio=2 دو برابر می‌شود. function posterRef({ width = 1080, height = 1527 } = {}) { const element = document.createElement("div"); Object.defineProperty(element, "offsetWidth", { value: width }); Object.defineProperty(element, "offsetHeight", { value: height }); element.querySelectorAll = () => []; return { current: element }; } async function download(ref) { render(); fireEvent.click(screen.getByLabelText("دانلود")); await waitFor(() => expect(jsPdfCalls.save.length).toBe(1)); } describe("PDF پوستر", () => { beforeEach(() => { jsPdfCalls.ctor = []; jsPdfCalls.addImage = []; jsPdfCalls.save = []; }); it("کاغذ A4 است، نه اندازه‌ای که از نسبت تصویر درمی‌آید", async () => { await download(posterRef()); expect(jsPdfCalls.ctor[0]).toMatchObject({ orientation: "portrait", unit: "mm", format: "a4", }); }); it("پوستر A4 کل صفحه را پر می‌کند و یک صفحه بیشتر نیست", async () => { await download(posterRef()); const [, , x, y, width, height] = jsPdfCalls.addImage[0]; expect(jsPdfCalls.addImage).toHaveLength(1); expect(width).toBeCloseTo(210, 1); expect(height).toBeCloseTo(297, 0); expect(x).toBeCloseTo(0, 1); expect(y).toBeCloseTo(0, 0); }); /** تور ایمنی: اگر ابعاد پوستر روزی بلندتر شد، تصویر باید کوچک شود نه اینکه از کاغذ بزند بیرون. */ it("پوستر بلندتر از A4 داخل کاغذ جا داده می‌شود، نه بریده", async () => { await download(posterRef({ width: 1080, height: 2000 })); const [, , x, y, width, height] = jsPdfCalls.addImage[0]; expect(height).toBeLessThanOrEqual(297); expect(width).toBeLessThanOrEqual(210); expect(x).toBeGreaterThan(0); expect(y).toBeCloseTo(0, 1); }); });