Files
generalFunctions/test/basic/statusBadge.basic.test.js
znetsixe 47faf94048 Phase 1 wave 1: domain + nodered + stats infra (additive)
Adds platform infrastructure used by the upcoming refactor of
nodeClass / specificClass across all 12 nodes:

- src/domain/UnitPolicy.js     — extracted from rotatingMachine/MGC
- src/domain/ChildRouter.js    — declarative event routing on top of childRegistrationUtils
- src/domain/LatestWinsGate.js — extracted from MGC dispatch gate
- src/domain/HealthStatus.js   — standardised {level, flags, message, source}
- src/nodered/statusBadge.js   — compose / error / idle / byState / text helpers
- src/stats/index.js           — mean / stdDev / median / mad / lerp

All additive — no existing exports change shape.
56 unit tests pass under node:test.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 18:27:29 +02:00

71 lines
2.6 KiB
JavaScript

'use strict';
const test = require('node:test');
const assert = require('node:assert/strict');
const { statusBadge, MAX_TEXT } = require('../../src/nodered/statusBadge');
test('compose joins parts with " | " and uses default green/dot', () => {
const badge = statusBadge.compose(['A', 'B']);
assert.deepEqual(badge, { fill: 'green', shape: 'dot', text: 'A | B' });
});
test('compose drops null/undefined/empty parts', () => {
const badge = statusBadge.compose(['A', null, 'B', undefined, '']);
assert.equal(badge.text, 'A | B');
assert.equal(badge.fill, 'green');
assert.equal(badge.shape, 'dot');
});
test('compose with empty parts and override fill returns empty text', () => {
const badge = statusBadge.compose([], { fill: 'yellow' });
assert.equal(badge.text, '');
assert.equal(badge.fill, 'yellow');
assert.equal(badge.shape, 'dot');
});
test('error returns red ring with ⚠ prefix', () => {
const badge = statusBadge.error('boom');
assert.deepEqual(badge, { fill: 'red', shape: 'ring', text: '⚠ boom' });
});
test('idle returns blue dot with ⏸ prefix', () => {
const badge = statusBadge.idle('waiting');
assert.deepEqual(badge, { fill: 'blue', shape: 'dot', text: '⏸️ waiting' });
});
test('byState returns the matching template', () => {
const map = { off: { fill: 'red', shape: 'dot', text: 'OFF' } };
const badge = statusBadge.byState(map, 'off');
assert.deepEqual(badge, { fill: 'red', shape: 'dot', text: 'OFF' });
});
test('byState returns grey "unknown state" badge when key is missing', () => {
const badge = statusBadge.byState({}, 'unknown');
assert.equal(badge.fill, 'grey');
assert.equal(badge.shape, 'ring');
assert.match(badge.text, /unknown state/);
assert.match(badge.text, /unknown/);
});
test('byState composes extra parts into the template text', () => {
const map = { run: { fill: 'green', shape: 'dot', text: 'RUN' } };
const badge = statusBadge.byState(map, 'run', { compose: ['flow=12.0', 'P=3kW'] });
assert.equal(badge.text, 'RUN | flow=12.0 | P=3kW');
});
test('text length is truncated to MAX_TEXT chars ending with …', () => {
const longInput = 'x'.repeat(200);
const badge = statusBadge.text(longInput);
assert.equal(badge.text.length, MAX_TEXT);
assert.equal(badge.text.endsWith('…'), true);
});
test('text helper defaults to green/dot and never returns null text', () => {
assert.equal(statusBadge.text(null).text, '');
assert.equal(statusBadge.text(undefined).text, '');
const badge = statusBadge.text('hi');
assert.equal(badge.fill, 'green');
assert.equal(badge.shape, 'dot');
});