| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- import { test, expect } from '../fixtures/auth';
- import type { Page } from '@playwright/test';
- /**
- * B-02 遗留现场单页断言
- * 目标:验证 aidopdev 测试库中两条半提交现场依旧保留,详情页可加载,
- * 且核心不变量(ActiveFlowInstanceId、状态非已关闭)仍然成立。
- *
- * 不变量来源:memory/project_s8_b02_status.md(2026-04-20 快照)
- * - id=4:阶段 2 Approve 半提交 → ActiveFlowInstanceId=796353842065477
- * - id=29:阶段 3 Reject 半提交 → ActiveFlowInstanceId=796458502344773(EX-20260414-0003-RJ)
- */
- const SCENES = [
- { id: 4, expectedFlow: '796353842065477', label: 'B-02 阶段 2 Approve 半提交' },
- { id: 29, expectedFlow: '796458502344773', expectedCode: 'EX-20260414-0003-RJ', label: 'B-02 阶段 3 Reject 半提交' },
- ] as const;
- async function getToken(page: Page): Promise<string | null> {
- return page.evaluate(() => {
- for (let i = 0; i < localStorage.length; i++) {
- const k = localStorage.key(i)!;
- if (/access-token$/i.test(k) && !/x-access-token$/i.test(k)) {
- const raw = localStorage.getItem(k)!;
- try {
- const v = JSON.parse(raw);
- return typeof v === 'string' ? v : v?.value ?? raw;
- } catch {
- return raw;
- }
- }
- }
- return null;
- });
- }
- async function fetchDetail(page: Page, id: number) {
- const token = await getToken(page);
- expect(token, '未取到 access-token').toBeTruthy();
- const baseURL = new URL(page.url()).origin;
- const resp = await page.request.get(
- `${baseURL}/api/aidop/s8/exceptions/${id}?tenantId=1&factoryId=1`,
- { headers: { Authorization: `Bearer ${token}` } },
- );
- return { status: resp.status(), body: resp.ok() ? await resp.json() : null };
- }
- test.describe('S8-B02-LEGACY 遗留现场单页断言', () => {
- for (const scene of SCENES) {
- test(`id=${scene.id} ${scene.label}`, async ({ authedPage }) => {
- // 1) API 层:记录依然存在 + 关键不变量
- await authedPage.goto('/#/aidop/s8/exceptions', { waitUntil: 'domcontentloaded' });
- await authedPage.waitForLoadState('networkidle', { timeout: 15_000 }).catch(() => {});
- const { status, body } = await fetchDetail(authedPage, scene.id);
- test.info().annotations.push({
- type: 'api',
- description: `GET /exceptions/${scene.id} → HTTP ${status}`,
- });
- expect(status, `详情接口非 200,记录可能已被清理`).toBe(200);
- const data = body?.data ?? body;
- expect(data, '详情响应缺少数据').toBeTruthy();
- const activeFlow =
- data.activeFlowInstanceId ?? data.ActiveFlowInstanceId ?? data.flowInstanceId;
- const code = data.code ?? data.exceptionCode;
- const status8 = data.status ?? data.statusName;
- test.info().annotations.push({
- type: 'snapshot',
- description: JSON.stringify({ code, status: status8, activeFlow }),
- });
- expect(String(activeFlow ?? ''), '半提交现场必须仍持有 ActiveFlowInstanceId').toBe(
- scene.expectedFlow,
- );
- expect(String(status8 ?? ''), '半提交现场不应处于已关闭状态').not.toMatch(/已关闭|已取消/);
- if ('expectedCode' in scene && scene.expectedCode) {
- expect(String(code ?? '')).toBe(scene.expectedCode);
- }
- // 2) UI 层:详情页可正常打开
- await authedPage.goto(`/#/aidop/s8/exceptions/${scene.id}`, {
- waitUntil: 'domcontentloaded',
- });
- await authedPage.waitForLoadState('networkidle', { timeout: 15_000 }).catch(() => {});
- const errorBoundary = authedPage.locator('text=/页面加载失败|Error|未找到/').first();
- const errorVisible = await errorBoundary.isVisible().catch(() => false);
- expect(errorVisible, '详情页出现错误提示').toBeFalsy();
- const titleArea = authedPage.locator(
- 'h1, h2, h3, .el-page-header, .el-card__header, .header',
- );
- await expect(titleArea.first(), '详情页应渲染标题区').toBeVisible({ timeout: 10_000 });
- await authedPage.screenshot({
- path: `test-results/s8-b02-id-${scene.id}.png`,
- fullPage: true,
- });
- });
- }
- });
|