const assert = require('assert'); const A = require('./audio.js'); // Glyph constants (must match audio.js exactly; these are the source-of-truth escapes). const GLYPH_OUT = ""; const GLYPH_OUT_MUTE = ""; const GLYPH_IN = ""; const GLYPH_IN_MUTE = ""; // --- clampVolume: 0..1.5, null/NaN -> 0 --- assert.strictEqual(A.clampVolume(-1), 0); assert.strictEqual(A.clampVolume(2), 1.5); assert.strictEqual(A.clampVolume(0.5), 0.5); assert.strictEqual(A.clampVolume(null), 0); assert.strictEqual(A.clampVolume(undefined), 0); assert.strictEqual(A.clampVolume(NaN), 0); assert.strictEqual(A.clampVolume("0.3"), 0.3); // --- volumePercent: integer percent of clamped volume --- assert.strictEqual(A.volumePercent(1), 100); assert.strictEqual(A.volumePercent(1.5), 150); assert.strictEqual(A.volumePercent(0), 0); assert.strictEqual(A.volumePercent(2), 150); // clamped first assert.strictEqual(A.volumePercent(null), 0); // --- nodeName: precedence description > nickname > name > "Audio"; null-safe --- assert.strictEqual( A.nodeName({ description: 'Desc', nickname: 'Nick', name: 'Name' }), 'Desc'); // nickname wins only when description AND the superset fields are absent assert.strictEqual( A.nodeName({ nickname: 'Nick', name: 'Name' }), 'Nick'); assert.strictEqual( A.nodeName({ name: 'Name' }), 'Name'); // superset fields sit between nickname and name assert.strictEqual( A.nodeName({ nodeDescription: 'ND', name: 'Name' }), 'ND'); assert.strictEqual( A.nodeName({ applicationName: 'App', name: 'Name' }), 'App'); assert.strictEqual( A.nodeName({ mediaName: 'Media', name: 'Name' }), 'Media'); assert.strictEqual(A.nodeName({}), 'Audio'); assert.strictEqual(A.nodeName(null), 'Audio'); // --- channelNames: lowercased string list --- assert.deepStrictEqual(A.channelNames(['FL', 'FR']), ['fl', 'fr']); assert.deepStrictEqual(A.channelNames([]), []); assert.deepStrictEqual(A.channelNames(null), []); // --- nodeMuted --- assert.strictEqual(A.nodeMuted({ muted: true }), true); assert.strictEqual(A.nodeMuted({ muted: false }), false); assert.strictEqual(A.nodeMuted({}), false); assert.strictEqual(A.nodeMuted(null), false); // --- roleForSink: muted->warning, vol0->ui.minor, vol0.5->ui.accent --- assert.strictEqual(A.roleForSink({ muted: true, volume: 0.5 }), 'warning'); assert.strictEqual(A.roleForSink({ muted: false, volume: 0 }), 'ui.minor'); assert.strictEqual(A.roleForSink({ muted: false, volume: 0.5 }), 'ui.accent'); assert.strictEqual(A.roleForSink({ volume: 1.0 }), 'ui.accent'); assert.strictEqual(A.roleForSink({}), 'ui.minor'); // no volume -> 0 -> ui.minor // --- privacyLabel: all four {mic,cam} combos --- assert.strictEqual(A.privacyLabel({ mic: true, cam: true }), 'Mic Cam'); assert.strictEqual(A.privacyLabel({ mic: true, cam: false }), 'Mic'); assert.strictEqual(A.privacyLabel({ mic: false, cam: true }), 'Cam'); assert.strictEqual(A.privacyLabel({ mic: false, cam: false }), 'Audio'); assert.strictEqual(A.privacyLabel({}), 'Audio'); assert.strictEqual(A.privacyLabel(null), 'Audio'); // --- glyphForRow: kind + muted matrix --- assert.strictEqual(A.glyphForRow('sink', false), GLYPH_OUT); assert.strictEqual(A.glyphForRow('sink', true), GLYPH_OUT_MUTE); assert.strictEqual(A.glyphForRow('source', false), GLYPH_IN); assert.strictEqual(A.glyphForRow('source', true), GLYPH_IN_MUTE); // --- shapeRow: full dict with correct percent/muted/glyph/role --- const sink = A.shapeRow({ id: 42, description: 'Speakers', volume: 0.5, muted: false, isDefault: true, active: true, channels: ['FL', 'FR'] }, 'sink'); assert.strictEqual(sink.id, '42'); assert.strictEqual(sink.name, 'Speakers'); assert.strictEqual(sink.kind, 'sink'); assert.strictEqual(sink.volume, 0.5); assert.strictEqual(sink.percent, 50); assert.strictEqual(sink.muted, false); assert.strictEqual(sink.role, 'ui.accent'); assert.strictEqual(sink.isDefault, true); assert.strictEqual(sink.active, true); assert.deepStrictEqual(sink.channels, ['fl', 'fr']); assert.strictEqual(sink.glyph, GLYPH_OUT); // muted source row: warning role, muted glyph, desaturatable const src = A.shapeRow({ id: 7, nodeDescription: 'Built-in Mic', volume: 0.8, muted: true }, 'source'); assert.strictEqual(src.kind, 'source'); assert.strictEqual(src.name, 'Built-in Mic'); assert.strictEqual(src.muted, true); assert.strictEqual(src.role, 'warning'); assert.strictEqual(src.glyph, GLYPH_IN_MUTE); assert.strictEqual(src.isDefault, false); assert.strictEqual(src.active, false); // null node -> safe defaults const empty = A.shapeRow(null, 'sink'); assert.strictEqual(empty.id, ''); assert.strictEqual(empty.name, 'Audio'); assert.strictEqual(empty.percent, 0); assert.strictEqual(empty.role, 'ui.minor'); assert.strictEqual(empty.glyph, GLYPH_OUT); // --- rowsById: keys by id --- const map = A.rowsById([{ id: 'a', x: 1 }, { id: 'b', x: 2 }]); assert.strictEqual(map.a.x, 1); assert.strictEqual(map.b.x, 2); assert.deepStrictEqual(Object.keys(A.rowsById([])), []); assert.deepStrictEqual(Object.keys(A.rowsById(null)), []); console.log('audio.test.js: ALL PASS');