const { test } = require('node:test'); const assert = require('node:assert/strict'); const { readFileSync } = require('node:fs'); const { join } = require('node:path'); const root = __dirname; const assets = JSON.parse(readFileSync(join(root, 'assets.json'), 'utf8')); const group = assets.groups['feature:jamesdsp']; test('JamesDSP runtime files live only in a lazy background group', () => { assert.ok(group, 'feature group exists'); assert.equal(group.contract, 1); assert.equal(group.eager, false); assert.equal(group.background, true); assert.deepEqual(group.dependencies, ['feature:eq-core', 'feature:vocal-reducer']); assert.deepEqual(group.files, [ '/vendor/jamesdsp/jamesdsp-feature.js', '/vendor/jamesdsp/jamesdsp-node.mjs', '/vendor/jamesdsp/params.mjs', '/vendor/jamesdsp/worklet.mjs', '/vendor/jamesdsp/dsp/jamesdsp.mjs', '/vendor/jamesdsp/dsp/jamesdsp.wasm', ]); for (const path of group.files) assert.equal(assets.groups.core.files.includes(path), false, `${path} is not core`); const sw = readFileSync(join(root, 'sw.js'), 'utf8'); for (const path of group.files) assert.equal(sw.includes(`'${path}'`), false, `${path} is not in the legacy shell`); }); test('JamesDSP resolves every module dependency through the page build manifest', () => { const node = readFileSync(join(root, 'vendor/jamesdsp/jamesdsp-node.mjs'), 'utf8'); const worklet = readFileSync(join(root, 'vendor/jamesdsp/worklet.mjs'), 'utf8'); assert.match(node, /globalThis\.Lazy\?\.url\?\.\(path\)/); assert.match(node, /assetURL\('\/vendor\/jamesdsp\/dsp\/jamesdsp\.wasm'/); assert.match(node, /assetURL\('\/vendor\/jamesdsp\/params\.mjs'/); assert.match(node, /workletURL\.hash=new URLSearchParams/); assert.match(worklet, /new URLSearchParams\(new URL\(import\.meta\.url\)\.hash\.slice\(1\)\)/); assert.match(worklet, /await import\(engineURL\)/); const feature = readFileSync(join(root, 'vendor/jamesdsp/jamesdsp-feature.js'), 'utf8'); assert.match(feature, /Lazy\.url\('\/vendor\/jamesdsp\/jamesdsp-node\.mjs'\)/); assert.match(feature, /Lazy\.url\('\/vendor\/jamesdsp\/dsp\/jamesdsp\.wasm'\)/); }); test('v1 wrapper rejects text effects and omits them from portable presets', () => { const node = readFileSync(join(root, 'vendor/jamesdsp/jamesdsp-node.mjs'), 'utf8'); const worklet = readFileSync(join(root, 'vendor/jamesdsp/worklet.mjs'), 'utf8'); assert.match(node, /Text effects are disabled in this player version/); assert.match(node, /toJSON\(\) \{return \{version:1,params:/); assert.doesNotMatch(worklet, /data\.type==='text'/); }); test('vendor provenance pins the source and retains both supplied license texts', () => { const version = readFileSync(join(root, 'vendor/jamesdsp/VERSION.txt'), 'utf8'); assert.match(version, /77be0b2e825a20ba98feff33d16dd0a43232ef3b/); assert.match(version, /GPL-2\.0 text/); assert.ok(readFileSync(join(root, 'vendor/jamesdsp/LICENSE.txt'), 'utf8').includes('Version 3')); assert.ok(readFileSync(join(root, 'vendor/jamesdsp/UPSTREAM-MAIN-LICENSE.txt'), 'utf8').includes('Version 2')); });