aps-agent/apps/web/e2e/order-closed-loop-contract....

41 lines
1.9 KiB
TypeScript
Raw Normal View History

// Round 65 W4: closed-loop APS order/MRP frontend contract guard.
// Source-level by design: validates backward-compatible typing and no-fake-success UI copy
// without mutating a live APS world or requiring authentication.
import { expect, test } from '@playwright/test';
import { readFile } from 'node:fs/promises';
import path from 'node:path';
const webRoot = path.resolve(process.cwd());
test('订单面板消费 closedLoop 证据并明确六阶段门禁', async () => {
const source = await readFile(path.join(webRoot, 'src/orders/OrderPanel.tsx'), 'utf8');
expect(source).toContain('setClosedLoop(res.result?.closedLoop ?? null)');
for (const label of ['商务订单', 'BOM/供需净算', '制造需求准入', '排产草案', 'P2 发布', 'P3 MES']) {
expect(source).toContain(label);
}
expect(source).toContain('它们仍是制造需求,不是已释放生产订单');
expect(source).toContain('不会自动转采购');
expect(source).toContain('待独立确认');
expect(source).toContain('closed-loop-manufacturing-demands');
expect(source).toContain('closed-loop-blockers');
});
test('MRP 分解类型保持旧清单并可选扩展 closedLoop 契约', async () => {
const source = await readFile(path.join(webRoot, 'src/api/types.ts'), 'utf8');
expect(source).toContain('make: MakeSuggestion[];');
expect(source).toContain('purchase: PurchaseSuggestion[];');
expect(source).toContain('outsource: OutsourceSuggestion[];');
expect(source).toContain('closedLoop?: MrpClosedLoopDecomposition;');
for (const field of [
'problemId: string;', 'sourceHash: string;', 'businessDate: string;',
'summary: ClosedLoopSummary;', 'projection: ClosedLoopProjection;',
'manufacturingDemands: ClosedLoopManufacturingDemand[];',
'supplyEvents: ClosedLoopSupplyEvent[];', 'blockers: ClosedLoopBlocker[];',
'schedulingProblemV2: SchedulingProblemV2Projection;',
]) {
expect(source).toContain(field);
}
});