51 lines
2.5 KiB
TypeScript
51 lines
2.5 KiB
TypeScript
// 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);
|
|
}
|
|
});
|
|
|
|
test('订单选择展示关联产物并在主世界刷新后补拉订单数据', async () => {
|
|
const source = await readFile(path.join(webRoot, 'src/orders/OrderPanel.tsx'), 'utf8');
|
|
|
|
expect(source).toContain('data-testid="order-linked-detail"');
|
|
expect(source).toContain('onClick: () => setSelectedId(o.id)');
|
|
expect(source).toContain('采购或委外为 0 可能是库存覆盖或未配置外协,并非刷新失败');
|
|
expect(source).toContain('worldRefreshRef.current = props.onWorldRefresh');
|
|
expect(source).toContain("setView('make')");
|
|
});
|