/** Issue 65: exhaustive entity-card clickability coverage. Pure Node only. */ import assert from 'node:assert/strict' import fs from 'node:fs' import { operationPanel, emergencyPanel, toEmergencySupport, toOperatingInformation } from '../src/modules/cockpit/domain/infrastructurePanels.js' import { operationOverviewPanel, monitoringPointLedgerPanel, toMonitoringOverview, toMonitoringDistribution } from '../src/modules/cockpit/domain/monitoringPanels.js' import { historyAnalysisPanel, workOrderCardRows } from '../src/modules/cockpit/domain/warningResponsePanels.js' import { currentEventsView, toCurrentEvents } from '../src/modules/cockpit/domain/eventList.js' import { CARD_ACTION, cardActionFor } from '../src/modules/cockpit/domain/panelBlocks.js' const loaded = { state: 'success', loaded: true, data: null } const listRows = (view) => (view.blocks || []).filter((block) => block.kind === 'list').flatMap((block) => block.rows || []) const action = (row, kind, code) => { const actual = cardActionFor(row) assert.equal(actual.kind, kind) assert.equal(actual.code, code) assert.equal(actual.reason, '') } const unavailable = (row, reason) => { const actual = cardActionFor(row) assert.equal(actual.kind, CARD_ACTION.NONE) assert.match(actual.reason, reason) } const operation = operationPanel(toOperatingInformation({ selectedIndustry: { code: 'WATER_SUPPLY' }, industries: [{ industry: { code: 'WATER_SUPPLY' }, state: 'READY', metrics: [{ metricCode: 'FLOW', metricName: '流量', category: 'FLOW', facilityId: '731', facilityKind: 'WATER_PLANT', pointCodes: ['WP-DISPLAY'] }, { metricCode: 'FLOW', metricName: '流量', category: 'FLOW', facilityId: null, facilityKind: 'WATER_PLANT', pointCodes: ['NOT-A-PK'] }, { metricCode: 'FLOW', metricName: '流量', category: 'FLOW', facilityId: '732', facilityKind: null, pointCodes: ['NOT-A-CATEGORY'] }] }] }), loaded) const operationRows = listRows(operation) action(operationRows[0], CARD_ACTION.FACILITY, '731') assert.equal(operationRows[0].identityCategory, 'WATER_PLANT') unavailable(operationRows[1], /主键/) unavailable(operationRows[2], /类别/) const engineering = operationPanel(toOperatingInformation({ selectedIndustry: { code: 'DRAINAGE' }, industries: [{ industry: { code: 'DRAINAGE' }, state: 'READY', metrics: [{ metricCode: 'POINTS', metricName: '排水闸门', category: 'CAPACITY', facilityId: 'eng-1', facilityKind: 'ENGINEERING_FACILITY', pointCodes: ['GATE-1'] }] }] }), loaded) const engineeringRow = listRows(engineering)[0] action(engineeringRow, CARD_ACTION.FACILITY, 'eng-1') assert.equal(engineeringRow.identityCategory, 'ENGINEERING_FACILITY') const emergency = emergencyPanel(toEmergencySupport({ sections: { hazardSources: { state: 'EMPTY', items: [] }, protectionTargets: { state: 'READY', items: [{ objectCode: 'risk001', objectName: '学校', category: 'PROTECTION_TARGET' }] }, emergencyResources: { state: 'READY', items: [{ objectCode: 'device001', objectName: '应急设备', category: 'EMERGENCY_RESOURCE' }, { objectCode: '', objectName: '无码对象', category: 'EMERGENCY_RESOURCE' }] } } }), loaded) const emergencyRows = listRows(emergency) action(emergencyRows[0], CARD_ACTION.EMERGENCY, 'risk001') assert.equal(emergencyRows[0].identityCategory, 'PROTECTION_TARGET') action(emergencyRows[1], CARD_ACTION.EMERGENCY, 'device001') assert.equal(emergencyRows[1].identityCategory, 'EMERGENCY_RESOURCE') unavailable(emergencyRows[2], /对象编码/) // 设备台账的行来自领域转换后的 devices(`code` 由 deviceCode 归一),测试必须走同一条链, // 否则造出来的行是"原始载荷形状",与真实行的键名不同 —— 那是测试自身失真,不是产品缺陷。 const overviewDomain = toMonitoringOverview({ devices: [{ deviceCode: 'D1', deviceName: '压力计' }, { deviceCode: '', deviceName: '无码设备' }] }) const overview = operationOverviewPanel({}, loaded, { devices: overviewDomain.devices }) const deviceRows = listRows(overview) action(deviceRows[0], CARD_ACTION.DEVICE, 'D1') unavailable(deviceRows[1], /设备编码/) const ledger = monitoringPointLedgerPanel(toMonitoringDistribution({ monitoringPoints: [{ pointCode: 'P1', pointName: '点位一' }, { pointCode: '', pointName: '无码点位' }], unassociatedEquipment: [], pagination: {} }), loaded) const pointRows = listRows(ledger) action(pointRows[0], CARD_ACTION.POINT, 'P1') unavailable(pointRows[1], /点位编码/) const history = historyAnalysisPanel({ mode: 'ALARM', events: [{ code: 'A-1', name: '报警一', level: 1 }] }, loaded) const historyRow = listRows(history)[0] action(historyRow, CARD_ACTION.EVENT, 'A-1') assert.equal(historyRow.identityFamily, 'ALARM') const orderRows = workOrderCardRows([{ id: '88', code: 'WO-88', stateCode: 0 }, { id: '', code: 'WO-NO-ID', stateCode: 0 }]) action(orderRows[0], CARD_ACTION.WORK_ORDER, '88') assert.notEqual(orderRows[0].identityCode, orderRows[0].code) unavailable(orderRows[1], /工单主键/) const current = toCurrentEvents({ mode: 'WARNING', pagination: { page: 1, pageSize: 10, total: 2, totalPages: 1 }, sections: { events: { state: 'READY', data: [{ eventNo: 'W-1', eventName: '预警一' }, { eventNo: '', eventName: '无码预警' }] } } }) const currentView = currentEventsView(current, current.sections.events) assert.equal(currentView.rows[0].identityCode, 'W-1') assert.equal(currentView.rows[0].identityFamily, 'WARNING') assert.equal(currentView.rows[1].identityCode, '') assert.match(currentView.rows[1].identityReason, /事件编号/) const eventPane = fs.readFileSync(new URL('../src/modules/cockpit/components/EventListPane.vue', import.meta.url), 'utf8') const warningPane = fs.readFileSync(new URL('../src/modules/cockpit/components/WarningResponsePane.vue', import.meta.url), 'utf8') assert.ok(eventPane.includes(':tabindex="canOpen(row) ? 0 : null"')) assert.ok(eventPane.includes('@click="canOpen(row) ? openEvent(row) : null"')) assert.ok(eventPane.includes(`:data-card-action="canOpen(row) ? 'event' : 'none'"`)) assert.ok(warningPane.includes("if (action.kind === 'event')")) assert.ok(warningPane.includes("if (action.kind === 'work-order')")) assert.ok(warningPane.includes('const prefill = row.identityPayload || row')) console.log('t65-clickability-coverage: 32/32')