Files
Mujoco_WASM/web_platform/e2e/lekiwi.agent.workspace.spec.ts
T
chenlin 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
feat: release v1.0.1 CADWorld 网站与 LeKiwi 智能抓放
集成同源 BYOK 会话隔离、精简模型设置、官方订阅入口和 HTTPS 发布运维;保留本地训练/调参与控制能力。同步 npm 版本及 CHANGELOG,记录公网真实 API 验收仍待用户凭据。
2026-09-24 09:57:41 +08:00

71 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { expect, test } from '@playwright/test';
import { resolve } from 'node:path';
import { readFile, writeFile } from 'node:fs/promises';
test('主工作台:A 导入、mock 单技能暂停/继续、物理成功及证据导出', async ({ page }, info) => {
const errors: string[] = [];
let modelRequests = 0;
page.on('pageerror', (e) => errors.push(e.message));
page.on('request', (r) => {
if (/\/api\/decision\/v1\/(plan|decide)$/.test(r.url())) modelRequests++;
});
await page.goto('/');
await page
.locator('input[type="file"]')
.first()
.setInputFiles(resolve('build/lekiwi/lekiwi-v1.zip'));
const dialog = page.getByRole('dialog', { name: '配置 URDF 仿真组件' });
await expect(dialog).toBeVisible({ timeout: 30000 });
await dialog.getByLabel('URDF 机器人 profile').selectOption('lekiwi-v1');
await dialog.getByRole('button', { name: '转换并加载' }).click();
await expect(page.getByRole('button', { name: '▶ 播放' })).toBeEnabled({ timeout: 60000 });
await page.getByRole('tab', { name: '控制台', exact: true }).click();
await page.getByRole('button', { name: 'LeKiwi 智能抓放', exact: true }).click();
const panel = page.getByLabel('LeKiwi 智能抓放任务', { exact: true });
await expect(panel).toContainText('MOCK(不调用模型 API)');
await panel.getByRole('button', { name: '加载 A 任务场景', exact: true }).click();
await expect(panel).toContainText('A 抓放场景已加载并暂停', { timeout: 60000 });
await panel.getByRole('button', { name: '单技能步进', exact: true }).click();
const status = panel.getByTestId('agent-task-state');
await expect(status).toContainText('任务已暂停', { timeout: 60000 });
await expect(status).toContainText('当前技能:open');
await expect(status).toContainText('Jev 1/60');
await panel.getByRole('button', { name: '继续任务', exact: true }).click();
await expect(status).toContainText('物理验收成功', { timeout: 180000 });
await expect(status).toContainText('Jev 11/60');
const download = page.waitForEvent('download');
await panel.getByRole('button', { name: '导出任务证据', exact: true }).click();
const downloaded = await download;
const evidence = JSON.parse(await readFile((await downloaded.path())!, 'utf8'));
await writeFile(
info.outputPath('workbench-physical-evidence.json'),
JSON.stringify(evidence, null, 2),
);
expect(evidence.mode).toBe('mock');
expect(evidence.succeeded).toBe(true);
expect(evidence.transported).toBeGreaterThanOrEqual(0.5);
expect(evidence.sample.onGoalSupport).toBe(true);
expect(modelRequests).toBe(0);
expect(errors).toEqual([]);
await page.screenshot({ path: info.outputPath('agent-workbench.png') });
await panel.getByRole('button', { name: '重置任务场景', exact: true }).click();
await expect(panel.getByTestId('agent-task-state')).toHaveCount(0, { timeout: 60000 });
await panel.getByLabel('目标 Y', { exact: true }).fill('0.617');
await panel.getByRole('button', { name: '单技能步进', exact: true }).click();
await expect(status).toContainText('任务已暂停', { timeout: 60000 });
const changedDownload = page.waitForEvent('download');
await panel.getByRole('button', { name: '导出任务证据', exact: true }).click();
const changed = JSON.parse(await readFile((await (await changedDownload).path())!, 'utf8'));
expect(changed.goal).toEqual([0.257, 0.617, 0.128]);
expect(changed.runId).not.toBe(evidence.runId);
expect(changed.sample.time).toBeLessThan(2.01);
expect(changed.sample.object[1]).toBeLessThan(0.02); // New source episode, not the old placed cube.
await writeFile(info.outputPath('edited-goal-episode.json'), JSON.stringify(changed, null, 2));
await panel.getByLabel('目标 Y', { exact: true }).fill('0.615');
await expect(status).toContainText('已取消');
await expect(status).toContainText('目标编辑使旧计划失效');
expect(modelRequests).toBe(0);
expect(errors).toEqual([]);
await expect(page.getByRole('button', { name: '强化学习任务', exact: true })).toBeVisible();
});