- update native web_engine sources and rebuilt wasm artifacts - add task cards, status notes and tooling scripts - add web e2e specs, tutorial UI sources and tutorial assets - sync golden task manifests and audit records Co-Authored-By: Claude Code <noreply@anthropic.com>
64 lines
3.1 KiB
TypeScript
64 lines
3.1 KiB
TypeScript
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 });
|
|
});
|
|
});
|