import { expect, test } from "@playwright/test"; import { starterSchema } from "../src/app/starter-schema"; import { expectExportExcludesCanvasHandles, expectNoForbiddenCanvasUi, } from "./canvas-handle-helpers"; import { expectToolcraftProductObservableToChange, getToolcraftProductObservableSnapshot, } from "./product-observable-helpers"; test("browser renders the Toolcraft template shell instead of a reference iframe shell", async ({ page, }) => { await page.goto("/"); await expect(page.locator('[data-slot="toolcraft-runtime-app"]')).toBeVisible(); if (starterSchema.assembly.surfaces.canvas.enabled) { await expect(page.getByRole("application", { name: "Canvas viewport" })).toBeVisible(); } const nonCanvasIframeCount = await page.evaluate( () => Array.from(document.querySelectorAll("iframe")).filter( (frame) => !frame.closest("[data-toolcraft-canvas-slot]"), ).length, ); expect( nonCanvasIframeCount, "Reference iframes may not replace the Toolcraft shell. Preserve reference output inside ToolcraftApp canvasContent.", ).toBe(0); }); test("browser preserves the Toolcraft canvas backing surface", async ({ page }) => { if (!starterSchema.assembly.surfaces.canvas.enabled) { return; } await page.goto("/"); const canvasViewport = page.getByRole("application", { name: "Canvas viewport" }); await expect(canvasViewport).toBeVisible(); const backgroundColor = await canvasViewport.evaluate((element) => window.getComputedStyle(element).backgroundColor, ); expect( backgroundColor, "The runtime CanvasShell backing must stay visible. Product renderers may customize their own output background, but they must not hide or make the workspace shell transparent.", ).not.toMatch(/^(?:transparent|rgba?\(\s*0\s*,\s*0\s*,\s*0\s*,\s*0\s*\))$/i); }); test("browser canvas contains product output without app UI controls or CTA copy", async ({ page, }) => { if (!starterSchema.assembly.surfaces.canvas.enabled) { return; } await page.goto("/"); await expect(page.getByRole("application", { name: "Canvas viewport" })).toBeVisible(); await expectNoForbiddenCanvasUi(page); }); test("product observable helper catches changed and unchanged output", async ({ page }) => { await page.setContent(`