Adds per-panel `meta.emittedFields` to machine.json (rotatingMachine) and machineGroup.json (MGC) templates. Each non-row panel declares the Influx field paths it visualizes, so a parent template's composer can filter out panels already covered by its children (#39 no-data-duplication rule). - config/machine.json: 13 non-row panels annotated. - config/machineGroup.json: panels annotated. - src/specificClass.js: collectEmittedFields(dashboard) helper. - test/basic/slice37-emitted-fields.basic.test.js: 4 cases (template loads with annotations, aggregation, missing-meta graceful, null input). PRD F-6 panel set audit: machine.json already covers all the PRD-required panels (State/Mode/Ctrl%/Runtime/NCog%/Flow/Efficiency/Pressure/Temperature/ Diagnostics) — substantially more than asked. No new panels added. PRD F-7 predicted-vs-measured side-by-side: deferred. Current architecture is "1 dashboard per node" (each child gets its own dashboard, cross-linked from the parent), not "1 dashboard with N composed panels." Side-by-side rendering of predicted (rotatingMachine dashboard) + measured (measurement child dashboard) lives naturally as drill-down navigation today. Refactor to a single-dashboard composition model would be substantial — flagged in the issue comment for v2 if the drill-down UX proves insufficient. Closes #37
41 lines
1.7 KiB
JavaScript
41 lines
1.7 KiB
JavaScript
'use strict';
|
|
|
|
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
|
|
const DashboardApi = require('../../src/specificClass.js');
|
|
|
|
test('rotatingMachine template panels declare meta.emittedFields', () => {
|
|
const api = new DashboardApi({});
|
|
const dash = api.loadTemplate('machine');
|
|
assert.ok(dash, 'template loaded');
|
|
const withFields = dash.panels.filter((p) => p?.meta?.emittedFields);
|
|
// 13 non-row panels in machine.json get annotated; row panels are skipped.
|
|
assert.ok(withFields.length >= 10, `expected ≥10 annotated panels, got ${withFields.length}`);
|
|
});
|
|
|
|
test('collectEmittedFields aggregates fields across panels', () => {
|
|
const api = new DashboardApi({});
|
|
const dash = api.loadTemplate('machine');
|
|
const fields = api.collectEmittedFields(dash);
|
|
assert.ok(fields.has('ctrl'), 'ctrl field declared by Ctrl % panel');
|
|
assert.ok(fields.has('flow'), 'flow field declared by Flow panel');
|
|
assert.ok(fields.has('efficiency'), 'efficiency field declared by Efficiency panel');
|
|
assert.ok(fields.has('relDistFromPeak'), 'relDistFromPeak declared by Distance from Peak panel');
|
|
});
|
|
|
|
test('collectEmittedFields returns empty Set for template without meta', () => {
|
|
const api = new DashboardApi({});
|
|
// measurement.json has no emittedFields metadata yet — its panels predate the annotation.
|
|
const dash = api.loadTemplate('measurement');
|
|
const fields = api.collectEmittedFields(dash);
|
|
assert.equal(fields.size, 0);
|
|
});
|
|
|
|
test('collectEmittedFields handles null/empty dashboard input gracefully', () => {
|
|
const api = new DashboardApi({});
|
|
assert.equal(api.collectEmittedFields(null).size, 0);
|
|
assert.equal(api.collectEmittedFields({}).size, 0);
|
|
assert.equal(api.collectEmittedFields({ panels: [] }).size, 0);
|
|
});
|