67 lines
4.1 KiB
JavaScript
67 lines
4.1 KiB
JavaScript
const { test } = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const { readFileSync } = require('node:fs');
|
|
const { join } = require('node:path');
|
|
const vm = require('node:vm');
|
|
|
|
const app = readFileSync(join(__dirname, 'app.js'), 'utf8');
|
|
const views = readFileSync(join(__dirname, 'views-core.js'), 'utf8');
|
|
|
|
function parsePreset(text) {
|
|
const declaration = views.match(/function parseJamesDspPreset\(text\) \{[\s\S]*?\n\}/)?.[0];
|
|
assert.ok(declaration, 'preset parser is present');
|
|
const context = vm.createContext({});
|
|
vm.runInContext(`${declaration}; globalThis.parse = parseJamesDspPreset;`, context);
|
|
return context.parse(text);
|
|
}
|
|
|
|
test('the persisted engine is Standard by default and upgrades missing JamesDSP settings safely', () => {
|
|
assert.match(app, /jamesDsp: \{ enabled: false, downloadForOffline: false, preset: 'flat', params: \{\}, irRef: null \}/);
|
|
assert.match(app, /downloadForOffline: saved\.downloadForOffline === true/);
|
|
assert.match(app, /enabled: saved\.enabled === true/);
|
|
assert.match(app, /preset: typeof saved\.preset === 'string' \? saved\.preset : 'flat'/);
|
|
assert.match(app, /settings: normalizeJamesDspSettings\(\{ \.\.\.DEFAULT_SETTINGS, \.\.\.\(loaded\.settings \|\| \{\}\) \}\)/);
|
|
assert.match(app, /data\.settings = normalizeJamesDspSettings\(\{ \.\.\.DEFAULT_SETTINGS, \.\.\.payload\.settings \}\)/);
|
|
});
|
|
|
|
test('live JamesDSP shares the existing iOS gate and never stacks over EqRender copies', () => {
|
|
assert.match(app, /const available = \(\) => !!AC && \(!isIOS \|\| data\.settings\.liveAudioIOS === true\)/);
|
|
assert.match(app, /if \(data\.settings\?\.jamesDsp\?\.enabled\) return null/);
|
|
assert.match(app, /const active = \(\) => EQ\.isIOS\(\) && WEB && !data\.settings\?\.jamesDsp\?\.enabled/);
|
|
assert.match(app, /if \(rendered\(\)\) throw new Error\('This song is already playing a Standard processed copy\./);
|
|
});
|
|
|
|
test('EQ creates no second context or element source and passes Standard fallback routing to the controller', () => {
|
|
assert.equal((app.match(/\.createMediaElementSource\(/g) || []).length, 0);
|
|
assert.match(app, /st\.ctx = AudioGraph\.context\(\)/);
|
|
assert.match(app, /AudioGraph\.connect\(el, st\.filters\[0\]\)/);
|
|
assert.match(app, /standardInput: st\.filters\[0\]/);
|
|
assert.match(app, /dspController\.setLevelDb\(st\.levelDb\)/);
|
|
assert.match(app, /if \(data\.settings\.jamesDsp\?\.enabled\) \{[\s\S]{0,450}startDsp\(\)/);
|
|
assert.match(app, /request !== dspRequest \|\| !data\.settings\.jamesDsp\?\.enabled/);
|
|
});
|
|
|
|
test('Playback settings expose persisted presets, bands, safe import/export, IR, and A/B bypass', () => {
|
|
assert.match(views, /sel\('setSoundEngine'/);
|
|
assert.match(views, /sel\('setDspPreset'/);
|
|
for (const id of ['setDspCompressor', 'dspPresetImportBtn', 'dspPresetExportBtn', 'dspResetBtn', 'dspIrFile']) assert.ok(views.includes(`id="${id}"`), id);
|
|
assert.match(views, /\[25, 40, 63, 100, 160, 250, 400, 630, 1000, 1600, 2500, 4000, 6300, 10000, 16000\]/);
|
|
assert.match(views, /imported\?\.texts/);
|
|
assert.doesNotMatch(views, /liveprog|ddc|arbitrary/);
|
|
assert.match(views, /navigator\.hardwareConcurrency/);
|
|
assert.match(views, /Long impulse responses are disabled/);
|
|
assert.doesNotMatch(views, /44\.1 or 48 kHz/);
|
|
assert.match(views, /setDspSpatialMode/);
|
|
assert.match(views, /data-dsp-param="convolver\.predelayMs"/);
|
|
assert.match(views, /data-dsp-param="convolver\.mix"/);
|
|
assert.match(app, /Bypass JamesDSP/);
|
|
assert.match(app, /toggleDspBypass/);
|
|
});
|
|
|
|
test('preset import validates ranges and excludes text-effect parameters', () => {
|
|
assert.deepEqual(JSON.parse(JSON.stringify(parsePreset(JSON.stringify({ version: 1, preset: 'warm', params: { 'eq.band0': 3, 'bass.enabled': 1 } })))), { preset: 'warm', params: { 'eq.band0': 3, 'bass.enabled': 1 } });
|
|
assert.throws(() => parsePreset({ version: 1, preset: 'flat', params: { 'liveprog.enabled': 1 } }), /text effects are disabled|Unsupported preset setting/);
|
|
assert.throws(() => parsePreset({ version: 1, params: { 'eq.band0': 50 } }), /Unsupported preset setting/);
|
|
assert.throws(() => parsePreset({ version: 1, texts: { effect: 'unsafe' }, params: {} }), /text effects are disabled/);
|
|
});
|