The working screens of an evening. The home screen lists the events of the working folder, asks its question, loads demos, copies, renames, imports and deletes, and shows what the trash holds. An open event frames its mode, offers Modifier, Débloquer and a confirmed lock takeover, and shows its warnings. Participants get a grid, a form and a file; an import goes through a preview and a report; tables, the default and tours have their screens; the plan draws tables, chairs, empty seats and names. Checked: 2342 node, 356 browser, 60 node-long; the Electron start check. --- FR --- [ADD] interface : liste, événement, participants, import, tables, plan Les écrans de travail d'une soirée. L'accueil liste les événements du dossier de travail, pose sa question, charge les démonstrations, copie, renomme, importe et supprime, et montre ce que tient la corbeille. Un événement ouvert encadre son mode, offre Modifier, Débloquer et une reprise de verrou confirmée, et montre ses avertissements. Les participants ont une grille, un formulaire et une fiche ; un import passe par un aperçu et un rapport ; tables, défaut et tours ont leurs écrans ; le plan dessine tables, chaises, sièges vides et noms. Vérifié : 2342 node, 356 navigateur, 60 node-long ; démarrage d'Electron. Assisted-by: Claude Opus 5.5
66 lines
3.2 KiB
JavaScript
66 lines
3.2 KiB
JavaScript
// © 2026 TechnoLibre (http://www.technolibre.ca)
|
||
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
|
||
|
||
// Épreuves du relais CSV de l'application (§ 13.4, § 10.1) : l'interface
|
||
// atteint src/csv par ce module, qui réexporte ses fonctions telles quelles
|
||
// et lie le motif du CSV des refus au libellé français. Les noms sont
|
||
// inventés.
|
||
import assert from 'node:assert/strict';
|
||
import { describe, test } from '../../test/lanceur.js';
|
||
import * as apercu from '../csv/apercu.js';
|
||
import * as colonnes from '../csv/colonnes.js';
|
||
import * as encodage from '../csv/encodage.js';
|
||
import * as exportCsv from '../csv/export.js';
|
||
import * as importCsv from '../csv/import.js';
|
||
import { decouper } from '../csv/lecture.js';
|
||
import * as normalisation from '../csv/normalisation.js';
|
||
import * as relais from './csv.js';
|
||
import { libelle } from './libelles.js';
|
||
|
||
describe('csv : le relais de src/csv pour l’interface (§ 13.4)', () => {
|
||
test('decoder, apercevoir, exporterParticipants, bilanRemplacement, cleNormalisee et CHAMPS sont ceux de src/csv', () => {
|
||
const attendus = [
|
||
['decoder', encodage.decoder],
|
||
['apercevoir', apercu.apercevoir],
|
||
['exporterParticipants', exportCsv.exporterParticipants],
|
||
['bilanRemplacement', importCsv.bilanRemplacement],
|
||
['cleNormalisee', normalisation.cleNormalisee],
|
||
];
|
||
assert.equal(attendus.length, 5);
|
||
for (const [nom, fonction] of attendus) {
|
||
assert.equal(typeof fonction, 'function', nom);
|
||
assert.equal(relais[nom], fonction, nom);
|
||
}
|
||
assert.equal(relais.CHAMPS, colonnes.CHAMPS);
|
||
assert.deepEqual(Object.keys(relais).sort(), [
|
||
'CHAMPS', 'apercevoir', 'bilanRemplacement', 'cleNormalisee', 'decoder', 'exporterParticipants', 'exporterRefus',
|
||
]);
|
||
});
|
||
|
||
test("exporterRefus écrit sous l'en-tête motif exactement libelle(code, details) d'une ligne refusée NOM_ABSENT", () => {
|
||
const texte = ['nom;prenom', 'Ombrelle;Iris', ';Théo', 'Pervenche;Ondine', ''].join('\r\n');
|
||
const lu = relais.apercevoir(texte);
|
||
assert.equal(lu.refusees.length, 1);
|
||
const [{ code, brut, ...details }] = lu.refusees;
|
||
assert.equal(code, 'NOM_ABSENT');
|
||
const { enregistrements } = decouper(relais.decoder(relais.exporterRefus(lu)).texte, ';');
|
||
assert.equal(enregistrements.length, 2);
|
||
const [entete, ligne] = enregistrements;
|
||
const rang = entete.indexOf('motif');
|
||
assert.ok(rang >= 0, entete.join(';'));
|
||
assert.equal(ligne[rang], libelle('NOM_ABSENT', details));
|
||
assert.equal(ligne[entete.indexOf('ligne')], '3');
|
||
assert.ok(brut.length > 0);
|
||
});
|
||
|
||
test('exporterRefus écrit les refus reçus en second argument, à la place de ceux de l’aperçu', () => {
|
||
const lu = relais.apercevoir(['nom;exclu', 'Ombrelle;peut-être', ''].join('\r\n'));
|
||
assert.equal(lu.refusees.length, 1);
|
||
const vide = decouper(relais.decoder(relais.exporterRefus(lu, [])).texte, ';').enregistrements;
|
||
assert.deepEqual(vide, [['nom', 'exclu', 'ligne', 'motif']]);
|
||
const [entete, ligne] = decouper(relais.decoder(relais.exporterRefus(lu, lu.refusees)).texte, ';').enregistrements;
|
||
const [{ code, brut, ...details }] = lu.refusees;
|
||
assert.equal(ligne[entete.indexOf('motif')], libelle(code, details));
|
||
assert.ok(brut.length > 0);
|
||
});
|
||
});
|