feedBack/tests/js/app_tour_library.test.js
2026-06-16 18:47:13 +02:00

64 lines
3.0 KiB
JavaScript

const { test } = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const tourScript = path.join(__dirname, '..', '..', 'plugins', 'app_tour_library', 'script.js');
const SRC = fs.readFileSync(tourScript, 'utf8');
function extractBlock(src, signature) {
const start = src.indexOf(signature);
assert.ok(start !== -1, `signature '${signature}' not found`);
const openBrace = src.indexOf('{', start);
assert.ok(openBrace !== -1, `opening brace after '${signature}' not found`);
let depth = 1;
let i = openBrace + 1;
while (i < src.length && depth > 0) {
const ch = src[i];
if (ch === '{') depth++;
else if (ch === '}') depth--;
i++;
}
assert.ok(depth === 0, `unbalanced braces after '${signature}'`);
return src.slice(start, i);
}
test('library tour registers dynamic steps for provider-aware instructions', () => {
const register = extractBlock(SRC, 'function _register()');
assert.match(register, /buildSteps:\s*_buildSteps/,
'Library tour registration must use buildSteps so provider instructions can be conditional');
});
test('library tour adds provider step only when multiple browsable providers exist', () => {
const providerCheck = extractBlock(SRC, 'async function _hasMultipleProviders()');
assert.match(providerCheck, /fetch\(\s*['"]\/api\/library\/providers['"]\s*\)/,
'Provider count must come from the library providers endpoint');
assert.match(providerCheck, /filter\(_isBrowsableProvider\)/,
'Provider count must ignore non-browsable providers');
assert.match(providerCheck, /providers\.length\s*>\s*1/,
'Provider step must require more than one provider');
const buildSteps = extractBlock(SRC, 'async function _buildSteps()');
assert.match(buildSteps, /!\(await\s+_hasMultipleProviders\(\)\)/,
'buildSteps must skip the provider step unless multiple providers are present');
assert.match(buildSteps, /splice\([\s\S]*PROVIDER_STEP/,
'buildSteps must insert the provider instruction into the tour');
});
test('library tour inserts provider step after the search step', () => {
const buildSteps = extractBlock(SRC, 'async function _buildSteps()');
assert.match(buildSteps, /insertAt\s*===\s*-1\s*\?\s*1\s*:\s*insertAt\s*\+\s*1/,
'Provider step must be inserted after the search step when search is found');
assert.match(buildSteps, /splice\([\s\S]*PROVIDER_STEP/,
'buildSteps must splice PROVIDER_STEP into the tour');
});
test('provider tour step targets the library provider selector', () => {
assert.match(SRC, /id:\s*['"]library-provider['"]/,
'Provider step must have a stable id');
assert.match(SRC, /selector:\s*['"]#lib-provider['"]/,
'Provider step must spotlight the provider selector');
assert.match(SRC, /waitFor:\s*['"]#lib-provider['"]/,
'Provider step must wait for the selector before showing');
});