import assert from 'node:assert/strict' import { deviceMetricKind, deviceMetricPath, toTypedMetricsPayload } from '../../../src/modules/cockpit/domain/deviceMetricSources.js' import { fetchEquipmentDetailAggregate } from '../../../src/modules/cockpit/services/detailApi.js' assert.equal(deviceMetricKind({ name: '测试流量计' }), 'flow') assert.equal(deviceMetricPath('flow', 'TEST-TCLLJ002215'), '/waterSupply/monitoring/flow/trend/TEST-TCLLJ002215') const typed = toTypedMetricsPayload({ data: [{ flow: 12.5, unit: 'm³/h', timestamp: '2026-10-19T10:00:00+08:00' }] }, 'D', 'flow') assert.equal(typed.metrics[0].value, 12.5) assert.equal(typed.metrics[0].unit, 'm³/h') const paths = [] const options = { config: { dataSource: 'real', api: { baseUrl: 'http://test.invalid/api/cockpit/v1' } }, fetchImpl: async (url) => { paths.push(url) if (url.endsWith('/detail-aggregate')) return new Response(JSON.stringify({ code: 200, data: { deviceCode: 'TEST-TCLLJ002215', aggregateState: 'READY', archive: { state: 'SUCCESS', data: { deviceCode: 'TEST-TCLLJ002215', deviceName: '测试流量计', deviceTypeName: '流量计' } }, metrics: { state: 'EMPTY', reason: 'NO_METRICS', data: null }, warnings: { state: 'SUCCESS', data: [] }, alarms: { state: 'SUCCESS', data: [] }, alarmWarningRelations: { state: 'SUCCESS', data: [] }, workOrders: { state: 'EMPTY', data: null }, timelines: { state: 'EMPTY', data: null }, latestImage: { state: 'EMPTY', data: null }, } })) if (url.includes('/waterSupply/monitoring/flow/trend/')) return new Response(JSON.stringify({ code: 200, data: [{ flow: 12.5, unit: 'm³/h', timestamp: '2026-10-19T10:00:00+08:00' }] })) throw new Error(`unexpected ${url}`) }, } const result = await fetchEquipmentDetailAggregate('TEST-TCLLJ002215', options) assert.equal(paths.length, 2) assert.equal(result.data.sections.metrics.data.metrics[0].value, 12.5) assert.equal(result.data.sections.metrics.data.metrics[0].unit, 'm³/h') assert.equal(deviceMetricKind({ type: 'FLOW_METER', name: '设备' }), 'flow') assert.equal(deviceMetricKind({ type: 'LEVEL_METER', name: '设备' }), '') const failedPaths = [] const failed = await fetchEquipmentDetailAggregate('D-401', { config: options.config, fetchImpl: async (url) => { failedPaths.push(url) if (url.endsWith('/detail-aggregate')) return new Response(JSON.stringify({ code: 200, data: { deviceCode: 'D-401', aggregateState: 'READY', archive: { state: 'SUCCESS', data: { deviceCode: 'D-401', deviceType: 'FLOW_METER', deviceName: '设备' } }, metrics: { state: 'EMPTY', reason: 'NO_METRICS', data: null }, warnings: { state: 'SUCCESS', data: [] }, alarms: { state: 'SUCCESS', data: [] }, alarmWarningRelations: { state: 'SUCCESS', data: [] }, workOrders: { state: 'EMPTY', data: null }, timelines: { state: 'EMPTY', data: null }, latestImage: { state: 'EMPTY', data: null }, } })) return new Response(JSON.stringify({ code: 401, msg: 'unauthorized' }), { status: 401 }) } }) assert.equal(failedPaths.length, 2) assert.equal(failed.data.sections.metrics.state, 'unavailable') assert.equal(failed.data.sections.warnings.state, 'success') console.log('PASS 流量计按设备类型切专用指标源,通用EMPTY不覆盖专用读数')