[ADD] skeleton: Capacitor web app that shows its dated version
The engine to come must be proven against oracles under node in seconds,
so the skeleton sets three test projects: node, watched; node-long; and a
real Chromium that reads computed styles in both themes. The version
lives in version.json alone; a check refuses eight divergences — technical
form, generated module, changelog head, stray version strings — and a
build guard keeps test files and fixture assets out of the bundle.
Checked: on this commit alone, 73 node tests, 7 browser tests and the
version check pass; the guard fails on a fixture joined as an asset.
--- FR ---
[ADD] squelette : application web Capacitor qui affiche sa version datée
Le moteur à venir doit s'éprouver contre des oracles sous node en
quelques secondes : le squelette pose trois projets d'épreuve — node,
sous surveillance ; node-long ; et un vrai Chromium qui lit le style
calculé dans les deux thèmes. La version vit dans version.json seul ; un
contrôle refuse huit divergences — forme technique, module engendré,
tête du changelog, chaînes de version égarées — et une garde de
construction tient fichiers et données d'épreuve hors du paquet.
Vérifié : sur ce commit seul, 73 épreuves node, 7 navigateur et le
contrôle de version passent ; la garde échoue sur une donnée jointe.
Assisted-by: Claude Opus 5.5
2026-10-05 13:13:13 -04:00
|
|
|
// © 2026 TechnoLibre (http://www.technolibre.ca)
|
|
|
|
|
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
|
|
|
|
|
|
|
|
|
|
// Épreuve de rendu du bandeau d'application (§ 8.4, § 18.6), dans un vrai
|
|
|
|
|
// moteur de rendu. Le test interroge le rendu, jamais la présence d'une
|
|
|
|
|
// classe (§ 14.2) : la visibilité de chaque élément, la boîte où la mise en
|
|
|
|
|
// page le pose et l'élément qu'atteint le centre de cette boîte, le style
|
|
|
|
|
// calculé, le texte, le titre de la fenêtre. Il ne lit aucun pixel : le
|
|
|
|
|
// contraste se calcule sur les couleurs calculées, qui ne sont les couleurs
|
|
|
|
|
// peintes que sans opacité partielle, filtre ni mode de fusion — ce qu'une
|
|
|
|
|
// épreuve vérifie dans l'ascendance de chaque texte (§ 14.5). Les épreuves de
|
[ADD] interface: colour tokens, two themes, checked palette, marks
The plan's colours carry meaning — a conflict, a reservation, a mode — so
they must stay readable for every reader and in both themes. jetons.css
defines the tokens for the light and dark themes, set by data-theme on the
root; palette.js reads them from the stylesheet text and checks, by
computation, contrast to WCAG and separation under the three
dichromacies, keeping the conflict hue reserved. The theme follows the
system at each start and the operator's choice lasts the session.
Checked: 1709 node and 43 browser tests.
--- FR ---
[ADD] interface : jetons de couleur, deux thèmes, palette, marques
Les couleurs du plan portent un sens — un conflit, une réservation, un mode
— et doivent rester lisibles pour tout lecteur et dans les deux thèmes.
jetons.css définit les jetons des thèmes clair et sombre, posés par
data-theme sur la racine ; palette.js les lit dans le texte de la feuille
et contrôle, par calcul, le contraste au sens des WCAG et la séparation
sous les trois dichromaties, la teinte du conflit restant réservée. Le
thème suit le système à chaque démarrage ; le choix de l'opérateur vaut
pour la séance.
Vérifié : 1709 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:12 -04:00
|
|
|
// visibilité, de contraste et d'opacité passent par les deux thèmes, que
|
|
|
|
|
// l'attribut data-theme de <html> choisit (§ 19.2). Le contraste est celui de
|
|
|
|
|
// palette.js, seule formule des WCAG du dépôt.
|
[ADD] skeleton: Capacitor web app that shows its dated version
The engine to come must be proven against oracles under node in seconds,
so the skeleton sets three test projects: node, watched; node-long; and a
real Chromium that reads computed styles in both themes. The version
lives in version.json alone; a check refuses eight divergences — technical
form, generated module, changelog head, stray version strings — and a
build guard keeps test files and fixture assets out of the bundle.
Checked: on this commit alone, 73 node tests, 7 browser tests and the
version check pass; the guard fails on a fixture joined as an asset.
--- FR ---
[ADD] squelette : application web Capacitor qui affiche sa version datée
Le moteur à venir doit s'éprouver contre des oracles sous node en
quelques secondes : le squelette pose trois projets d'épreuve — node,
sous surveillance ; node-long ; et un vrai Chromium qui lit le style
calculé dans les deux thèmes. La version vit dans version.json seul ; un
contrôle refuse huit divergences — forme technique, module engendré,
tête du changelog, chaînes de version égarées — et une garde de
construction tient fichiers et données d'épreuve hors du paquet.
Vérifié : sur ce commit seul, 73 épreuves node, 7 navigateur et le
contrôle de version passent ; la garde échoue sur une donnée jointe.
Assisted-by: Claude Opus 5.5
2026-10-05 13:13:13 -04:00
|
|
|
//
|
|
|
|
|
// Le projet navigateur n'importe pas node:assert/strict : côté navigateur,
|
|
|
|
|
// Vite le remplace par un module qui lève une erreur à tout accès. Il emploie
|
|
|
|
|
// expect, et prend test et describe chez Vitest plutôt que dans
|
|
|
|
|
// test/lanceur.js, dont le repli vers node:test ne vaut que pour la série node.
|
|
|
|
|
import { afterEach, beforeEach, describe, expect, test } from 'vitest';
|
|
|
|
|
import { flushSync, mount, unmount } from 'svelte';
|
|
|
|
|
import App from './App.svelte';
|
[ADD] interface: colour tokens, two themes, checked palette, marks
The plan's colours carry meaning — a conflict, a reservation, a mode — so
they must stay readable for every reader and in both themes. jetons.css
defines the tokens for the light and dark themes, set by data-theme on the
root; palette.js reads them from the stylesheet text and checks, by
computation, contrast to WCAG and separation under the three
dichromacies, keeping the conflict hue reserved. The theme follows the
system at each start and the operator's choice lasts the session.
Checked: 1709 node and 43 browser tests.
--- FR ---
[ADD] interface : jetons de couleur, deux thèmes, palette, marques
Les couleurs du plan portent un sens — un conflit, une réservation, un mode
— et doivent rester lisibles pour tout lecteur et dans les deux thèmes.
jetons.css définit les jetons des thèmes clair et sombre, posés par
data-theme sur la racine ; palette.js les lit dans le texte de la feuille
et contrôle, par calcul, le contraste au sens des WCAG et la séparation
sous les trois dichromaties, la teinte du conflit restant réservée. Le
thème suit le système à chaque démarrage ; le choix de l'opérateur vaut
pour la séance.
Vérifié : 1709 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:12 -04:00
|
|
|
import { contraste } from './palette.js';
|
[ADD] skeleton: Capacitor web app that shows its dated version
The engine to come must be proven against oracles under node in seconds,
so the skeleton sets three test projects: node, watched; node-long; and a
real Chromium that reads computed styles in both themes. The version
lives in version.json alone; a check refuses eight divergences — technical
form, generated module, changelog head, stray version strings — and a
build guard keeps test files and fixture assets out of the bundle.
Checked: on this commit alone, 73 node tests, 7 browser tests and the
version check pass; the guard fails on a fixture joined as an asset.
--- FR ---
[ADD] squelette : application web Capacitor qui affiche sa version datée
Le moteur à venir doit s'éprouver contre des oracles sous node en
quelques secondes : le squelette pose trois projets d'épreuve — node,
sous surveillance ; node-long ; et un vrai Chromium qui lit le style
calculé dans les deux thèmes. La version vit dans version.json seul ; un
contrôle refuse huit divergences — forme technique, module engendré,
tête du changelog, chaînes de version égarées — et une garde de
construction tient fichiers et données d'épreuve hors du paquet.
Vérifié : sur ce commit seul, 73 épreuves node, 7 navigateur et le
contrôle de version passent ; la garde échoue sur une donnée jointe.
Assisted-by: Claude Opus 5.5
2026-10-05 13:13:13 -04:00
|
|
|
import { VERSION } from '../version.genere.js';
|
|
|
|
|
|
|
|
|
|
const TRANSPARENT = 'rgba(0, 0, 0, 0)';
|
[ADD] interface: colour tokens, two themes, checked palette, marks
The plan's colours carry meaning — a conflict, a reservation, a mode — so
they must stay readable for every reader and in both themes. jetons.css
defines the tokens for the light and dark themes, set by data-theme on the
root; palette.js reads them from the stylesheet text and checks, by
computation, contrast to WCAG and separation under the three
dichromacies, keeping the conflict hue reserved. The theme follows the
system at each start and the operator's choice lasts the session.
Checked: 1709 node and 43 browser tests.
--- FR ---
[ADD] interface : jetons de couleur, deux thèmes, palette, marques
Les couleurs du plan portent un sens — un conflit, une réservation, un mode
— et doivent rester lisibles pour tout lecteur et dans les deux thèmes.
jetons.css définit les jetons des thèmes clair et sombre, posés par
data-theme sur la racine ; palette.js les lit dans le texte de la feuille
et contrôle, par calcul, le contraste au sens des WCAG et la séparation
sous les trois dichromaties, la teinte du conflit restant réservée. Le
thème suit le système à chaque démarrage ; le choix de l'opérateur vaut
pour la séance.
Vérifié : 1709 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:12 -04:00
|
|
|
const THEMES = ['clair', 'sombre'];
|
[ADD] skeleton: Capacitor web app that shows its dated version
The engine to come must be proven against oracles under node in seconds,
so the skeleton sets three test projects: node, watched; node-long; and a
real Chromium that reads computed styles in both themes. The version
lives in version.json alone; a check refuses eight divergences — technical
form, generated module, changelog head, stray version strings — and a
build guard keeps test files and fixture assets out of the bundle.
Checked: on this commit alone, 73 node tests, 7 browser tests and the
version check pass; the guard fails on a fixture joined as an asset.
--- FR ---
[ADD] squelette : application web Capacitor qui affiche sa version datée
Le moteur à venir doit s'éprouver contre des oracles sous node en
quelques secondes : le squelette pose trois projets d'épreuve — node,
sous surveillance ; node-long ; et un vrai Chromium qui lit le style
calculé dans les deux thèmes. La version vit dans version.json seul ; un
contrôle refuse huit divergences — forme technique, module engendré,
tête du changelog, chaînes de version égarées — et une garde de
construction tient fichiers et données d'épreuve hors du paquet.
Vérifié : sur ce commit seul, 73 épreuves node, 7 navigateur et le
contrôle de version passent ; la garde échoue sur une donnée jointe.
Assisted-by: Claude Opus 5.5
2026-10-05 13:13:13 -04:00
|
|
|
|
|
|
|
|
// Composantes [r, g, b, a] d'une couleur calculée. Chromium la rend sous la
|
|
|
|
|
// forme « rgb(r, g, b) » ou « rgba(r, g, b, a) » quand la source est une
|
|
|
|
|
// couleur sRGB ; toute autre forme fait échouer l'épreuve plutôt que de la
|
|
|
|
|
// laisser passer sans mesure.
|
|
|
|
|
function composantes(couleur) {
|
|
|
|
|
const m = /^rgba?\((\d+), (\d+), (\d+)(?:, ([\d.]+))?\)$/.exec(couleur);
|
|
|
|
|
if (m === null) {
|
|
|
|
|
throw new Error(`couleur calculée illisible : ${couleur}`);
|
|
|
|
|
}
|
|
|
|
|
const alpha = m[4] === undefined ? 1 : Number(m[4]);
|
|
|
|
|
return [Number(m[1]), Number(m[2]), Number(m[3]), alpha];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// L'élément, puis chacun de ses ancêtres jusqu'à la racine du document.
|
|
|
|
|
function ascendance(element) {
|
|
|
|
|
const chaine = [];
|
|
|
|
|
for (let n = element; n !== null; n = n.parentElement) {
|
|
|
|
|
chaine.push(n);
|
|
|
|
|
}
|
|
|
|
|
return chaine;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fond peint sous un élément : le premier fond non transparent de son
|
|
|
|
|
// ascendance, ou null.
|
|
|
|
|
function fondPeint(element) {
|
|
|
|
|
for (const n of ascendance(element)) {
|
|
|
|
|
const fond = composantes(getComputedStyle(n).backgroundColor);
|
|
|
|
|
if (fond[3] !== 0) {
|
|
|
|
|
return fond;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Éléments du sous-arbre qui portent eux-mêmes un nœud de texte non vide.
|
|
|
|
|
function porteursDeTexte(racine) {
|
|
|
|
|
return [racine, ...racine.querySelectorAll('*')].filter((el) =>
|
|
|
|
|
[...el.childNodes].some(
|
|
|
|
|
(n) => n.nodeType === Node.TEXT_NODE && n.textContent.trim() !== '',
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Nom lisible d'un élément dans un message d'échec.
|
|
|
|
|
function designation(element) {
|
|
|
|
|
const classe = element.getAttribute('class');
|
|
|
|
|
return classe ? `${element.localName}.${classe}` : element.localName;
|
|
|
|
|
}
|
|
|
|
|
|
[ADD] interface: colour tokens, two themes, checked palette, marks
The plan's colours carry meaning — a conflict, a reservation, a mode — so
they must stay readable for every reader and in both themes. jetons.css
defines the tokens for the light and dark themes, set by data-theme on the
root; palette.js reads them from the stylesheet text and checks, by
computation, contrast to WCAG and separation under the three
dichromacies, keeping the conflict hue reserved. The theme follows the
system at each start and the operator's choice lasts the session.
Checked: 1709 node and 43 browser tests.
--- FR ---
[ADD] interface : jetons de couleur, deux thèmes, palette, marques
Les couleurs du plan portent un sens — un conflit, une réservation, un mode
— et doivent rester lisibles pour tout lecteur et dans les deux thèmes.
jetons.css définit les jetons des thèmes clair et sombre, posés par
data-theme sur la racine ; palette.js les lit dans le texte de la feuille
et contrôle, par calcul, le contraste au sens des WCAG et la séparation
sous les trois dichromaties, la teinte du conflit restant réservée. Le
thème suit le système à chaque démarrage ; le choix de l'opérateur vaut
pour la séance.
Vérifié : 1709 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:12 -04:00
|
|
|
// Exécute mesure() sous le thème demandé, posé par data-theme sur <html>, et
|
|
|
|
|
// rend sa valeur. L'attribut retrouve ensuite sa valeur d'avant, ou son
|
|
|
|
|
// absence, même quand mesure() lève : le test suivant part du même document.
|
[ADD] skeleton: Capacitor web app that shows its dated version
The engine to come must be proven against oracles under node in seconds,
so the skeleton sets three test projects: node, watched; node-long; and a
real Chromium that reads computed styles in both themes. The version
lives in version.json alone; a check refuses eight divergences — technical
form, generated module, changelog head, stray version strings — and a
build guard keeps test files and fixture assets out of the bundle.
Checked: on this commit alone, 73 node tests, 7 browser tests and the
version check pass; the guard fails on a fixture joined as an asset.
--- FR ---
[ADD] squelette : application web Capacitor qui affiche sa version datée
Le moteur à venir doit s'éprouver contre des oracles sous node en
quelques secondes : le squelette pose trois projets d'épreuve — node,
sous surveillance ; node-long ; et un vrai Chromium qui lit le style
calculé dans les deux thèmes. La version vit dans version.json seul ; un
contrôle refuse huit divergences — forme technique, module engendré,
tête du changelog, chaînes de version égarées — et une garde de
construction tient fichiers et données d'épreuve hors du paquet.
Vérifié : sur ce commit seul, 73 épreuves node, 7 navigateur et le
contrôle de version passent ; la garde échoue sur une donnée jointe.
Assisted-by: Claude Opus 5.5
2026-10-05 13:13:13 -04:00
|
|
|
async function sousTheme(theme, mesure) {
|
[ADD] interface: colour tokens, two themes, checked palette, marks
The plan's colours carry meaning — a conflict, a reservation, a mode — so
they must stay readable for every reader and in both themes. jetons.css
defines the tokens for the light and dark themes, set by data-theme on the
root; palette.js reads them from the stylesheet text and checks, by
computation, contrast to WCAG and separation under the three
dichromacies, keeping the conflict hue reserved. The theme follows the
system at each start and the operator's choice lasts the session.
Checked: 1709 node and 43 browser tests.
--- FR ---
[ADD] interface : jetons de couleur, deux thèmes, palette, marques
Les couleurs du plan portent un sens — un conflit, une réservation, un mode
— et doivent rester lisibles pour tout lecteur et dans les deux thèmes.
jetons.css définit les jetons des thèmes clair et sombre, posés par
data-theme sur la racine ; palette.js les lit dans le texte de la feuille
et contrôle, par calcul, le contraste au sens des WCAG et la séparation
sous les trois dichromaties, la teinte du conflit restant réservée. Le
thème suit le système à chaque démarrage ; le choix de l'opérateur vaut
pour la séance.
Vérifié : 1709 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:12 -04:00
|
|
|
const racine = document.documentElement;
|
|
|
|
|
const avant = racine.getAttribute('data-theme');
|
|
|
|
|
racine.setAttribute('data-theme', theme);
|
[ADD] skeleton: Capacitor web app that shows its dated version
The engine to come must be proven against oracles under node in seconds,
so the skeleton sets three test projects: node, watched; node-long; and a
real Chromium that reads computed styles in both themes. The version
lives in version.json alone; a check refuses eight divergences — technical
form, generated module, changelog head, stray version strings — and a
build guard keeps test files and fixture assets out of the bundle.
Checked: on this commit alone, 73 node tests, 7 browser tests and the
version check pass; the guard fails on a fixture joined as an asset.
--- FR ---
[ADD] squelette : application web Capacitor qui affiche sa version datée
Le moteur à venir doit s'éprouver contre des oracles sous node en
quelques secondes : le squelette pose trois projets d'épreuve — node,
sous surveillance ; node-long ; et un vrai Chromium qui lit le style
calculé dans les deux thèmes. La version vit dans version.json seul ; un
contrôle refuse huit divergences — forme technique, module engendré,
tête du changelog, chaînes de version égarées — et une garde de
construction tient fichiers et données d'épreuve hors du paquet.
Vérifié : sur ce commit seul, 73 épreuves node, 7 navigateur et le
contrôle de version passent ; la garde échoue sur une donnée jointe.
Assisted-by: Claude Opus 5.5
2026-10-05 13:13:13 -04:00
|
|
|
try {
|
[ADD] interface: colour tokens, two themes, checked palette, marks
The plan's colours carry meaning — a conflict, a reservation, a mode — so
they must stay readable for every reader and in both themes. jetons.css
defines the tokens for the light and dark themes, set by data-theme on the
root; palette.js reads them from the stylesheet text and checks, by
computation, contrast to WCAG and separation under the three
dichromacies, keeping the conflict hue reserved. The theme follows the
system at each start and the operator's choice lasts the session.
Checked: 1709 node and 43 browser tests.
--- FR ---
[ADD] interface : jetons de couleur, deux thèmes, palette, marques
Les couleurs du plan portent un sens — un conflit, une réservation, un mode
— et doivent rester lisibles pour tout lecteur et dans les deux thèmes.
jetons.css définit les jetons des thèmes clair et sombre, posés par
data-theme sur la racine ; palette.js les lit dans le texte de la feuille
et contrôle, par calcul, le contraste au sens des WCAG et la séparation
sous les trois dichromaties, la teinte du conflit restant réservée. Le
thème suit le système à chaque démarrage ; le choix de l'opérateur vaut
pour la séance.
Vérifié : 1709 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:12 -04:00
|
|
|
return await mesure();
|
[ADD] skeleton: Capacitor web app that shows its dated version
The engine to come must be proven against oracles under node in seconds,
so the skeleton sets three test projects: node, watched; node-long; and a
real Chromium that reads computed styles in both themes. The version
lives in version.json alone; a check refuses eight divergences — technical
form, generated module, changelog head, stray version strings — and a
build guard keeps test files and fixture assets out of the bundle.
Checked: on this commit alone, 73 node tests, 7 browser tests and the
version check pass; the guard fails on a fixture joined as an asset.
--- FR ---
[ADD] squelette : application web Capacitor qui affiche sa version datée
Le moteur à venir doit s'éprouver contre des oracles sous node en
quelques secondes : le squelette pose trois projets d'épreuve — node,
sous surveillance ; node-long ; et un vrai Chromium qui lit le style
calculé dans les deux thèmes. La version vit dans version.json seul ; un
contrôle refuse huit divergences — forme technique, module engendré,
tête du changelog, chaînes de version égarées — et une garde de
construction tient fichiers et données d'épreuve hors du paquet.
Vérifié : sur ce commit seul, 73 épreuves node, 7 navigateur et le
contrôle de version passent ; la garde échoue sur une donnée jointe.
Assisted-by: Claude Opus 5.5
2026-10-05 13:13:13 -04:00
|
|
|
} finally {
|
[ADD] interface: colour tokens, two themes, checked palette, marks
The plan's colours carry meaning — a conflict, a reservation, a mode — so
they must stay readable for every reader and in both themes. jetons.css
defines the tokens for the light and dark themes, set by data-theme on the
root; palette.js reads them from the stylesheet text and checks, by
computation, contrast to WCAG and separation under the three
dichromacies, keeping the conflict hue reserved. The theme follows the
system at each start and the operator's choice lasts the session.
Checked: 1709 node and 43 browser tests.
--- FR ---
[ADD] interface : jetons de couleur, deux thèmes, palette, marques
Les couleurs du plan portent un sens — un conflit, une réservation, un mode
— et doivent rester lisibles pour tout lecteur et dans les deux thèmes.
jetons.css définit les jetons des thèmes clair et sombre, posés par
data-theme sur la racine ; palette.js les lit dans le texte de la feuille
et contrôle, par calcul, le contraste au sens des WCAG et la séparation
sous les trois dichromaties, la teinte du conflit restant réservée. Le
thème suit le système à chaque démarrage ; le choix de l'opérateur vaut
pour la séance.
Vérifié : 1709 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:12 -04:00
|
|
|
if (avant === null) {
|
|
|
|
|
racine.removeAttribute('data-theme');
|
|
|
|
|
} else {
|
|
|
|
|
racine.setAttribute('data-theme', avant);
|
|
|
|
|
}
|
[ADD] skeleton: Capacitor web app that shows its dated version
The engine to come must be proven against oracles under node in seconds,
so the skeleton sets three test projects: node, watched; node-long; and a
real Chromium that reads computed styles in both themes. The version
lives in version.json alone; a check refuses eight divergences — technical
form, generated module, changelog head, stray version strings — and a
build guard keeps test files and fixture assets out of the bundle.
Checked: on this commit alone, 73 node tests, 7 browser tests and the
version check pass; the guard fails on a fixture joined as an asset.
--- FR ---
[ADD] squelette : application web Capacitor qui affiche sa version datée
Le moteur à venir doit s'éprouver contre des oracles sous node en
quelques secondes : le squelette pose trois projets d'épreuve — node,
sous surveillance ; node-long ; et un vrai Chromium qui lit le style
calculé dans les deux thèmes. La version vit dans version.json seul ; un
contrôle refuse huit divergences — forme technique, module engendré,
tête du changelog, chaînes de version égarées — et une garde de
construction tient fichiers et données d'épreuve hors du paquet.
Vérifié : sur ce commit seul, 73 épreuves node, 7 navigateur et le
contrôle de version passent ; la garde échoue sur une donnée jointe.
Assisted-by: Claude Opus 5.5
2026-10-05 13:13:13 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let composant;
|
|
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
|
composant = mount(App, { target: document.body });
|
|
|
|
|
flushSync();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
|
unmount(composant);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function bandeau() {
|
|
|
|
|
return document.body.querySelector('header.bandeau');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Le bandeau, puis chacun des éléments qui y portent un texte.
|
|
|
|
|
function bandeauEtTextes() {
|
|
|
|
|
return [...new Set([bandeau(), ...porteursDeTexte(bandeau())])];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
describe("bandeau d'application", () => {
|
|
|
|
|
test('existe et porte la version affichée', () => {
|
|
|
|
|
expect(bandeau()).not.toBeNull();
|
|
|
|
|
expect(bandeau().textContent).toContain(VERSION.affichee);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('le bandeau et chacun de ses textes sont visibles dans la fenêtre, dans les deux thèmes (§ 14.2, § 18.6)', async () => {
|
|
|
|
|
// Le texte, le titre et le style calculé se relisent sur un élément qui
|
|
|
|
|
// ne peint rien. L'épreuve interroge donc la mise en page : chaque élément
|
|
|
|
|
// est visible pour checkVisibility (display, visibility, opacité nulle,
|
|
|
|
|
// content-visibility), sa boîte est non vide et tient dans la fenêtre, et
|
|
|
|
|
// le point central de cette boîte atteint l'élément ou l'un de ses
|
|
|
|
|
// descendants — un élément recouvert, ou rogné par un ancêtre, laisse le
|
|
|
|
|
// point à un autre. elementFromPoint suit l'atteinte du pointeur : un
|
|
|
|
|
// élément en pointer-events: none n'y répond pas, et l'épreuve le refuse.
|
|
|
|
|
for (const theme of THEMES) {
|
|
|
|
|
await sousTheme(theme, () => {
|
|
|
|
|
const elements = bandeauEtTextes();
|
|
|
|
|
expect(elements.length).toBeGreaterThan(1);
|
|
|
|
|
for (const element of elements) {
|
|
|
|
|
const lieu = `${theme} : ${designation(element)}`;
|
|
|
|
|
expect(
|
|
|
|
|
element.checkVisibility({ opacityProperty: true, visibilityProperty: true }),
|
|
|
|
|
`${lieu} : checkVisibility`,
|
|
|
|
|
).toBe(true);
|
|
|
|
|
const boite = element.getBoundingClientRect();
|
|
|
|
|
expect(boite.width, `${lieu} : largeur`).toBeGreaterThan(0);
|
|
|
|
|
expect(boite.height, `${lieu} : hauteur`).toBeGreaterThan(0);
|
|
|
|
|
expect(boite.left, `${lieu} : bord gauche`).toBeGreaterThanOrEqual(0);
|
|
|
|
|
expect(boite.top, `${lieu} : bord haut`).toBeGreaterThanOrEqual(0);
|
|
|
|
|
expect(boite.right, `${lieu} : bord droit`).toBeLessThanOrEqual(innerWidth);
|
|
|
|
|
expect(boite.bottom, `${lieu} : bord bas`).toBeLessThanOrEqual(innerHeight);
|
|
|
|
|
const atteint = document.elementFromPoint(
|
|
|
|
|
boite.left + boite.width / 2,
|
|
|
|
|
boite.top + boite.height / 2,
|
|
|
|
|
);
|
|
|
|
|
expect(
|
|
|
|
|
element.contains(atteint),
|
|
|
|
|
`${lieu} : le centre de sa boîte atteint ${atteint === null ? 'aucun élément' : designation(atteint)}`,
|
|
|
|
|
).toBe(true);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('porte la provenance de la construction', () => {
|
|
|
|
|
expect(import.meta.env.MODE).toBe('test');
|
|
|
|
|
expect(bandeau().textContent).toContain('épreuve');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('le titre de la fenêtre porte le nom et la version affichée', () => {
|
|
|
|
|
expect(document.title).toBe(
|
|
|
|
|
`Gestion table tournante Libre — ${VERSION.affichee}`,
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('le texte et le fond du bandeau ont une couleur calculée', () => {
|
|
|
|
|
const style = getComputedStyle(bandeau());
|
|
|
|
|
expect(style.color).not.toBe(TRANSPARENT);
|
|
|
|
|
expect(style.backgroundColor).not.toBe(TRANSPARENT);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('chaque texte du bandeau tient 4,5:1 sur un fond opaque, dans les deux thèmes (§ 14.5)', async () => {
|
|
|
|
|
const couleursParTheme = [];
|
|
|
|
|
for (const theme of THEMES) {
|
|
|
|
|
const couleurs = await sousTheme(theme, () => {
|
|
|
|
|
const textes = porteursDeTexte(bandeau());
|
|
|
|
|
expect(textes.length).toBeGreaterThan(0);
|
|
|
|
|
for (const element of textes) {
|
|
|
|
|
const lieu = `${theme} : ${designation(element)}`;
|
|
|
|
|
const texte = composantes(getComputedStyle(element).color);
|
|
|
|
|
const fond = fondPeint(element);
|
|
|
|
|
expect(fond, lieu).not.toBeNull();
|
|
|
|
|
expect(texte[3], lieu).toBe(1);
|
|
|
|
|
expect(fond[3], lieu).toBe(1);
|
|
|
|
|
expect(contraste(texte, fond), lieu).toBeGreaterThanOrEqual(4.5);
|
|
|
|
|
}
|
|
|
|
|
return [document.body, bandeau()].map((el) => {
|
|
|
|
|
const style = getComputedStyle(el);
|
|
|
|
|
return `${style.color} sur ${style.backgroundColor}`;
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
couleursParTheme.push(couleurs);
|
|
|
|
|
}
|
[ADD] interface: colour tokens, two themes, checked palette, marks
The plan's colours carry meaning — a conflict, a reservation, a mode — so
they must stay readable for every reader and in both themes. jetons.css
defines the tokens for the light and dark themes, set by data-theme on the
root; palette.js reads them from the stylesheet text and checks, by
computation, contrast to WCAG and separation under the three
dichromacies, keeping the conflict hue reserved. The theme follows the
system at each start and the operator's choice lasts the session.
Checked: 1709 node and 43 browser tests.
--- FR ---
[ADD] interface : jetons de couleur, deux thèmes, palette, marques
Les couleurs du plan portent un sens — un conflit, une réservation, un mode
— et doivent rester lisibles pour tout lecteur et dans les deux thèmes.
jetons.css définit les jetons des thèmes clair et sombre, posés par
data-theme sur la racine ; palette.js les lit dans le texte de la feuille
et contrôle, par calcul, le contraste au sens des WCAG et la séparation
sous les trois dichromaties, la teinte du conflit restant réservée. Le
thème suit le système à chaque démarrage ; le choix de l'opérateur vaut
pour la séance.
Vérifié : 1709 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:12 -04:00
|
|
|
// Un attribut que la feuille ne lit pas, ou un thème sombre qui ne
|
|
|
|
|
// redéfinit aucune couleur, ferait mesurer deux fois le thème clair.
|
[ADD] skeleton: Capacitor web app that shows its dated version
The engine to come must be proven against oracles under node in seconds,
so the skeleton sets three test projects: node, watched; node-long; and a
real Chromium that reads computed styles in both themes. The version
lives in version.json alone; a check refuses eight divergences — technical
form, generated module, changelog head, stray version strings — and a
build guard keeps test files and fixture assets out of the bundle.
Checked: on this commit alone, 73 node tests, 7 browser tests and the
version check pass; the guard fails on a fixture joined as an asset.
--- FR ---
[ADD] squelette : application web Capacitor qui affiche sa version datée
Le moteur à venir doit s'éprouver contre des oracles sous node en
quelques secondes : le squelette pose trois projets d'épreuve — node,
sous surveillance ; node-long ; et un vrai Chromium qui lit le style
calculé dans les deux thèmes. La version vit dans version.json seul ; un
contrôle refuse huit divergences — forme technique, module engendré,
tête du changelog, chaînes de version égarées — et une garde de
construction tient fichiers et données d'épreuve hors du paquet.
Vérifié : sur ce commit seul, 73 épreuves node, 7 navigateur et le
contrôle de version passent ; la garde échoue sur une donnée jointe.
Assisted-by: Claude Opus 5.5
2026-10-05 13:13:13 -04:00
|
|
|
expect(
|
|
|
|
|
couleursParTheme[1],
|
|
|
|
|
`mêmes couleurs dans les deux thèmes : ${couleursParTheme[0].join(' ; ')}`,
|
|
|
|
|
).not.toEqual(couleursParTheme[0]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("aucune opacité partielle, aucun filtre ni mode de fusion sous un texte, dans les deux thèmes (§ 14.5)", async () => {
|
|
|
|
|
// opacity et filter ne s'héritent pas : posés sur un ancêtre, ils changent
|
|
|
|
|
// le pixel peint sans changer le style calculé du texte. Chaque niveau de
|
|
|
|
|
// l'ascendance est donc relu, jusqu'à la racine du document.
|
|
|
|
|
for (const theme of THEMES) {
|
|
|
|
|
await sousTheme(theme, () => {
|
|
|
|
|
const textes = porteursDeTexte(bandeau());
|
|
|
|
|
expect(textes.length).toBeGreaterThan(0);
|
|
|
|
|
for (const element of textes) {
|
|
|
|
|
for (const n of ascendance(element)) {
|
|
|
|
|
const style = getComputedStyle(n);
|
|
|
|
|
const lieu = `${theme} : ${designation(n)} sous ${designation(element)}`;
|
|
|
|
|
expect(style.opacity, lieu).toBe('1');
|
|
|
|
|
expect(style.filter, lieu).toBe('none');
|
|
|
|
|
expect(style.backdropFilter, lieu).toBe('none');
|
|
|
|
|
expect(style.mixBlendMode, lieu).toBe('normal');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|