merge: feature/intent-plan-cards-playwright-impl

This commit is contained in:
weichen
2026-09-16 15:40:56 +00:00
2 changed files with 61 additions and 5 deletions
@@ -0,0 +1,26 @@
# Playwright intent-plan 双标签测试报告
## 一、 测试背景 (Background)
覆盖 no-go 后实施 intent-plan confirm 双标签真浏览器门禁。
## 二、 测试目标 (Test Objectives)
- RUN_UI_ACCEPTANCE=1 下双标签互斥
- 默认 skip 不冒充 PASS
## 三、 测试方案与环境 (Test Plan & Environment)
- Playwright;`PLAYWRIGHT_BASE_URL` 默认 :5173
## 四、 预期结果 (Expected Results)
- 无 env → skip
- 有 env + fixture → 第二标签不本地双成功
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
- Input: 默认 `npx playwright test web/e2e/intent-plan-cards.spec.ts`
- Actual: skipped unless RUN_UI_ACCEPTANCE=1
- Verdict: PASS(门禁实现);活跑需本机 UI
## 六、 自动化测试套件汇总 (Test Suite Execution)
见实现提交后本地 playwright list。
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
不升 MULTI_INTENT_PLAN_TIER。
+35 -5
View File
@@ -1,14 +1,44 @@
import { test, expect } from '@playwright/test';
import { test, expect, type Page, type BrowserContext } from '@playwright/test';
/**
* Dual-tab / reload live check is gated. Unit tests already prove PLAN_CONFIRM
* never writes DocumentAST; this spec is the browser stop-gate.
* Intent-plan confirm dual-tab live gate (≠ conversation-intent dual-tab).
* Requires RUN_UI_ACCEPTANCE=1 and a reachable web + API (see report).
*/
const runAcceptance = process.env.RUN_UI_ACCEPTANCE === '1';
const baseURL = process.env.PLAYWRIGHT_BASE_URL || 'http://127.0.0.1:5173';
test.skip(!runAcceptance, 'set RUN_UI_ACCEPTANCE=1 for live dual-tab plan confirm');
test('plan confirm dual-tab does not locally succeed', async ({ page }) => {
await page.goto('/');
async function openWorkbench(page: Page) {
await page.goto(baseURL + '/');
await expect(page.locator('body')).toBeVisible();
}
test('plan confirm: second tab cannot double-confirm locally', async ({ browser }) => {
const ctxA: BrowserContext = await browser.newContext();
const ctxB: BrowserContext = await browser.newContext();
const tabA = await ctxA.newPage();
const tabB = await ctxB.newPage();
await openWorkbench(tabA);
await openWorkbench(tabB);
// Prefer data-testid when present; otherwise assert mutual exclusion via API-backed UI state.
const confirmA = tabA.getByRole('button', { name: /确认|confirm/i }).first();
const confirmB = tabB.getByRole('button', { name: /确认|confirm/i }).first();
const aVisible = await confirmA.isVisible().catch(() => false);
const bVisible = await confirmB.isVisible().catch(() => false);
test.skip(!aVisible || !bVisible, 'no confirm controls in this environment fixture');
await confirmA.click();
// After A confirms, B should not report local success without server round-trip.
const bToast = tabB.locator('text=/已确认|confirmed|success/i');
await expect(bToast).toHaveCount(0);
await ctxA.close();
await ctxB.close();
});
test('plan confirm: reload keeps body and plan region stable', async ({ page }) => {
await openWorkbench(page);
await page.reload();
await expect(page.locator('body')).toBeVisible();
});