/** * v1.8.2 — ERROR_STEP_BY_PHASE 补 BATCH_EXECUTE + SYNC_EXPORT 2 key 回归测试 * * 修 v1.5.0 设计塌方残留: * ErrorPhase type (18 值) 含 BATCH_EXECUTE + SYNC_EXPORT * ERROR_STEP_BY_PHASE map (旧 16 key) 漏这 2 key * Edge VALID_ERROR_PHASES 派生自 map 也缺, 设备端合法 wire 被误判 TOLERATED * * v1.8.2 修复后, 设备端 commit c9bdc03 (BATCH 子项 _FAILED data.error.phase= * BATCH_EXECUTE, step=DataTransfer) 应在 Edge 走 STRICT 通过, 不再 TOLERATED * * 设计文档: * - Round 9'' reply: protocol-team-reply-to-batch-execute-gap-v1.8.1.md * - Round 10'' ack: device-team-final-ack-v1.8.1.md */ import { ERROR_STEP_BY_PHASE, isValidErrorStepForPhase } from '../index'; // 注意: ErrorPhase type 是 string union (type 不是 value), 测试中用 string literal 等效 describe('v1.8.2 — ERROR_STEP_BY_PHASE BATCH_EXECUTE + SYNC_EXPORT 补 key', () => { describe('1. BATCH_EXECUTE step 合法性', () => { test('DataTransfer 应属 BATCH_EXECUTE phase (设备端 commit c9bdc03 实证 wire)', () => { expect(isValidErrorStepForPhase('DataTransfer', 'BATCH_EXECUTE')).toBe(true); }); test('SubItemTimeout 应属 BATCH_EXECUTE phase (v1.8.2 新增)', () => { expect(isValidErrorStepForPhase('SubItemTimeout', 'BATCH_EXECUTE')).toBe(true); }); test('SubItemDeviceQuery 应属 BATCH_EXECUTE phase (v1.8.2 新增)', () => { expect(isValidErrorStepForPhase('SubItemDeviceQuery', 'BATCH_EXECUTE')).toBe(true); }); test('未列入的 step (e.g. CheckConcurrency) 应不属 BATCH_EXECUTE', () => { expect(isValidErrorStepForPhase('CheckConcurrency', 'BATCH_EXECUTE')).toBe(false); }); }); describe('2. SYNC_EXPORT step 合法性', () => { test('ReadDayData 应属 SYNC_EXPORT phase (v1.8.2 新增)', () => { expect(isValidErrorStepForPhase('ReadDayData', 'SYNC_EXPORT')).toBe(true); }); test('AggregateExport 应属 SYNC_EXPORT phase (v1.8.2 新增)', () => { expect(isValidErrorStepForPhase('AggregateExport', 'SYNC_EXPORT')).toBe(true); }); test('未列入的 step (e.g. Download) 应不属 SYNC_EXPORT', () => { expect(isValidErrorStepForPhase('Download', 'SYNC_EXPORT')).toBe(false); }); }); describe('3. enum 镜像一致性 (v1.9.0 detection 族命名空间统一)', () => { test('ErrorPhase type 18 值应全在 ERROR_STEP_BY_PHASE map 内', () => { // v1.9.0: detection 7 phase 加 QUICK_DETECTION_ 前缀 const errorPhaseValues = [ 'PROGRAM_INIT', 'PROGRAM_FETCH', 'PROGRAM_EXTRACT', 'PROGRAM_PREPROCESS', 'PROGRAM_COMPILE', 'PROGRAM_UPLOAD', 'PROGRAM_STATS', 'PROGRAM_COMPLETE', 'QUICK_DETECTION_INIT', 'QUICK_DETECTION_SWITCH_DETECT', 'QUICK_DETECTION_SWITCH_CONFIG_READ', 'QUICK_DETECTION_SYNC_DETECT', 'QUICK_DETECTION_BARGRAPH_DETECT', 'QUICK_DETECTION_SYNC_RECOVER', 'QUICK_DETECTION_COMPLETE', 'SYNC_EXPORT', 'BATCH_EXECUTE', 'EDGE_PROXY', ]; const mapKeys = Object.keys(ERROR_STEP_BY_PHASE); for (const phase of errorPhaseValues) { expect(mapKeys).toContain(phase); } // 数量也对齐: 18 type 值 == 18 map key expect(mapKeys.length).toBe(errorPhaseValues.length); }); test('ERROR_STEP_BY_PHASE 每个 key 至少含 1 个 step (v1.10.0: 只 PROGRAM_STATS 是空 step, PROGRAM_COMPLETE/QUICK_DETECTION_COMPLETE 已镜像加 Wrapup)', () => { for (const [phase, steps] of Object.entries(ERROR_STEP_BY_PHASE)) { expect(Array.isArray(steps)).toBe(true); // v1.9.0: QUICK_DETECTION_COMPLETE 加 DetectionWrapup // v1.10.0 §1: PROGRAM_COMPLETE 加 ProgramWrapup (镜像 invariant) // 仅 PROGRAM_STATS 仍空 (云端 RabbitMQ 通道下线后无失败 step) const allowEmpty = ['PROGRAM_STATS']; if (!allowEmpty.includes(phase)) { expect(steps.length).toBeGreaterThan(0); } } }); }); describe('4. v1.5.0 已有 PROGRAM_UPLOAD step 兼容性回归 (v1.8.2 不动)', () => { test('PROGRAM_UPLOAD step 全 5 个仍合法 (DeviceCheck/DataTransfer/ForbiddenTable/StatusRecovery/RetryLimitExceeded)', () => { const steps = ['DeviceCheck', 'DataTransfer', 'ForbiddenTable', 'StatusRecovery', 'RetryLimitExceeded']; for (const s of steps) { expect(isValidErrorStepForPhase(s, 'PROGRAM_UPLOAD')).toBe(true); } }); }); describe('5. v1.8.2 修复实证 — 设备端 commit c9bdc03 wire 应通过', () => { test('设备端 BARGRAPH BATCH 子项 _FAILED data.error 应全字段合法', () => { // 设备端 commit c9bdc03 wire 实证 (Round 9'' §1): // data.error = { phase: 'BATCH_EXECUTE', step: 'DataTransfer', // category: 'TRANSPORT', detail: 'CAN bus...' } expect(isValidErrorStepForPhase('DataTransfer', 'BATCH_EXECUTE')).toBe(true); // 这条 wire 在 v1.8.1 是 ⚠️ TOLERATED (map drift), v1.8.2 后应 STRICT 通过 }); }); });