import { expect, test } from "@playwright/test"; import path from "node:path"; import { fileURLToPath } from "node:url"; const HERE = path.dirname(fileURLToPath(import.meta.url)); const ASSET_DIR = path.resolve(HERE, "../../../blender-5.2.0/tests/files/io_tests/blend_geometry"); const MATERIALS_PBR = path.join(ASSET_DIR, "materials_pbr.blend"); const TEXTURES = { "texture_checker.png": path.join(ASSET_DIR, "texture_checker.png"), "texture_illum.png": path.join(ASSET_DIR, "texture_illum.png"), "texture_roughness.png": path.join(ASSET_DIR, "texture_roughness.png"), }; test.use({ viewport: { width: 1600, height: 1000 } }); test.describe("PBR real asset production path", () => { test.setTimeout(240_000); test("reads PBR node/map bindings, packs external textures into OPFS and applies scene color management", async ({ page }) => { await page.goto("/?ui=web"); await page.locator('[data-testid="blend-file-input"]').setInputFiles(MATERIALS_PBR); await expect(page.locator(".blender-app")).toHaveAttribute("data-project-id", /.+/, { timeout: 60_000 }); await expect(page.getByText(/Engine: SceneIR/).first()).toBeVisible({ timeout: 60_000 }); const webTools = page.locator('[data-testid="native-web-tools-toggle"]'); if (await webTools.count()) await webTools.click(); await expect.poll(async () => page.locator("canvas[data-tone-mapping]").evaluateAll((nodes) => { const viewports = nodes .map((node) => node as HTMLCanvasElement) .filter((canvas) => Boolean(canvas.dataset.viewTransform)); if (!viewports.length) return false; return viewports.every((canvas) => { const view = canvas.dataset.viewTransform ?? ""; const tone = canvas.dataset.toneMapping ?? ""; if (/agx/i.test(view)) return tone === "agx"; if (/standard|raw/i.test(view)) return tone === "standard"; if (/neutral/i.test(view)) return tone === "neutral"; if (/aces|filmic/i.test(view)) return tone === "aces"; return false; }); }), { timeout: 30_000 }).toBe(true); await page.getByRole("button", { name: "Shading", exact: true }).click({ force: true }); await page.waitForTimeout(2_500); const external = page.locator(".wasm-shader-external"); await expect(external).toBeVisible({ timeout: 30_000 }); await expect(external.locator("label")).toHaveCount(3); await external.locator("summary").click(); await page.waitForTimeout(6_000); for (const [name, file] of Object.entries(TEXTURES)) { const label = external.locator("label").filter({ hasText: name }).first(); await expect(label).toBeVisible({ timeout: 15_000 }); const chooserPromise = page.waitForEvent("filechooser"); await label.locator('input[type="file"]').click(); const chooser = await chooserPromise; await chooser.setFiles(file); await expect(external.locator("label").filter({ hasText: name })).toHaveCount(0, { timeout: 30_000 }); } await expect(external.locator("label")).toHaveCount(0); await page.screenshot({ path: test.info().outputPath("pbr-materials.png"), fullPage: false }); }); });