/** * Tests des PRESETS de traitements (v1.9.4 — miroir de `PKPresets.kt`) : * le modèle ESE ANALYTIQUE couvre 6 esters injectables — les presets de * création doivent offrir les 6 (comme TFS offre les 7 du V3C et WHSAH * les 6 du fit Mona). Avant v1.9.4, les presets ESE n'offraient que * EV/EU/EEn (l'héritage des tables ODS) — remontée : « les presets n'ont * pas été mis à jour lors de l'ajout du modèle source ESE ». */ import { test, describe } from 'node:test'; import assert from 'node:assert/strict'; import { all } from '../js/pk/presets.js'; describe('PKPresets web (presets ESE étendus — v1.9.4)', () => { test('les presets ESE couvrent les 6 esters du fit analytique', () => { const eseInjectable = all.filter((p) => p.pkModel === 'ESE' && p.esterType !== 'NONE'); const esters = eseInjectable.map((p) => p.esterType).sort(); assert.deepEqual(esters, ['EB', 'EC', 'EEN', 'EU', 'EUCS', 'EV']); }); test('chaque ester couvert a EXACTEMENT un preset ESE (pas de doublon)', () => { const eseInjectable = all.filter((p) => p.pkModel === 'ESE' && p.esterType !== 'NONE'); const names = eseInjectable.map((p) => p.nameKey); assert.equal(new Set(names).size, names.length); }); test('chaque preset a une clé i18n présente dans EN et FR', async () => { const { store } = await import('../js/data/store.js'); store.setBackend(new Map()); // Node : pas de localStorage const i18n = await import('../js/util/i18n.js'); // t() lit la langue du store (pas de setLanguage exporté) : on force // successivement 'en' puis 'fr' via les settings (miroir de l'app). for (const lang of ['en', 'fr']) { store.setSettings({ language: lang }); for (const p of all) { // t() retombe sur la clé brute si absente : un libellé égal à la // clé = clé manquante (leçon §12 web : une string manquante // s'affiche brute dans l'UI) assert.notEqual(i18n.t(p.nameKey), p.nameKey, `clé i18n manquante (${lang}) : ${p.nameKey}`); } } }); test('les presets TFS (7) et WHSAH (6) restent inchangés', () => { const injectables = (model) => all.filter((p) => p.pkModel === model && p.esterType !== 'NONE'); assert.equal(injectables('TFS').length, 7); assert.equal(injectables('WHS').length, 6); }); test('choicesForModel (éditeur + dialog de dose) suit la couverture du fit ESE', async () => { // v1.9.4 : l'éditeur liste choicesForModel(model) — si ce helper restait // sur la couverture des tables ODS (3 esters), l'éditeur n'offrirait pas // EC/EB/EUCS même avec les presets à jour (parité Android v1.9.0). const { choicesForModel } = await import('../js/data/models.js'); assert.deepEqual(choicesForModel('ESE').sort(), ['EB', 'EC', 'EEN', 'EU', 'EUCS', 'EV']); // TFS reste EXPLICITE à 7 (pas d'EUCS dans le V3C — sinon 0 pg/mL) et // WHSAH à 6 (PEP non couvert). assert.deepEqual(choicesForModel('TFS').sort(), ['EB', 'EC', 'ECS', 'EEN', 'EU', 'EV', 'PEP']); assert.deepEqual(choicesForModel('WHS').sort(), ['EB', 'EC', 'ECS', 'EEN', 'EU', 'EV']); assert.equal(choicesForModel('TFS').includes('EUCS'), false); }); test('les presets ESE non-injectables (gel/patch/oral) restent en Bateman', () => { const eseNonInjectable = all.filter( (p) => p.pkModel === 'ESE' && (p.esterType === 'NONE' || p.esterType == null), ); assert.ok(eseNonInjectable.length >= 3, 'gel/patch/oral toujours présents'); assert.ok(eseNonInjectable.every((p) => p.esterType === 'NONE')); }); });