import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import { districtQuery, districtLabel, districtFilterLabel, industryLabel } from '../../../src/modules/cockpit/domain/filterOptions.js' import { buildQuery } from '../../../src/modules/cockpit/services/domainRequest.js' import { toMonitoringOverview, monitoringOverviewPanel, toMonitoringDistribution, monitoringDistributionPanel, monitoringPointLedgerPanel, toMonitoringSituation, operationOverviewPanel } from '../../../src/modules/cockpit/domain/monitoringPanels.js' import { toManagementInformation, managementPanel, toBaseArchives } from '../../../src/modules/cockpit/domain/infrastructurePanels.js' import { archiveRows } from '../../../src/modules/cockpit/domain/equipmentDetailView.js' import { registerCockpitMocks } from '../../../src/modules/cockpit/mocks/contractMocks.js' import { fetchMapSnapshot } from '../../../src/modules/cockpit/services/mapApi.js' import { fetchMonitoringDistribution } from '../../../src/modules/cockpit/services/monitoringApi.js' import { fetchBaseArchives, fetchManagementInformation } from '../../../src/modules/cockpit/services/infrastructureApi.js' import { fetchOverviewRegions } from '../../../src/modules/cockpit/services/overviewApi.js' let passed = 0 async function check(name, run) { await run() passed += 1 console.log(`PASS ${name}`) } const section = { state: 'success' } await check('district codes and unknown values', () => { assert.equal(buildQuery({ district: districtQuery('south') }), '?district=0') assert.equal(districtQuery('north'), 1) assert.equal(districtQuery('taichang'), 2) assert.equal(districtQuery('unassigned'), 'UNASSIGNED') assert.equal(districtQuery('all'), '') assert.equal(districtQuery('garbage'), '') assert.equal(districtLabel(0), '城南') for (const value of [null, undefined, '', '0', 8]) assert.equal(districtLabel(value), '未分区') assert.equal(industryLabel('MANHOLE'), '窨井') }) await check('null district is not enough to infer selection', () => { assert.equal(districtFilterLabel({ district: null, districtFilter: 'NONE' }), '全域') assert.equal(districtFilterLabel({ district: null, districtFilter: 'UNASSIGNED' }), '未分区') assert.equal(districtFilterLabel({ district: 0, districtFilter: 'ASSIGNED' }), '城南') }) await check('data time never falls back to sample or response time', () => { const item = (raw) => monitoringOverviewPanel(toMonitoringOverview(raw), section).blocks[0].items.find((row) => row.key === 'createdAt') assert.equal(item({ createdAt: 'record', sampledAt: 'sample', updatedAt: 'response' }).value, 'record') assert.equal(item({ createdAt: null, sampledAt: 'sample', updatedAt: 'response' }).value, '—') }) await check('ledger and abnormal equipment expose object time', () => { const distribution = toMonitoringDistribution({ createdAt: 'batch', monitoringPoints: [{ pointCode: 'p', district: 0, createdAt: 'point' }], mapFilter: { district: null, districtFilter: 'UNASSIGNED' } }) assert.equal(monitoringPointLedgerPanel(distribution, section).blocks[0].rows[0].dataTime, 'point') assert.equal(monitoringDistributionPanel(distribution, section).blocks.find((block) => block.kind === 'rows').rows.find((row) => row.key === 'district').value, '未分区') const situation = toMonitoringSituation({ abnormalEquipment: [{ deviceCode: 'd', createdAt: null, district: 2 }] }) assert.equal(operationOverviewPanel(situation, section).blocks.find((block) => block.kind === 'list').rows[0].dataTime, '—') }) await check('management uses separate facility and equipment counts only', () => { const view = managementPanel(toManagementInformation({ totals: { facilityCount: 1, equipmentCount: 0 }, districtIndustry: [{ district: 0, industry: 'MANHOLE', facilityCount: 1, equipmentCount: 0 }], organizations: [{ organizationName: 'FORBIDDEN' }] }), section) assert.match(JSON.stringify(view), /城南 · 窨井/) assert.doesNotMatch(JSON.stringify(view), /FORBIDDEN|管理单位|权属|责任区域/) assert.match(JSON.stringify(view), /设备 0 台/) assert.equal(toBaseArchives({ districtDistribution: [{ district: 0, count: 2 }] }).regions[0].code, 0) }) await check('archive retains static ownership and maintenance rows', () => { const rows = archiveRows({ ownershipUnit: 'owner', maintainer: 'maintainer', maintainerPhone: 'phone' }) for (const [key, value] of [['ownershipUnit', 'owner'], ['maintainer', 'maintainer'], ['maintainerPhone', 'phone']]) assert.equal(rows.find((row) => row.key === key).value, value) }) const transports = {} registerCockpitMocks({ handlers: { registerMockTransport: (path, handler) => { transports[path] = handler } } }) const get = (path, query = '') => transports[path]({ path: path + query }) await check('mock distribution filters assigned and unassigned districts', async () => { for (const [query, code, mode] of [['0', 0, 'ASSIGNED'], ['UNASSIGNED', null, 'UNASSIGNED']]) { const payload = await get('/monitoring/distribution', `?district=${query}`) assert.ok(payload.monitoringPoints.length > 0) assert.ok(payload.monitoringPoints.every((row) => row.district === code)) assert.equal(payload.mapFilter.district, code) assert.equal(payload.mapFilter.districtFilter, mode) } assert.equal((await get('/monitoring/distribution')).mapFilter.districtFilter, 'NONE') }) await check('mock management filtered totals equal row sums', async () => { const payload = await get('/infrastructure/management-information', '?district=0') assert.ok(payload.districtIndustry.length > 0) assert.ok(payload.districtIndustry.every((row) => row.district === 0)) assert.equal(payload.totals.facilityCount, payload.districtIndustry.reduce((sum, row) => sum + row.facilityCount, 0)) assert.equal(payload.organizations, undefined) }) await check('archive mock aggregates use the same filtered population', async () => { for (const query of ['', '?district=0', '?district=UNASSIGNED', '?industry=MANHOLE', '?district=0&industry=GAS']) { const payload = await get('/infrastructure/base-archives', query) for (const key of ['industryDistribution', 'districtDistribution', 'ageDistribution', 'facilityTypeDistribution']) { assert.equal(payload[key].reduce((sum, row) => sum + row.count, 0), payload.totals.facilityCount) } } }) await check('real transport request params use district, never region', async () => { const config = { dataSource: 'real', api: { baseUrl: 'http://test.invalid' } } for (const fetcher of [fetchMapSnapshot, fetchMonitoringDistribution, fetchBaseArchives, fetchManagementInformation, fetchOverviewRegions]) { for (const [scope, expected] of [['south', '0'], ['unassigned', 'UNASSIGNED'], ['all', null]]) { let seen await fetcher({ scope, config, fetchImpl: async (url) => { seen = new URL(url) return { ok: true, status: 200, json: async () => ({ monitoringPoints: [], unassociatedEquipment: [], pagination: { total: 0 }, total: 0, totals: { facilityCount: 0, equipmentCount: 0 }, districtIndustry: [] }) } } }) assert.equal(seen.searchParams.get('district'), expected) assert.equal(seen.searchParams.has('region'), false) assert.equal(seen.searchParams.has('createdAt'), false) } } }) await check('template exposes separate data and sample time assertions', () => { const panel = readFileSync(new URL('../../../src/modules/cockpit/components/PanelBlocks.vue', import.meta.url), 'utf8') const detail = readFileSync(new URL('../../../src/modules/cockpit/components/EquipmentDetailSections.vue', import.meta.url), 'utf8') assert.match(panel, /data-data-time>数据时间/) assert.match(detail, /data-sampled-at>采样时间/) }) console.log(`T15: ${passed}/${passed} checks passed. Browser acceptance not covered.`)