Files
workinf_Blender_Wasm/web/tests/e2e/pbr-asset-library-production.spec.ts
mes123456 d5dd647881
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled
feat(web): finish RE 5000PBR lesson video and fix non-ASCII GLB import
- Add 11:07 Chinese-narrated lesson video, VTT, poster and 13 chapter screenshots.
- Regenerate 20-render WebGL2 matrix and 15 operation captures on RTX 4060.
- Fix WASM staging for non-ASCII import filenames (猴头.glb); rebuild web_engine.
- Harden lesson video recording pipeline; fix stale lesson-link E2E selector.
- Add RE PBR derived libraries, lesson page, evidence and status report.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-11-12 21:49:24 +08:00

78 lines
3.8 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 PBR_FIXTURE = path.resolve(HERE, "../../../tests/files/web/m12_glb_main_v1/pbr.blend");
test.use({ viewport: { width: 1600, height: 1000 } });
const objectCount = async (page: import("@playwright/test").Page): Promise<number> => {
const text = await page.getByTestId("scene-stats").innerText();
return Number(/Objects (\d+)/.exec(text)?.[1] ?? "0");
};
async function openShading(page: import("@playwright/test").Page) {
await page.goto("/?ui=web");
await page.locator('[data-testid="blend-file-input"]').setInputFiles(PBR_FIXTURE);
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 page.getByRole("button", { name: "Shading", exact: true }).click({ force: true });
await expect(page.locator(".pbr-asset-library")).toBeVisible({ timeout: 30_000 });
await expect(page.locator(".pbr-asset-card")).toHaveCount(20, { timeout: 60_000 });
}
test("PBR asset library seeds OPFS, appends a model, assigns a material and renders", async ({ page }) => {
test.setTimeout(300_000);
await openShading(page);
await expect.poll(async () => page.locator(".pbr-asset-thumb img").evaluateAll((images) =>
images.filter((image) => (image as HTMLImageElement).naturalWidth > 0).length), { timeout: 30_000 }).toBe(20);
const before = await objectCount(page);
await page.locator(".pbr-asset-card", { hasText: "PBR Cube" }).first().dblclick();
await expect.poll(() => objectCount(page), { timeout: 30_000 }).toBeGreaterThan(before);
await page.locator(".pbr-asset-card", { hasText: "PBR Metal Brushed" }).first().dblclick();
await expect.poll(async () => page.locator('select[aria-label^="材质槽"]').first().inputValue(), { timeout: 30_000 })
.toBe("material:PBR Metal Brushed");
await expect.poll(async () => page.locator(".material-preview-status").innerText(), { timeout: 30_000 }).toContain("COMPILED");
await page.getByRole("button", { name: "Rendering", exact: true }).click();
await page.getByRole("button", { name: "渲染 PBR", exact: true }).click();
await expect.poll(async () => page.locator(".pbr-render-result img").count(), { timeout: 90_000 }).toBe(1);
await expect.poll(async () => page.locator(".pbr-render-result img").first().evaluate((image) =>
(image as HTMLImageElement).naturalWidth), { timeout: 30_000 }).toBeGreaterThan(0);
});
test("seeded PBR asset catalog and previews survive a page reload", async ({ page }) => {
test.setTimeout(240_000);
await openShading(page);
await page.reload();
await expect(page.locator(".blender-app")).toBeVisible({ timeout: 60_000 });
const persisted = await page.evaluate(async () => {
const { StorageClient } = await import("/src/storage/StorageClient.ts");
const client = new StorageClient();
try {
const catalog = await client.getAssetCatalog();
const preview = catalog.manifest?.assets.find((asset) => asset.preview)?.preview;
const bytes = preview ? await client.readAssetCatalogPreview("asset-library", preview.sha256) : null;
return {
assets: catalog.manifest?.assets.length ?? 0,
revision: catalog.manifest?.revision ?? 0,
seedId: catalog.seed?.seedId ?? "",
previewBytes: bytes?.data.byteLength ?? 0,
};
}
finally {
client.terminate();
}
});
expect(persisted.assets).toBe(20);
expect(persisted.seedId).toBe("pbr-essentials-v1");
expect(persisted.previewBytes).toBeGreaterThan(0);
});