feat(operations): support canonical source providers
This commit is contained in:
@@ -173,3 +173,57 @@ test('fuzzy searches a vehicle and renders all source diagnosis evidence', async
|
||||
}));
|
||||
await waitFor(() => expect(mocks.vehicleSourceDiagnostic).toHaveBeenCalledWith('VIN001', expect.any(AbortSignal)));
|
||||
});
|
||||
|
||||
test('allows provider maintenance but keeps canonical source policy read only', async () => {
|
||||
seedSession();
|
||||
mocks.opsHealth.mockResolvedValue({
|
||||
linkHealth: [], kafkaLag: 0, activeConnections: 10, capacityFindings: [], redisOnlineKeys: 5,
|
||||
tdengineWritable: true, mysqlWritable: true,
|
||||
runtime: { platformRelease: 'test-release', dataMode: 'production', requestTimeoutMs: 5000, amapSecurityProxyEnabled: true, amapSecurityCodeExposed: false }
|
||||
});
|
||||
mocks.sourceReadiness.mockResolvedValue({ totalVehicles: 1, boundVehicles: 1, identityRequiredVehicles: 0, onlineVehicles: 1, sources: [] });
|
||||
mocks.vehicleCoverage.mockResolvedValue({ items: [{ vin: 'VIN-CANONICAL', plate: '沪A00001', protocols: ['JT808'], missingProtocols: [], sourceStatus: [], sourceCount: 1, onlineSourceCount: 1, online: true, lastSeen: '', bindingStatus: 'bound' }], total: 1, limit: 20, offset: 0 });
|
||||
const diagnostic = {
|
||||
evidence: {
|
||||
vin: 'VIN-CANONICAL', plate: '沪A00001', mileageDate: '', recommendedLocationProtocol: 'JT808',
|
||||
recommendedLocationLabel: 'JT808', locationConflict: false,
|
||||
locationSources: [{
|
||||
protocol: 'JT808', sourceLabel: 'JT808', providerOverride: '', terminalLabel: '', sourceKind: 'CANONICAL', sourceRef: 'b'.repeat(64),
|
||||
selectedWithinProtocol: true, recommended: true, enabled: true, priority: 100, policyRemark: '', online: true, qualityStatus: 'OK', qualityReason: '',
|
||||
longitude: 113.1, latitude: 23.1, eventTime: '2026-07-16 10:00:00', receivedAt: '2026-07-16 10:00:01',
|
||||
selectionReason: '协议融合快照只能维护提供方'
|
||||
}],
|
||||
mileageSources: [], comparison: { locationMaxDistanceM: 0, totalMileageDeltaKm: 0, dailyMileageDeltaKm: 0, reportTimeDeltaSeconds: 0 }, asOf: ''
|
||||
},
|
||||
policy: { vin: 'VIN-CANONICAL', version: 1, updatedBy: 'system', updatedAt: '', audit: [] },
|
||||
recommendationReason: '当前推荐 JT808 的协议融合结果', refreshHint: '等待下一次上报'
|
||||
};
|
||||
mocks.vehicleSourceDiagnostic.mockResolvedValue(diagnostic);
|
||||
mocks.updateVehicleSourcePolicy.mockResolvedValue(diagnostic);
|
||||
const client = new QueryClient({ defaultOptions: { queries: { retry: false } } });
|
||||
render(<QueryClientProvider client={client}><OperationsPage /></QueryClientProvider>);
|
||||
fireEvent.change(screen.getByLabelText('按车牌或 VIN 搜索诊断车辆'), { target: { value: '沪A' } });
|
||||
const candidateButton = await waitFor(() => {
|
||||
const button = document.querySelector<HTMLButtonElement>('.v2-source-candidates button');
|
||||
expect(button).toBeTruthy();
|
||||
return button!;
|
||||
});
|
||||
fireEvent.click(candidateButton);
|
||||
|
||||
expect(await screen.findByLabelText('JT808 优先级')).toBeDisabled();
|
||||
expect(screen.getByLabelText('JT808 策略备注')).toBeDisabled();
|
||||
expect(screen.getByRole('checkbox', { name: '启用' })).toBeDisabled();
|
||||
expect(screen.getByLabelText('JT808 提供方')).toBeEnabled();
|
||||
fireEvent.change(screen.getByLabelText('JT808 提供方'), { target: { value: '东方北斗' } });
|
||||
fireEvent.change(screen.getByLabelText('JT808 提供方核验依据'), { target: { value: 'GPS 运维终端清单 2026-07-16' } });
|
||||
fireEvent.click(screen.getByRole('button', { name: '保存提供方' }));
|
||||
await waitFor(() => expect(mocks.updateVehicleSourcePolicy).toHaveBeenCalledWith('VIN-CANONICAL', {
|
||||
version: 1,
|
||||
sourceRef: 'b'.repeat(64),
|
||||
providerName: '东方北斗',
|
||||
providerEvidence: 'GPS 运维终端清单 2026-07-16',
|
||||
enabled: true,
|
||||
priority: 100,
|
||||
remark: ''
|
||||
}));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user