tests/rename-settings.test.cjs
Rama main · réplica de lectura del repositorio original.
const fs = require('fs');
const path = require('path');
const vm = require('vm');
const ts = require('typescript');
const read = (...p) => fs.readFileSync(path.join(__dirname, '..', ...p), 'utf8');
const assert = (cond, msg) => { if (!cond) throw new Error(msg); };
// Pull one top-level `const name = ... };` block out of a file and run it with the given stand-ins.
const load = (src, name, sandbox) => {
const block = src.match(new RegExp(`const ${name} = [\\s\\S]*?\\n\\};`));
assert(block, `${name} not found`);
const js = ts.transpileModule(block[0], { compilerOptions: { target: ts.ScriptTarget.ES2020 } }).outputText;
return vm.runInNewContext(`${js}\n${name}`, sandbox);
};
const tab = read('frontend', 'src', 'components', 'settings', 'RenameSettingsTab.tsx');
const SAMPLE = load(tab, 'SAMPLE', {});
const renderPreview = load(tab, 'renderPreview', {});
const buildPreview = load(tab, 'buildPreview', { SAMPLE, renderPreview });
const normalizeConflict = load(tab, 'normalizeConflict', {});
// Empty tokens leave no empty brackets, like the backend renderer
assert(renderPreview('{Title} ({Region}) [{Languages}]', { Title: 'X', Region: '', Languages: '' }) === 'X', 'empty () or [] left in the preview');
assert(renderPreview('{Title} - DLC - {ContentName}', { Title: 'X', ContentName: '' }) === 'X - DLC', 'dangling separator left in the preview');
// Only separators next to an empty token go, a dash of the title stays
const lacrimosa = 'Ys VIII -Lacrimosa of DANA-';
assert(renderPreview('{Title}', { Title: lacrimosa }) === lacrimosa, 'trailing dash of the title cut in the preview');
assert(renderPreview('{Title}', { Title: '-Zero-' }) === '-Zero-', 'dashes of the title cut in the preview');
assert(renderPreview('{Title} - {Version}', { Title: lacrimosa, Version: '' }) === lacrimosa, 'separator before an empty token left, or the title cut');
assert(renderPreview('{Region} - {Title}', { Region: '', Title: '-Zero-' }) === '-Zero-', 'separator after an empty token left, or the title cut');
assert(renderPreview('{Title} - Update {Version}', { Title: '-Zero-', Version: '' }) === '-Zero- - Update', 'empty version not dropped cleanly');
assert(renderPreview('{Title} - {Region} - {Version}', { Title: 'X', Region: '', Version: '1.02' }) === 'X - 1.02', 'separators around an empty token not collapsed');
assert(renderPreview('{Title}-{Region}-{Version}', { Title: 'X', Region: '', Version: '1.02' }) === 'X-1.02', 'dashes around an empty token not collapsed');
// The group suffix is shown once, on every template
const preview = buildPreview({ includeReleaseGroupInFilename: true, releaseGroupSuffix: '[{ReleaseGroup}]', mainFileTemplate: '{Title}' });
assert(preview.main === 'Chrono Trigger [FitGirl].zip', `main preview is ${preview.main}`);
assert(preview.update.endsWith(' [FitGirl].zip'), `update preview is ${preview.update}`);
assert(preview.dlc.endsWith(' [FitGirl].zip'), `dlc preview is ${preview.dlc}`);
assert(!/\.replace\('\.zip'/.test(tab), 'preview still glues a second name onto the first');
// Overwrite is gone; a stored one shows as Skip
assert(normalizeConflict('Overwrite') === 'Skip', 'Overwrite not mapped to Skip');
assert(normalizeConflict('Suffix') === 'Suffix', 'Suffix lost');
assert(normalizeConflict(undefined) === 'Skip', 'missing value not mapped to Skip');
assert(!tab.includes('value="Overwrite"'), 'Overwrite is still offered');
assert(tab.includes("{'{Disc}'}") && tab.includes('renameTokenDisc'), '{Disc} token not documented');
const translations = read('frontend', 'src', 'i18n', 'translations.ts');
const count = key => (translations.match(new RegExp(`\\b${key}:`, 'g')) || []).length;
assert(count('renameTokenDisc') === 7, 'renameTokenDisc is not in all 7 languages');
assert(count('missingRetentionDesc') === 7, 'missingRetentionDesc is not in all 7 languages');
const en = translations.slice(translations.indexOf('\n en: {'), translations.indexOf('\n fr: {'));
assert(/missingRetentionDesc: .*Monitored games are kept/.test(en), 'en retention text does not say monitored games are kept');
assert(!translations.includes('renameConflictOverwrite'), 'renameConflictOverwrite still translated');
console.log('rename-settings: ok');