// Triage-only probe: executes production functions with Cesium API doubles. // No application changes, browser, server, or GPU rendering. Expected red until #47 is fixed. import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import vm from 'node:vm' import { groupOverlappingDevices, fanLayout } from '../../../../../src/modules/cockpit/domain/overlapDevices.js' import * as effects from '../../../../../src/modules/cockpit/domain/deviceEffects.js' const engine = readFileSync(new URL('../../../../../src/modules/cockpit/services/cesiumEngine.js', import.meta.url), 'utf8') const productionFunction = (name) => { const match = engine.match(new RegExp(`(?:export )?function ${name}\\([^]*?\\n\\}`)) assert.ok(match, `${name} exists`) return match[0].replace(/^export /, '') } const property = (initial) => { let value = initial return { getValue: () => value, setValue: (next) => { value = next } } } const rows = ['ALARM', 'NORMAL'].map((status, index) => ({ code: index ? 'EQ-N' : 'EQ-A', pointCode: 'MP-T47', status, longitude: 110.3632, latitude: 28.4524, placement: 'drawn', coordinate: { renderable: true }, size: 14, shape: index ? 'circle' : 'triangle', })) const group = groupOverlappingDevices(rows)[0] const plan = effects.planDeviceEffects({ devices: rows, enabled: true }) const source = { entities: { values: [], add(input) { const entity = { show: true, ...input } entity.properties = Object.fromEntries(Object.entries(input.properties || {}).map(([key, value]) => [key, property(value)])) this.values.push(entity) return entity }, remove(entity) { this.values = this.values.filter((item) => item !== entity) }, removeAll() { this.values = [] }, } } let requests = 0 const viewer = { scene: { requestRender() { requests += 1 } } } const context = vm.createContext({ ...effects, source, viewer, rows, groups: [group], plan, deviceSources: new Map([[viewer, source]]), deviceMarkerSource: () => source, deviceBaseStyle: new Map(), deviceEffectState: { viewer, plan, selectedCode: '', tick: 0, raf: 0 }, RING_ENTITY_PREFIX: 'fx|', Color: { WHITE: { withAlpha: (alpha) => ({ alpha }) } }, Cartesian2: class { constructor(x, y) { this.x = x; this.y = y } }, Cartesian3: { fromDegrees: (longitude, latitude) => ({ longitude, latitude }) }, HeightReference: { CLAMP_TO_GROUND: 'ground' }, VerticalOrigin: { CENTER: 'center' }, mapTextLabel: () => ({ show: true }), stopDeviceEffects: () => {}, ensureEffectLoop: () => {}, Date: { now: () => 300 }, }) for (const name of ['syncAssociatedDevices', 'setOverlapPresentation', 'ringEntitiesOf', 'ensureRingEntities', 'clearRingEntities', 'baseStyleOf', 'animatedByCode', 'writeEffectFrame', 'applyDeviceEffects', 'readDeviceEffects']) { vm.runInContext(productionFunction(name), context) } vm.runInContext(`syncAssociatedDevices(viewer, rows, () => 'red', () => 'icon', groups); applyDeviceEffects(viewer, plan, { devices: rows, fxImageOf: () => 'halo' });`, context) let failures = 0 function snapshot(name, input) { context.input = input vm.runInContext('setOverlapPresentation(viewer, input); writeEffectFrame()', context) const visibleFx = source.entities.values.filter((entity) => entity.properties.effectFx?.getValue() === true && entity.show !== false && entity.billboard.color.alpha > 0) const visibleDevices = source.entities.values.filter((entity) => entity.properties.deviceCode && entity.show !== false).map((entity) => entity.properties.deviceCode.getValue()) const readback = vm.runInContext('readDeviceEffects(viewer)', context) console.log(JSON.stringify({ case: name, animatedPlan: plan.animated.length, abnormalCount: plan.abnormalCount, degraded: plan.degraded, visibleDevices, visibleFx: visibleFx.length, reportedFx: readback.fx.length, fxReadbackContainsVisibility: readback.fx.every((item) => 'visible' in item || 'show' in item), requests })) return visibleFx.length } function expectVisible(name, input) { const count = snapshot(name, input) try { assert.ok(count > 0, 'expected visible abnormal effect while associated layer and effects are enabled'); console.log(`PASS ${name}`) } catch (error) { failures += 1; console.log(`FAIL ${name}: ${error.message}`) } } expectVisible('collapsed', { groupKey: group.key, state: 'collapsed' }) const offsets = Object.fromEntries(fanLayout(group).map((item) => [item.deviceCode, { x: item.x, y: item.y }])) expectVisible('expanded-control', { groupKey: group.key, state: 'expanded', offsets }) expectVisible('selected-NORMAL', { groupKey: group.key, state: 'selected', selectedCode: 'EQ-N' }) expectVisible('selected-ALARM-control', { groupKey: group.key, state: 'selected', selectedCode: 'EQ-A' }) console.log(`T47 triage probe: ${failures} failed expectations; render visibility logic only, not a browser/GPU verification.`) process.exitCode = failures ? 1 : 0