Files
workinf_Blender_Wasm/web/tests/e2e/mesh-lod-reader-production.spec.ts
mes123456 f3e21c6b98
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
chore: checkpoint web Blender migration source, tools and docs
Accumulated uncommitted work: GHOST Web backend, WebGL/GPU web layer,
web workflow engine and protocol, tooling, docs and task records.
Large generated evidence, user-testing archives, build snapshots and
imported test assets remain untracked.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-11-10 11:18:01 +08:00

35 lines
4.0 KiB
TypeScript

import { test, expect } from '@playwright/test';
import fs from 'node:fs';
import path from 'node:path';
import crypto from 'node:crypto';
import type { WebEngineLODResult } from '../../protocol/web-engine';
const root = path.resolve(import.meta.dirname, '../../..');
const baseline = path.join(root, 'tests/golden/WBV2-P1424-001/lod-current-main-20261021');
const evidence = process.env.WBV2_EVIDENCE_DIR ?? baseline;
const candidate = process.env.WBV2_PRODUCTION_CANDIDATE ?? path.join(root, 'web/dist');
const hash = (file: string) => crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex');
test('concave reader uses native desktop triangulation', async ({ page, browser }) => {
const oracle = JSON.parse(fs.readFileSync(path.join(baseline, 'desktop-concave.json'), 'utf8'));
const fixture = path.join(root, oracle.fixture); expect(hash(fixture)).toBe(oracle.fixtureSha256);
const record = { started: Date.now(), chrome: browser.version(), viewport: page.viewportSize(), fixture: oracle.fixture, fixtureSha256: hash(fixture), failures: [] as string[], consoleErrors: [] as string[], modules: [] as { url: string; sha256: string }[], isolated: false, observed: null as unknown };
page.on('requestfailed', request => record.failures.push(`${request.url()}: ${request.failure()?.errorText}`));
page.on('request', request => { if (new URL(request.url()).pathname.startsWith('/src/')) record.failures.push(`NON_PRODUCTION_SOURCE ${request.url()}`); });
page.on('console', message => { if (message.type() === 'error') record.consoleErrors.push(message.text()); }); page.on('pageerror', error => record.consoleErrors.push(error.message));
page.on('response', response => { const url = new URL(response.url()).pathname; if (response.status() >= 400) record.failures.push(`${response.status()} ${url}`); if (/\.wasm$|wasm-module-manifest\.json$/.test(url)) record.modules.push({ url, sha256: hash(path.join(candidate, url)) }); });
let passed = false;
try {
await page.addInitScript(() => { const Native = window.Worker; window.Worker = class extends Native { constructor(url: string | URL, options?: WorkerOptions) { super(url, options); this.addEventListener('message', ({ data }) => { if (data.result?.lod) (window as unknown as { __concaveLOD: unknown }).__concaveLOD = data.result.lod; }); } }; });
await page.goto('/?ui=web'); record.isolated = await page.evaluate(() => crossOriginIsolated); expect(record.isolated).toBe(true);
await page.getByTestId('blend-file-input').setInputFiles(fixture);
await expect(page.getByText('ConcaveNotch', { exact: true })).toBeVisible({ timeout: 60_000 });
const before = await page.getByTestId('scene-stats').textContent(); await page.getByRole('button', { name: '生成 LOD' }).click();
await expect(page.getByTestId('engine-status')).toContainText('cache ready', { timeout: 90_000 });
const observed = await page.evaluate(() => { const lod = (window as unknown as { __concaveLOD: WebEngineLODResult }).__concaveLOD; return { revision: lod.manifest.sourceMeshRevision, unavailable: lod.errors?.length ?? 0, levels: lod.levels.map(level => ({ triangles: level.outputTriangleCount, positions: Array.from(new Float32Array(level.geometryBuffers[0].positions)), indices: Array.from(new Uint32Array(level.geometryBuffers[0].indices)) })) }; });
record.observed = observed; expect(observed.levels).toHaveLength(1);
expect(observed.levels[0]).toEqual({ triangles: oracle.triangles, positions: oracle.positions, indices: oracle.indices });
expect(observed.unavailable).toBe(2); await expect(page.getByTestId('engine-status')).toContainText('2 unavailable level(s)');
expect(await page.getByTestId('scene-stats').textContent()).toBe(before);
expect(record.failures).toEqual([]); expect(record.consoleErrors).toEqual([]); passed = true;
} finally { fs.writeFileSync(path.join(evidence, `${record.started}-concave-reader.json`), JSON.stringify({ ...record, passed, exitCode: passed ? 0 : 1, durationMs: Date.now() - record.started, testSourceSha256: hash(import.meta.filename) }, null, 2)); }
});