import { describe, expect, it } from "vitest"; import complexAssetCatalog from "../../apps/web/src/generated/complex-assets.json"; import { P0A_DYNAMIC_STICKERS } from "../../apps/web/src/dynamic-provider.js"; import { DYNAMIC_RENDER_MODELS } from "../../apps/web/src/dynamic-render-models.js"; import { P0A_COLOR_CARDS } from "../../apps/web/src/palette-provider.js"; import { P0A_FONT_OPTIONS, P0A_TEXT_TEMPLATES } from "../../apps/web/src/text-assets.js"; import { ninePatchSlices } from "../../apps/web/src/editor-stage.js"; import { P0A_COLOR_CARD_IDS, P0A_DYNAMIC_STICKER_IDS, P0A_REQUIRED_FONT_PANEL_IDS, P0A_TEXT_TEMPLATE_IDS, } from "../../packages/template-registry/src/index.js"; function containsAbsolutePath(value: unknown): boolean { if (typeof value === "string") return /^[A-Z]:[\\/]/i.test(value); if (Array.isArray(value)) return value.some(containsAbsolutePath); return value !== null && typeof value === "object" && Object.values(value).some(containsAbsolutePath); } describe("POSTV1-ASSET-ALL-16 complete asset catalog", () => { it("publishes every normalized complex asset instead of the original alpha subset", () => { expect(P0A_TEXT_TEMPLATE_IDS).toHaveLength(332); expect(P0A_TEXT_TEMPLATE_IDS[0]).toBe("FLOWER001"); expect(P0A_TEXT_TEMPLATE_IDS.at(-1)).toBe("SIMPLE017"); expect(P0A_REQUIRED_FONT_PANEL_IDS).toHaveLength(86); expect(P0A_REQUIRED_FONT_PANEL_IDS[0]).toBe("FONT001"); expect(P0A_REQUIRED_FONT_PANEL_IDS.at(-1)).toBe("FONT086"); expect(P0A_COLOR_CARD_IDS).toHaveLength(16); expect(P0A_COLOR_CARD_IDS[0]).toBe("COLOR001"); expect(P0A_COLOR_CARD_IDS.at(-1)).toBe("COLOR016"); expect(P0A_DYNAMIC_STICKER_IDS).toHaveLength(35); expect(P0A_DYNAMIC_STICKER_IDS[0]).toBe("DYN001"); expect(P0A_DYNAMIC_STICKER_IDS.at(-1)).toBe("DYN035"); }); it("generates a sanitized browser catalog for every text, font, and dynamic definition", () => { expect(complexAssetCatalog.schema_version).toBe("DadaComplexBrowserCatalog/v2"); expect(complexAssetCatalog.text_resource_revision).toMatch(/^[a-f0-9]{16}$/); expect(complexAssetCatalog.text_templates).toHaveLength(332); expect(complexAssetCatalog.font_panel_items).toHaveLength(86); expect(complexAssetCatalog.dynamic_stickers).toHaveLength(35); expect(complexAssetCatalog.text_templates.filter((item) => item.preview_asset_id)).toHaveLength(261); expect(complexAssetCatalog.text_templates.every((item) => item.available)).toBe(true); expect(complexAssetCatalog.text_templates.every((item) => item.render_model.text_layers.length > 0)).toBe(true); expect(complexAssetCatalog.text_templates.filter((item) => item.resource_class === "zip_template")).toHaveLength(330); expect(complexAssetCatalog.text_templates.reduce((count, item) => count + item.render_model.image_layers.length, 0)).toBe(316); expect(complexAssetCatalog.text_templates.reduce((count, item) => count + item.render_model.particle_layers.length, 0)).toBe(9); expect(complexAssetCatalog.text_templates.reduce((count, item) => count + item.render_model.text_layers.length, 0)).toBe(490); expect(complexAssetCatalog.text_templates.filter((item) => item.render_model.text_layers.some((layer) => "fill_pattern_asset_id" in layer))).toHaveLength(14); expect(containsAbsolutePath(complexAssetCatalog)).toBe(false); }); it("keeps the captured template font, default text, style, and decoration layers", () => { const byId = new Map(complexAssetCatalog.text_templates.map((item) => [item.template_id, item])); const flower001 = byId.get("FLOWER001")!; expect(flower001.default_font_id).toMatch(/^TEXT-FONT-FLOWER001-/); expect(flower001.font_match_status).toBe("template_package"); expect(flower001.render_model.image_layers).toHaveLength(1); expect(flower001.render_model.text_layers[0]).toMatchObject({ fill_color: "#FFC5D4", stroke_color: "#FF69A6", stroke_width: 5, }); const flower008 = byId.get("FLOWER008")!; expect(flower008.default_text).toBe("Vlog."); expect(flower008.default_font_id).toMatch(/^TEXT-FONT-FLOWER008-/); const heading001 = byId.get("H001")!; expect(heading001.render_model.image_layers).toHaveLength(5); expect(heading001.default_font_id).toMatch(/^TEXT-FONT-H001-/); const materialText = byId.get("FLOWER048")!; expect(materialText.render_model.text_layers[0]).toHaveProperty("fill_pattern_asset_id"); const underlinedText = byId.get("FLOWER121")!; expect(underlinedText.render_model.image_layers).toHaveLength(1); const particleText = byId.get("H013")!; expect(particleText.render_model.particle_layers).toHaveLength(3); const ninePatchLayers = complexAssetCatalog.text_templates.flatMap((item) => item.render_model.image_layers) .filter((layer) => "nine_patch" in layer); expect(ninePatchLayers.length).toBeGreaterThanOrEqual(100); expect(byId.get("FLOWER023")!.render_model.image_layers[0]).toMatchObject({ nine_patch: { bottom: 16, left: 53, right: 25, source_height: 63, source_width: 159, top: 12 }, }); expect(byId.get("H001")!.render_model.image_layers).toEqual(expect.arrayContaining([ expect.objectContaining({ anchor_x: 0 }), expect.objectContaining({ anchor_x: 1 }), ])); expect(byId.get("H079")!.render_model.text_layers.slice(0, 3).every((layer) => Math.abs(layer.rotation - 10) < 0.001)).toBe(true); expect(byId.get("FLOWER024")!.render_model.image_layers[0]).toMatchObject({ alpha: 0.4000000059604645 }); }); it("preserves nine-patch edges while stretching only the decoration center", () => { const slices = ninePatchSlices(231, 63, { bottom: 16, left: 53, right: 25, sourceHeight: 63, sourceWidth: 159, top: 12, }); expect(slices).toHaveLength(9); expect(slices[0]).toEqual({ destination: { height: 12, width: 53, x: 0, y: 0 }, source: { height: 12, width: 53, x: 0, y: 0 } }); expect(slices[4]).toEqual({ destination: { height: 35, width: 153, x: 53, y: 12 }, source: { height: 35, width: 81, x: 53, y: 12 } }); expect(slices[8]).toEqual({ destination: { height: 16, width: 25, x: 206, y: 47 }, source: { height: 16, width: 25, x: 134, y: 47 } }); }); it("exposes every generated definition to the editor", () => { expect(P0A_TEXT_TEMPLATES).toHaveLength(332); expect(P0A_TEXT_TEMPLATES.every((item) => item.available && item.fontUrl)).toBe(true); expect(P0A_FONT_OPTIONS).toHaveLength(86); expect(P0A_COLOR_CARDS).toHaveLength(16); expect(P0A_DYNAMIC_STICKERS).toHaveLength(35); expect(Object.keys(DYNAMIC_RENDER_MODELS)).toHaveLength(35); }); });