gestion_table_tournante_libre/src/application/traduction.test.js

112 lines
4.9 KiB
JavaScript
Raw Normal View History

// © 2026 TechnoLibre (http://www.technolibre.ca)
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
// Épreuves du mécanisme de traduction (§ 14.6) : une clé absente lève et se
// nomme, une clé de deux tables lève à la création, les clés s'énumèrent
// triées, une entrée en compose une autre, et la langue témoin encadre le
// résultat entier de t d'une seule paire de marques. Les tables d'épreuve sont
// inventées.
import assert from 'node:assert/strict';
import { describe, test } from '../../test/lanceur.js';
import { MARQUE_TEMOIN, creerTraduction } from './traduction.js';
const { ouverture: O, fermeture: F } = MARQUE_TEMOIN;
const TABLE_A = new Map([
['essai.vide', '\u{2014}'],
['essai.salut', ({ nom }) => `Bonjour ${nom}`],
['essai.compose', ({ nom }, texte) => `${texte('essai.salut', { nom })}, ${texte('essai.vide')}`],
]);
const TABLE_B = new Map([
['AUTRE_CODE', () => 'Un code d’essai.'],
['autre.libelle', 'Un libellé'],
]);
describe('traduction : le mécanisme (§ 14.6)', () => {
test('les deux marques de la langue témoin sont U+2045 et U+2046, et figées', () => {
assert.equal(O, '\u{2045}');
assert.equal(F, '\u{2046}');
assert.ok(Object.isFrozen(MARQUE_TEMOIN));
});
test('une clé absente lève RangeError, et le message nomme la clé ; jamais la clé brute, jamais une chaîne vide', () => {
const { t } = creerTraduction([TABLE_A]);
assert.throws(() => t('essai.inconnue'), (erreur) => {
assert.ok(erreur instanceof RangeError);
assert.match(erreur.message, /essai\.inconnue/);
return true;
});
assert.throws(() => t(undefined), RangeError);
assert.throws(() => t('constructor'), RangeError);
});
test('une clé portée par deux tables lève à la création, et se nomme', () => {
const doublon = new Map([['essai.salut', 'Salut']]);
assert.throws(() => creerTraduction([TABLE_A, doublon]), (erreur) => {
assert.ok(erreur instanceof RangeError);
assert.match(erreur.message, /essai\.salut/);
return true;
});
});
test('cles() énumère toutes les clés des tables, triées par unités UTF-16', () => {
const { cles } = creerTraduction([TABLE_A, TABLE_B]);
const attendues = ['AUTRE_CODE', 'autre.libelle', 'essai.compose', 'essai.salut', 'essai.vide'];
assert.equal(cles().length, 5);
assert.deepEqual(cles(), attendues);
});
test('une chaîne se rend telle quelle, une fonction reçoit ses détails, et une entrée en compose une autre par texte', () => {
const { t, langue } = creerTraduction([TABLE_A, TABLE_B]);
assert.equal(langue, 'fr');
assert.equal(t('autre.libelle'), 'Un libellé');
assert.equal(t('essai.salut', { nom: 'Iris Ombrelle' }), 'Bonjour Iris Ombrelle');
assert.equal(t('essai.compose', { nom: 'Théo Pervenche' }), 'Bonjour Théo Pervenche, \u{2014}');
assert.equal(t('AUTRE_CODE'), 'Un code d’essai.');
});
test("une fonction appelée sans détails en reçoit un objet vide ; une entrée qui ne rend pas une chaîne lève", () => {
const table = new Map([
['essai.details', (details) => `${Object.keys(details).length}`],
['essai.nombre', () => 3],
]);
const { t } = creerTraduction([table]);
assert.equal(t('essai.details'), '0');
assert.equal(t('essai.details', null), '0');
assert.throws(() => t('essai.nombre'), TypeError);
});
test("une table qui n'est pas une Map, une entrée ni chaîne ni fonction, une langue inconnue lèvent à la création", () => {
assert.throws(() => creerTraduction([{ 'essai.objet': 'x' }]), TypeError);
assert.throws(() => creerTraduction([new Map([['essai.nombre', 4]])]), TypeError);
assert.throws(() => creerTraduction([TABLE_A], { langue: 'en' }), RangeError);
});
});
describe('traduction : la langue témoin (§ 14.6)', () => {
test('t encadre son résultat de la marque, une fois', () => {
const { t, langue } = creerTraduction([TABLE_A, TABLE_B], { langue: 'temoin' });
assert.equal(langue, 'temoin');
assert.equal(t('essai.vide'), `${O}\u{2014}${F}`);
assert.equal(t('autre.libelle'), `${O}Un libellé${F}`);
});
test('une fonction de détails est décorée sur son résultat entier', () => {
const { t } = creerTraduction([TABLE_A], { langue: 'temoin' });
assert.equal(t('essai.salut', { nom: 'Ondine Lacasse' }), `${O}Bonjour Ondine Lacasse${F}`);
});
test("une composition ne porte qu'une paire de marques : texte compose en français", () => {
const { t } = creerTraduction([TABLE_A], { langue: 'temoin' });
const rendu = t('essai.compose', { nom: 'Grisaille' });
assert.equal(rendu, `${O}Bonjour Grisaille, \u{2014}${F}`);
assert.equal(rendu.split(O).length - 1, 1);
assert.equal(rendu.split(F).length - 1, 1);
});
test('une clé absente lève en langue témoin comme en français', () => {
const { t } = creerTraduction([TABLE_A], { langue: 'temoin' });
assert.throws(() => t('essai.inconnue'), RangeError);
});
});