const test = require('node:test'); const assert = require('node:assert'); const C = require('../static/calibration.js'); test('baseSignalName strips an element suffix', () => { assert.strictEqual(C.baseSignalName('Adc'), 'Adc'); assert.strictEqual(C.baseSignalName('Adc[3]'), 'Adc'); assert.strictEqual(C.baseSignalName('Adc[12]'), 'Adc'); assert.strictEqual(C.baseSignalName('A[1]B'), 'A[1]B'); assert.strictEqual(C.baseSignalName(''), ''); }); test('calKey is stable and separates the two fields', () => { assert.strictEqual(C.calKey('a', 'b'), C.calKey('a', 'b')); assert.notStrictEqual(C.calKey('ab', 'c'), C.calKey('a', 'bc')); }); test('normaliseCal accepts a valid entry and fills defaults', () => { assert.deepStrictEqual( C.normaliseCal({source: ' wave ', signal: ' Adc ', scale: 2, offset: -1, unit: ' V '}), {source: 'wave', signal: 'Adc', scale: 2, offset: -1, unit: 'V'}); assert.deepStrictEqual( C.normaliseCal({source: 'wave', signal: 'Adc'}), {source: 'wave', signal: 'Adc', scale: 1, offset: 0, unit: ''}); }); test('normaliseCal strips an element suffix from the signal name', () => { assert.strictEqual(C.normaliseCal({source: 'w', signal: 'Adc[3]'}).signal, 'Adc'); }); test('normaliseCal truncates an over-long unit', () => { const long = 'abcdefghijklmnopqrstuvwxyz'; assert.strictEqual(C.normaliseCal({source: 'w', signal: 's', unit: long}).unit, long.slice(0, C.MAX_UNIT_LEN)); }); test('normaliseCal rejects invalid entries', () => { assert.strictEqual(C.normaliseCal(null), null); assert.strictEqual(C.normaliseCal({signal: 's'}), null); assert.strictEqual(C.normaliseCal({source: 'w'}), null); assert.strictEqual(C.normaliseCal({source: ' ', signal: 's'}), null); assert.strictEqual(C.normaliseCal({source: 'w', signal: 's', scale: 0}), null); assert.strictEqual(C.normaliseCal({source: 'w', signal: 's', scale: NaN}), null); assert.strictEqual(C.normaliseCal({source: 'w', signal: 's', scale: Infinity}), null); assert.strictEqual(C.normaliseCal({source: 'w', signal: 's', offset: NaN}), null); assert.strictEqual(C.normaliseCal({source: 'w', signal: 's', scale: '2'}), null); }); test('applyCal and invertCal round-trip', () => { const cal = {scale: 0.5, offset: -1.25, unit: 'V'}; assert.strictEqual(C.applyCal(10, cal), 3.75); assert.strictEqual(C.invertCal(3.75, cal), 10); assert.strictEqual(C.applyCal(7, C.IDENTITY), 7); assert.strictEqual(C.invertCal(7, C.IDENTITY), 7); }); test('applyCal passes non-finite samples through untouched', () => { assert.ok(Number.isNaN(C.applyCal(NaN, {scale: 2, offset: 1, unit: ''}))); }); test('calRange re-orders when the scale is negative', () => { assert.deepStrictEqual(C.calRange(0, 10, {scale: 2, offset: 1, unit: ''}), [1, 21]); assert.deepStrictEqual(C.calRange(0, 10, {scale: -2, offset: 1, unit: ''}), [-19, 1]); }); test('CalTable.get returns IDENTITY for an unknown signal', () => { const t = new C.CalTable(); assert.deepStrictEqual(t.get('w', 'Adc'), C.IDENTITY); }); test('CalTable.get resolves an element name to its base signal', () => { const t = new C.CalTable(); t.set({source: 'w', signal: 'Adc', scale: 3, offset: 0, unit: ''}); assert.strictEqual(t.get('w', 'Adc[7]').scale, 3); }); test('CalTable.set stores, overwrites, and deletes identity entries', () => { const t = new C.CalTable(); assert.strictEqual(t.set({source: 'w', signal: 'Adc', scale: 2}), true); assert.strictEqual(t.get('w', 'Adc').scale, 2); t.set({source: 'w', signal: 'Adc', scale: 5}); assert.strictEqual(t.get('w', 'Adc').scale, 5); assert.strictEqual(t.list().length, 1); // Resetting to identity removes the entry entirely. assert.strictEqual(t.set({source: 'w', signal: 'Adc', scale: 1, offset: 0, unit: ''}), true); assert.strictEqual(t.list().length, 0); // An invalid entry is refused and changes nothing. assert.strictEqual(t.set({source: 'w', signal: 'Adc', scale: 0}), false); assert.strictEqual(t.list().length, 0); }); test('CalTable.replaceAll drops the previous contents', () => { const t = new C.CalTable(); t.set({source: 'w', signal: 'Old', scale: 2}); t.replaceAll([ {source: 'w', signal: 'B', scale: 2}, {source: 'w', signal: 'A', scale: 3}, {source: 'w', signal: 'Bad', scale: 0}, {source: 'w', signal: 'Ident', scale: 1, offset: 0, unit: ''}, ]); assert.deepStrictEqual(t.list().map(e => e.signal), ['A', 'B']); }); test('CalTable.list is sorted by source then signal', () => { const t = new C.CalTable(); t.set({source: 'z', signal: 'a', scale: 2}); t.set({source: 'a', signal: 'z', scale: 2}); t.set({source: 'a', signal: 'b', scale: 2}); assert.deepStrictEqual(t.list().map(e => e.source + '/' + e.signal), ['a/b', 'a/z', 'z/a']); });