Files
workinf_Blender_Wasm/web/tests/fixtures/console-main-workflow.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

42 lines
3.1 KiB
TypeScript

import { expect, type Page } from '@playwright/test';
import type { NativeMainReceipt } from '../../protocol/native-workflow';
export function finiteLocation(value: unknown): asserts value is [number, number, number] {
expect(Array.isArray(value)).toBe(true); expect(value).toHaveLength(3);
for (const coordinate of value as unknown[]) { expect(typeof coordinate).toBe('number'); expect(Number.isFinite(coordinate)).toBe(true); }
}
export async function latestMainReceipt(page: Page): Promise<NativeMainReceipt | null> {
const output = await page.locator('.native-workflow-output').textContent(); expect(typeof output).toBe('string');
const line = output!.split('\n').filter(value => value.startsWith('[MainReceipt] ')).at(-1);
if (!line) return null;
const value = JSON.parse(line.slice('[MainReceipt] '.length)) as NativeMainReceipt;
expect(value !== null && typeof value === 'object' && !Array.isArray(value)).toBe(true);
expect(typeof value.command).toBe('string'); expect(Number.isSafeInteger(value.sequence)).toBe(true); expect(value.sequence).toBeGreaterThanOrEqual(0);
expect(value.activeObject === null || value.activeObject === undefined || typeof value.activeObject === 'string').toBe(true);
expect(Array.isArray(value.objects)).toBe(true);
for (const object of value.objects) { expect(object !== null && typeof object === 'object').toBe(true); expect(typeof object.name).toBe('string'); finiteLocation(object.location); }
return value;
}
export async function receiptAfter(page: Page, action: () => Promise<unknown>, status = 'SUCCEEDED'): Promise<NativeMainReceipt> {
const previous = (await latestMainReceipt(page))?.sequence ?? -1;
await action();
await expect.poll(async () => (await latestMainReceipt(page))?.sequence ?? -1, { timeout: 30000 }).toBeGreaterThan(previous);
await expect(page.locator('.native-workflow-controls output')).toHaveText('READY');
await expect(page.locator('.native-session-panel')).toHaveAttribute('data-command-status', status);
return (await latestMainReceipt(page))!;
}
type WebMain = { requestId: string; revision: number; nodes: { name: string; type: string; transform: { translation: [number, number, number] } }[] };
export async function webMain(page: Page): Promise<WebMain> {
const value = await page.evaluate(() => (window as any).__nativeWorkflowMain) as WebMain;
expect(value !== null && typeof value === 'object').toBe(true); expect(typeof value.requestId).toBe('string');
expect(Number.isSafeInteger(value.revision)).toBe(true); expect(Array.isArray(value.nodes)).toBe(true);
for (const node of value.nodes) { expect(typeof node.name).toBe('string'); expect(typeof node.type).toBe('string'); finiteLocation(node.transform?.translation); }
return value;
}
export async function expectWebLocation(page: Page, name: string, expected: [number, number, number]) {
finiteLocation(expected);
for (let axis = 0; axis < 3; axis++) await expect.poll(async () => {
const node = (await webMain(page)).nodes.find(item => item.name === name); expect(node).toBeDefined();
return node!.transform.translation[axis];
}, { timeout: 30000 }).toBeCloseTo(expected[axis], 5);
}