74 lines
3.1 KiB
TypeScript
74 lines
3.1 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import type { CanvasState } from "@dada/shared-contracts";
|
|
|
|
import { CanvasEditHistory } from "../../apps/web/src/editor-canvas.js";
|
|
import {
|
|
EXPORT_DIMENSIONS,
|
|
completePendingTextForExport,
|
|
resolveExportSettings,
|
|
sha256Blob,
|
|
} from "../../apps/web/src/export-compositor.js";
|
|
import { P0A_TEXT_TEMPLATES, TextEditSession, createTextTemplateElement } from "../../apps/web/src/text-assets.js";
|
|
|
|
function canvasWithText(): CanvasState {
|
|
return {
|
|
background: {
|
|
adjustments: { brightness: 0, contrast: 0, crop: null, filter: "none", fit: "fill", saturation: 0, sharpness: 0, temperature: 0 },
|
|
asset_id: null,
|
|
},
|
|
elements: [createTextTemplateElement(P0A_TEXT_TEMPLATES[0]!, {
|
|
createdAt: "2026-08-03T06:00:00.000Z",
|
|
elementId: "00000000-0000-4000-8000-000000000901",
|
|
}, 0)],
|
|
pixel_height: 1440,
|
|
pixel_width: 1080,
|
|
ratio: "3:4",
|
|
schema_version: 1,
|
|
};
|
|
}
|
|
|
|
describe("TASK-WP4-05 export compositor contract", () => {
|
|
it("freezes exact output pixels for all four ratios", () => {
|
|
expect(EXPORT_DIMENSIONS).toEqual({
|
|
"1:1": { height: 1080, width: 1080 },
|
|
"3:4": { height: 1440, width: 1080 },
|
|
"4:3": { height: 1080, width: 1440 },
|
|
"9:16": { height: 1920, width: 1080 },
|
|
});
|
|
});
|
|
|
|
it("uses JPG 92 by default, accepts only 80-100, and removes PNG quality", () => {
|
|
expect(resolveExportSettings({ format: "jpg", ratio: "3:4" })).toEqual({
|
|
format: "jpg", height: 1440, mimeType: "image/jpeg", quality: 92, width: 1080,
|
|
});
|
|
expect(resolveExportSettings({ format: "jpg", quality: 80, ratio: "1:1" }).quality).toBe(80);
|
|
expect(resolveExportSettings({ format: "jpg", quality: 100, ratio: "4:3" }).quality).toBe(100);
|
|
expect(resolveExportSettings({ format: "png", quality: 80, ratio: "9:16" })).toEqual({
|
|
format: "png", height: 1920, mimeType: "image/png", width: 1080,
|
|
});
|
|
expect(() => resolveExportSettings({ format: "jpg", quality: 79, ratio: "3:4" })).toThrowError("export_quality_invalid");
|
|
expect(() => resolveExportSettings({ format: "jpg", quality: 100.5, ratio: "3:4" })).toThrowError("export_quality_invalid");
|
|
});
|
|
|
|
it("turns one pending text draft into exactly one history operation", () => {
|
|
const before = canvasWithText();
|
|
const draftSession = new TextEditSession(before.elements[0]!, P0A_TEXT_TEMPLATES);
|
|
draftSession.setContent("待提交导出文字");
|
|
const draft = draftSession.value;
|
|
const history = new CanvasEditHistory(before);
|
|
|
|
const confirmed = completePendingTextForExport(before, draft);
|
|
history.commit(confirmed);
|
|
|
|
expect(confirmed.elements[0]?.content).toBe("待提交导出文字");
|
|
expect(before.elements[0]?.content).toBe("春日计划");
|
|
expect(history.undo()?.elements[0]?.content).toBe("春日计划");
|
|
expect(history.redo()?.elements[0]?.content).toBe("待提交导出文字");
|
|
});
|
|
|
|
it("hashes the exact Blob bytes used by download and latest persistence", async () => {
|
|
const blob = new Blob(["same-export-blob"], { type: "image/png" });
|
|
expect(await sha256Blob(blob)).toBe("ef710020af56830015263fa74537d28601fd0fb03f4a69d1cde63ff8722a9fd6");
|
|
});
|
|
});
|