gestion_table_tournante_libre/src/interface/generation/Avancement.navigateur.test.js
Mathieu Benoit c6082c3af2 [IMP] proposals, generation, badges, preview: cards and grouped headers
The proposal table had a dozen measure columns with no grouping. Five
group headers now gather neighbouring measures without changing any
column text; numbers align right in tabular figures, and the kept
placement row wears the Retenu tint and a « retenue » pill. Generation
settings and progress, badges and the paper choice become cards, each
paper a distinct choice; the preview toolbar groups its commands. The
printed paper is unchanged. Checked: node 172, browser 162.

--- FR ---

[IMP] propositions, génération, badges, aperçu : cartes, intitulés

Le tableau des propositions alignait une douzaine de mesures sans
groupe. Cinq intitulés de groupe réunissent les mesures voisines sans
changer le texte d'aucune colonne ; les nombres s'alignent à droite en
chiffres tabulaires, la ligne du retenu porte la teinte Retenu et une
pastille « retenue ». Réglages et avancement, badges et papier
deviennent des cartes, chaque papier un choix distinct ; la barre de
l'aperçu groupe ses commandes. Le papier imprimé ne change pas.
Vérifié : node 172, navigateur 162.

Assisted-by: Claude Opus 5.5
2026-10-11 00:58:07 -04:00

77 lines
3.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// © 2026 TechnoLibre (http://www.technolibre.ca)
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
// L'avancement d'une génération dans un vrai moteur de rendu (§ 5.10) : la
// barre de progression se voit. Le composant est monté seul, dans un
// conteneur de largeur fixée ; la barre se lit par son rôle, son
// remplissage par son premier enfant, les couleurs par leurs jetons, dans
// les deux thèmes.
//
// Le projet navigateur emploie expect, et test et describe de Vitest
// (§ 14.8).
import '../jetons.css';
import { flushSync, mount, unmount } from 'svelte';
import { afterEach, describe, expect, test } from 'vitest';
import { creerHorlogePilotee } from '../../application/horloge.js';
import { TABLES_APPLICATION } from '../../application/libelles.js';
import { creerTraduction } from '../../application/traduction.js';
import { couleurDeJeton } from '../../../test/navigateur/captures.js';
import { composantes, contraste, sousTheme } from '../../../test/navigateur/rendu.js';
import { TABLES_INTERFACE } from '../libelles.js';
import Avancement from './Avancement.svelte';
const { t } = creerTraduction([...TABLES_APPLICATION, ...TABLES_INTERFACE]);
const montes = [];
afterEach(() => {
for (const { composant, conteneur } of montes.splice(0)) {
unmount(composant);
conteneur.remove();
}
});
// Monte Avancement dans un conteneur de 600 px.
function monter(props) {
const conteneur = document.createElement('div');
conteneur.style.width = '600px';
document.body.prepend(conteneur);
const contexte = new Map([
['t', t],
['horloge', creerHorlogePilotee()],
]);
const composant = mount(Avancement, { target: conteneur, props, context: contexte });
flushSync();
montes.push({ composant, conteneur });
return conteneur;
}
describe('l’avancement se voit (§ 5.10)', () => {
test('la barre occupe la largeur de son conteneur ; son remplissage, au prorata, se peint de la teinte de l’action à 3:1 sur la piste, dans les deux thèmes', async () => {
const conteneur = monter({ fait: 250, total: 1000, annuler: () => {} });
const barre = conteneur.querySelector('[role="progressbar"]');
expect(barre.getAttribute('aria-valuenow')).toBe('250');
expect(barre.getBoundingClientRect().width).toBeGreaterThanOrEqual(0.9 * conteneur.getBoundingClientRect().width);
const plein = barre.firstElementChild;
expect(plein.getBoundingClientRect().width / barre.clientWidth).toBeCloseTo(0.25, 2);
expect(barre.getBoundingClientRect().height).toBeGreaterThanOrEqual(8);
for (const theme of ['clair', 'sombre']) {
await sousTheme(theme, async () => {
const remplissage = composantes(getComputedStyle(plein).backgroundColor);
const piste = composantes(getComputedStyle(barre).backgroundColor);
expect(remplissage.join(), theme).toBe(couleurDeJeton('--couleur-action-fond').join());
expect(piste.join(), theme).toBe(couleurDeJeton('--couleur-carte-fond-sourd').join());
expect(contraste(remplissage, piste), theme).toBeGreaterThanOrEqual(3);
});
}
});
test('le compte se lit en mots au-dessus de la barre, et « Annuler la génération » la suit', () => {
const conteneur = monter({ fait: 250, total: 1000, annuler: () => {} });
const barre = conteneur.querySelector('[role="progressbar"]');
const texte = [...conteneur.querySelectorAll('p')].find((p) => p.textContent === t('generation.avancement.texte', { fait: 250, total: 1000 }));
expect(texte).toBeDefined();
expect(texte.getBoundingClientRect().bottom).toBeLessThanOrEqual(barre.getBoundingClientRect().top);
const annuler = conteneur.querySelector('[data-commande="annuler"]');
expect(annuler.getBoundingClientRect().top).toBeGreaterThanOrEqual(barre.getBoundingClientRect().bottom);
});
});