f3a8a38acd
web-platform-ci / Standalone decision service (no cloud credentials) (push) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled
lekiwi-compatibility / cpu-compatibility (push) Has been cancelled
web-platform-ci / Standalone decision service (no cloud credentials) (pull_request) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (pull_request) Has been cancelled
web-platform-ci / Playwright E2E (pull_request) Has been cancelled
lekiwi-compatibility / cpu-compatibility (pull_request) Has been cancelled
集成同源 BYOK 会话隔离、精简模型设置、官方订阅入口和 HTTPS 发布运维;保留本地训练/调参与控制能力。同步 npm 版本及 CHANGELOG,记录公网真实 API 验收仍待用户凭据。
59 lines
2.7 KiB
TypeScript
59 lines
2.7 KiB
TypeScript
import { expect, test } from '@playwright/test';
|
|
import { resolve } from 'node:path';
|
|
import { writeFile } from 'node:fs/promises';
|
|
import type {} from '../physics/runner';
|
|
|
|
test('完整 314244 面三轮:真实 WASM、随轴运动、ZIP 重导与有界资源', async ({ page }, info) => {
|
|
const errors: string[] = [];
|
|
page.on('pageerror', (error) => errors.push(error.message));
|
|
await page.goto('/physics/runner.html');
|
|
await page.waitForFunction(() => Boolean(window.lekiwiPhysics));
|
|
await page.evaluate((path) => window.lekiwiPhysics.boot(path), `/@fs${resolve('build/lekiwi')}`);
|
|
try {
|
|
const before = await page.evaluate(() => window.lekiwiPhysics.visualStats());
|
|
// The three original filenames contain identical bytes; one content-addressed
|
|
// OBJ is shared by three independent visual instances.
|
|
expect(before.generatedMeshes).toHaveLength(1);
|
|
expect(before.wheels).toHaveLength(3);
|
|
for (const wheel of before.wheels) {
|
|
expect(wheel.faces).toBe(314244);
|
|
expect(wheel.vertices).toBeGreaterThan(150000);
|
|
expect(wheel.centerError).toBeLessThan(1e-6);
|
|
expect(wheel.scale).toEqual([0.001, 0.001, 0.001]);
|
|
expect(wheel.collision).toBe(false);
|
|
expect(wheel.mass).toBe(0);
|
|
}
|
|
await page.evaluate(() => window.lekiwiPhysics.drive(0, 0.1, 0, 0.25));
|
|
const after = await page.evaluate(() => window.lekiwiPhysics.visualStats());
|
|
for (let i = 0; i < 3; i++) {
|
|
expect(after.wheels[i].centerError).toBeLessThan(1e-6);
|
|
expect(
|
|
after.wheels[i].rotation.some((v, j) => Math.abs(v - before.wheels[i].rotation[j]) > 0.01),
|
|
).toBe(true);
|
|
}
|
|
const traces: Awaited<ReturnType<typeof window.lekiwiPhysics.packageRoundtrip>>[] = [];
|
|
for (let i = 0; i < 8; i++) {
|
|
const result = await page.evaluate(() => window.lekiwiPhysics.packageRoundtrip());
|
|
expect(result.oldModelDeleted).toBe(true);
|
|
expect(result.oldDataDeleted).toBe(true);
|
|
expect(result.workspaces).toHaveLength(1);
|
|
expect(result.generatedMeshes).toHaveLength(1);
|
|
expect(result.wheels.every((wheel) => wheel.faces === 314244 && !wheel.collision)).toBe(true);
|
|
traces.push(result);
|
|
}
|
|
console.log(
|
|
'mesh resources',
|
|
traces.map((t) => ({ heap: t.heap, bytes: t.projectBytes, xml: t.xmlFiles })),
|
|
);
|
|
await writeFile(
|
|
info.outputPath('full-mesh-roundtrip.json'),
|
|
JSON.stringify({ before, after, traces }, null, 2),
|
|
);
|
|
expect(traces.every((t) => t.projectBytes === traces[0].projectBytes)).toBe(true);
|
|
expect(traces[7].heap).toBeLessThanOrEqual(traces[5].heap + 32 * 1024 * 1024);
|
|
expect(errors).toEqual([]);
|
|
} finally {
|
|
await page.evaluate(() => window.lekiwiPhysics.dispose());
|
|
}
|
|
});
|