import { expect, test } from "@playwright/test"; import fs from "node:fs"; import path from "node:path"; const root = path.resolve(import.meta.dirname, "../../.."); const expected = JSON.parse(fs.readFileSync(path.join(root, "tests/golden/M10-09/shader-pipeline.json"), "utf8")); test("M10-09 keeps the previous material pipeline after compile failure", async ({ page }) => { await page.goto("/"); const result = await page.evaluate(async () => { const { PBRMaterialPipeline } = await import("/src/three-adapter/pbr.ts"); const valid = { id: "material:pipeline", name: "Pipeline", baseColor: [0.2, 0.3, 0.4, 1] as [number, number, number, number], roughness: 0.5, metallic: 0, emissionColor: [0, 0, 0, 1] as [number, number, number, number], alpha: 1, ior: 1.45, nodes: [ { id: "principled", type: "PRINCIPLED" as const, name: "Principled" }, { id: "output", type: "OUTPUT" as const, name: "Output" }, ], links: [{ fromNodeId: "principled", fromSocket: "BSDF", toNodeId: "output", toSocket: "Surface" }], }; const invalid = { ...valid, nodes: [{ id: "mix", type: "UNSUPPORTED" as const, name: "Mix" }, ...valid.nodes] }; const pipeline = new PBRMaterialPipeline(); const first = pipeline.update(valid); const failed = pipeline.update(invalid); const preserved = failed.material === first.material; const failureReport = first.material.userData.shaderCompileFailure; const replacement = pipeline.update({ ...valid, baseColor: [0.8, 0.2, 0.1, 1] }); const replaced = replacement.material !== first.material; const oldDisposed = first.material.userData.shaderCompile?.status !== "COMPILED"; pipeline.dispose(); return { first: first.report?.status, failure: failed.report?.status, preserved, failureCode: failureReport?.issues?.[0]?.code, replaced, replacedOnSuccess: replacement.replaced, oldPipelineStillCompiled: !oldDisposed, }; }); expect(result).toEqual({ first: "COMPILED", failure: expected.failureStatus, preserved: expected.preservedPipeline, failureCode: "SHADER_NODE_UNSUPPORTED", replaced: true, replacedOnSuccess: expected.replacedOnSuccess, oldPipelineStillCompiled: expected.failureDoesNotDisposePrevious, }); });