The quality page needs figures the engine did not yet produce. It now bounds each person's distinct memberships (A_max) and checks it with the indicator guard; reads facilitator diversity over the evening and per round; records the search's moves and record points; lists repeated and imposed pairs; and lays out charts through one geometry module with two bench thresholds. Chart colour tokens carry their own validation. Default plans still equal the reference fingerprints; nothing new is written to the file yet. Checked: node 4768, navigateur 967, node-long 128; new modules at 100 %. --- FR --- [ADD] moteur de la qualité : A_max, diversité, course, paires La page de qualité demande des chiffres que le moteur ne produisait pas. Il borne désormais les appartenances distinctes de chacun (A_max) et la garde des indicateurs la vérifie ; il lit la diversité des animateurs sur la soirée et par tour ; il relève les mouvements et les points de la recherche ; il liste les paires répétées et imposées ; un seul module de géométrie dispose les graphiques, avec deux seuils au banc. Les jetons des graphiques portent leur propre validation. Les plans par défaut égalent les empreintes ; rien de neuf ne s'écrit encore au fichier. Vérifié : node 4768, navigateur 967, longues 128 ; nouveaux modules à 100 %. Assisted-by: Claude Opus 5.5
216 lines
13 KiB
JavaScript
216 lines
13 KiB
JavaScript
// © 2026 TechnoLibre (http://www.technolibre.ca)
|
|
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
|
|
|
|
// Un seul lanceur, trois projets (§ 14.4, § 14.8).
|
|
//
|
|
// node fonctions pures, sans DOM et sans greffon Svelte : un module qui
|
|
// importerait un composant échoue au chargement.
|
|
// node-long épreuves lourdes, hors de la série surveillée. Leur durée croît
|
|
// avec l'application : chacune dispose de deux minutes, là où le
|
|
// délai par défaut de Vitest, 5 s, la ferait échouer par
|
|
// dépassement et non sur un défaut. Ce délai arrête un test
|
|
// bloqué ; le plafond de la série est celui du rapporteur.
|
|
// navigateur un vrai moteur de rendu. Le projet étend vite.config.js : un
|
|
// module s'y résout par les mêmes greffons et réglages que dans la
|
|
// construction du livrable, sans seconde configuration à tenir
|
|
// d'accord avec la première. Il joue les épreuves de src/ et
|
|
// celles de l'outillage partagé de test/navigateur/.
|
|
// Chromium y tourne sans réseau hors de la boucle locale, au
|
|
// facteur d'échelle 1 (test/chromium.js). Les commandes des
|
|
// captures d'écran (test/navigateur/commandes_documentation.js)
|
|
// y sont déclarées, et le mode des captures, que GTT_CAPTURES
|
|
// choisit — verifier par défaut, ecrire sous make captures —,
|
|
// arrive à la page par provide (§ 19.5). Parmi elles, tramerPdf
|
|
// trame sous node les pages du PDF de la planche (§ 19.6). La
|
|
// commande d'impression (test/navigateur/commandes_impression.js),
|
|
// qui imprime le document d'une épreuve en PDF par le moteur de
|
|
// Chromium (§ 11.7), y est déclarée aussi.
|
|
import { defineConfig } from 'vitest/config';
|
|
import { playwright } from '@vitest/browser-playwright';
|
|
import { optionsNavigateur } from './test/chromium.js';
|
|
import * as commandesDocumentation from './test/navigateur/commandes_documentation.js';
|
|
import * as commandesImpression from './test/navigateur/commandes_impression.js';
|
|
import { coeursDisponibles, reglagesSeries } from './test/machine.js';
|
|
|
|
// Les commandes du projet navigateur, chacune sous son nom : celles des
|
|
// captures d'écran, puis celle de l'impression.
|
|
const COMMANDES_NAVIGATEUR = Object.fromEntries(
|
|
[commandesDocumentation, commandesImpression].flatMap((module) => module.COMMANDES.map((nom) => [nom, module[nom]])),
|
|
);
|
|
|
|
// Les séries node suivent le nombre de cœurs de la machine (test/machine.js) :
|
|
// en deçà de quatre, des threads sur tous les cœurs, et les épreuves lourdes
|
|
// de la série surveillée passent dans la série longue (§ 14.14). Sous la
|
|
// mesure de la couverture, que process.argv annonce par --coverage, elles
|
|
// restent dans node, où se mesurent les seuils qu'elles couvrent.
|
|
const SERIES = reglagesSeries(coeursDisponibles(), { couverture: process.argv.includes('--coverage') });
|
|
const PROCESSUS = { pool: SERIES.pool, maxWorkers: SERIES.maxWorkers };
|
|
|
|
// Les épreuves node qui lisent les composants de src/interface par le système
|
|
// de fichiers — chaînes, couleurs, en-tête, jetons lus, écouteurs du plan,
|
|
// version affichée, graphe des couches, version qu'App reçoit par ses
|
|
// propriétés, découpe des étiquettes hors de leur module —, celle qui importe
|
|
// App.svelte pour en voir l'échec sous node, et la garde du banc, qui balaie
|
|
// l'arbre à côté des motifs de ce fichier. S'y ajoutent les épreuves qui
|
|
// chargent ce fichier : il nomme les composants dans son motif, et son graphe
|
|
// porte les commandes des captures d'écran, qui balaient doc/captures ; la
|
|
// garde des lecteurs par le disque (test/arborescence.test.js), textuelle,
|
|
// les compte parmi les lecteurs des composants. test/documentation.test.js en
|
|
// est : elle lit ces motifs pour les fichiers que scripts/documentation.js
|
|
// lit par le disque. La garde de la contrainte 35 (src/moteur/criteres.test.js)
|
|
// lit chaque composant à la recherche d'une liste littérale de critères.
|
|
const RELANCES_D_UN_COMPOSANT = Object.freeze([
|
|
'test/arborescence.test.js',
|
|
'test/sources_interface.test.js',
|
|
'scripts/version.test.js',
|
|
'test/projets.test.js',
|
|
'test/licence.test.js',
|
|
'src/interface/palette.test.js',
|
|
'src/interface/plan/ecouteurs.test.js',
|
|
'src/interface/apropos.test.js',
|
|
'scripts/banc/banc.test.js',
|
|
'test/chromium.test.js',
|
|
'test/machine.test.js',
|
|
'test/rapporteur.test.js',
|
|
'test/documentation.test.js',
|
|
'src/stockage/etiquettes.test.js',
|
|
'src/moteur/criteres.test.js',
|
|
]);
|
|
|
|
// Les épreuves node qui lisent la feuille des jetons par le système de
|
|
// fichiers — palette validée par calcul, var(--…) déclarés, couleurs des
|
|
// sources, en-tête, version affichée, faces de la police de l'interface —,
|
|
// et la garde des motifs, qui balaie les feuilles de style de
|
|
// src/interface.
|
|
const RELANCES_DES_JETONS = Object.freeze([
|
|
'src/interface/palette.test.js',
|
|
'src/interface/marques.test.js',
|
|
'test/sources_interface.test.js',
|
|
'test/licence.test.js',
|
|
'scripts/version.test.js',
|
|
'test/arborescence.test.js',
|
|
'test/polices.test.js',
|
|
]);
|
|
|
|
export default defineConfig({
|
|
test: {
|
|
// test/rapporteur.js imprime, après le bilan par défaut, la durée de
|
|
// chaque projet et les dix épreuves les plus lentes, et fait échouer
|
|
// l'exécution quand node ou node-long dépasse son plafond (§ 14.14). Un
|
|
// chemin relatif se lit depuis la racine du projet.
|
|
reporters: ['default', './test/rapporteur.js'],
|
|
// La couverture (§ 14.13), que lancent npm run couverture et make
|
|
// couverture : la série node sous l'instrumentation de V8, sans le
|
|
// rapporteur, dont les plafonds bornent la série surveillée et la série
|
|
// longue, non une mesure. Aucun seuil global : un pourcentage d'ensemble
|
|
// se satisfait en couvrant les modules faciles. Le tableau imprime une
|
|
// ligne par couche et par module de src/, pleins compris — que Vitest
|
|
// tait sinon quand un agent le lance — et à 0 % ceux qu'aucune épreuve ne
|
|
// charge ; coverage/index.html montre, ligne à ligne, ce qui n'est jamais
|
|
// exécuté. Les modules nommés ci-dessous tiennent 100 % de branches,
|
|
// seuil dur : la commande échoue en deçà. Une branche nue s'y couvre par
|
|
// un cas ajouté, ou part avec le code mort ; le seuil ne s'abaisse pas,
|
|
// et test/arborescence.test.js garde ces seuils, ces deux rapports et
|
|
// les deux commandes qui lancent la mesure.
|
|
coverage: {
|
|
provider: 'v8',
|
|
include: ['src/**/*.js'],
|
|
exclude: ['src/**/*.test.js'],
|
|
reporter: [['text', { skipFull: false }], 'html'],
|
|
reportsDirectory: 'coverage',
|
|
thresholds: {
|
|
'src/geometrie/graphique.js': { branches: 100 },
|
|
'src/moteur/correspondance.js': { branches: 100 },
|
|
'src/moteur/criteres.js': { branches: 100 },
|
|
'src/moteur/diversite.js': { branches: 100 },
|
|
'src/moteur/indicateurs.js': { branches: 100 },
|
|
'src/moteur/paires.js': { branches: 100 },
|
|
'src/moteur/plafond.js': { branches: 100 },
|
|
'src/stockage/depot.js': { branches: 100 },
|
|
'src/stockage/journal.js': { branches: 100 },
|
|
},
|
|
},
|
|
// Sous surveillance, une épreuve se relance quand un module de son graphe
|
|
// d'imports change. Les fichiers des motifs se lisent hors de tout graphe :
|
|
// le contrôle de version (§ 18.5) lit les premiers par le système de
|
|
// fichiers ; la coquille s'exécute dans un processus à part, la
|
|
// configuration d'electron-builder se charge par un require natif et lit
|
|
// capacitor.config.json, et le script de construction se lance depuis une
|
|
// copie ; le point d'entrée de la page et le montage des épreuves du
|
|
// navigateur, qu'aucune épreuve node n'importe, se lisent par le disque, la
|
|
// langue et les démonstrations qu'ils passent à App comprises
|
|
// (test/livrable.test.js). Les composants de src/interface et la feuille des
|
|
// jetons se lisent comme du texte par les gardes qui les balaient ; sous
|
|
// node, sans greffon Svelte, aucun graphe ne les parcourt. Chaque motif
|
|
// rattache ses fichiers aux épreuves qui les lisent, et au contrôle de
|
|
// version quand son point 6 les balaie. Un fichier qui répond à un motif ne
|
|
// relance que les épreuves nommées, et plus celles qui l'importeraient : un
|
|
// motif relance donc toute épreuve de la série node qui importe l'un de ses
|
|
// fichiers — test/fichiers_electron.test.js importe electron/fichiers.js,
|
|
// test/projets.test.js importe App.svelte —, et ne nomme aucune table de
|
|
// libellés, que le graphe suffit à suivre. test/arborescence.test.js garde
|
|
// cette règle, et relève toute épreuve de la série node dont le texte lit un
|
|
// composant ou une feuille de style de src/interface sans que son motif la
|
|
// relance. Les motifs ne servent que la série node, la seule que la commande
|
|
// surveillée lance (§ 14.4) : sous une surveillance du projet navigateur,
|
|
// lancée à la main, un composant ou la feuille des jetons modifiés ne
|
|
// relancent aucune épreuve du navigateur, que le motif tait ; elles se
|
|
// relancent à la main. L'option se lit au niveau du lanceur : posée dans un
|
|
// projet, elle est ignorée sans avertissement.
|
|
watchTriggerPatterns: [
|
|
{ pattern: /(^|\/)(version\.json|package-lock\.json|CHANGELOG\.md|README\.md|GUIDE-[^/]*\.md)$/,
|
|
testsToRun: () => ['scripts/version.test.js', 'test/documentation.test.js'] },
|
|
{ pattern: /(^|\/)(package\.json|doc\/captures\/[^/]+|src\/interface\/parcours\.navigateur\.test\.js)$/,
|
|
testsToRun: () => 'test/documentation.test.js' },
|
|
{ pattern: /(^|\/)electron\/[^/]+$/,
|
|
testsToRun: () => ['test/coquille.test.js', 'test/fichiers_electron.test.js', 'test/livrable.test.js',
|
|
'scripts/essai_demarrage.test.js', 'scripts/version.test.js'] },
|
|
{ pattern: /(^|\/)test\/electron_factice\.js$/,
|
|
testsToRun: () => ['test/coquille.test.js', 'scripts/version.test.js'] },
|
|
{ pattern: /(^|\/)(electron-builder\.config\.cjs|capacitor\.config\.json)$/,
|
|
testsToRun: () => ['test/livrable.test.js', 'scripts/construire_windows.test.js', 'scripts/version.test.js'] },
|
|
{ pattern: /(^|\/)(src\/main\.js|test\/navigateur\/montage\.js)$/,
|
|
testsToRun: () => ['test/livrable.test.js', 'test/arborescence.test.js', 'scripts/version.test.js'] },
|
|
{ pattern: /(^|\/)scripts\/construire_windows\.sh$/,
|
|
testsToRun: () => ['scripts/construire_windows.test.js', 'scripts/version.test.js'] },
|
|
{ pattern: /(^|\/)src\/interface\/.+\.svelte$/,
|
|
testsToRun: () => [...RELANCES_D_UN_COMPOSANT] },
|
|
{ pattern: /(^|\/)src\/interface\/jetons\.css$/,
|
|
testsToRun: () => [...RELANCES_DES_JETONS] },
|
|
// La feuille d'impression de l'aperçu (§ 11.7) : les gardes des
|
|
// feuilles de style, et le modèle de l'aperçu, qui la lit par le disque.
|
|
{ pattern: /(^|\/)src\/interface\/impression\.css$/,
|
|
testsToRun: () => [...RELANCES_DES_JETONS, 'src/interface/impression/modele.test.js'] },
|
|
// Les documents porteurs de régions engendrées et le manifeste des
|
|
// captures, que scripts/documentation.js lit par le disque (§ 19.8).
|
|
{ pattern: /(^|\/)(README\.md|GUIDE-[^/]*\.md|doc\/captures\/manifeste\.json)$/,
|
|
testsToRun: () => 'scripts/documentation.test.js' },
|
|
// Le relevé du banc, que scripts/documentation.js lit par le disque
|
|
// pour la région « constantes » (§ 19.10) : les deux épreuves de la
|
|
// documentation, et celles qui l'importent, que le motif ne relancerait
|
|
// plus sinon.
|
|
{ pattern: /(^|\/)scripts\/banc\/releve\.json$/,
|
|
testsToRun: () => ['test/documentation.test.js', 'scripts/documentation.test.js', 'src/geometrie/constantes.test.js',
|
|
'scripts/banc/releve.test.js', 'scripts/banc/lancer.test.js'] },
|
|
],
|
|
projects: [
|
|
{ test: {
|
|
name: 'node', environment: 'node', ...PROCESSUS,
|
|
include: ['src/**/*.test.js', 'scripts/**/*.test.js', 'test/**/*.test.js'],
|
|
exclude: ['**/*.long.test.js', '**/*.navigateur.test.js', 'node_modules/**',
|
|
...SERIES.horsSerieSurveillee] } },
|
|
{ test: {
|
|
name: 'node-long', environment: 'node', ...PROCESSUS,
|
|
include: ['src/**/*.long.test.js', 'test/**/*.long.test.js', ...SERIES.horsSerieSurveillee],
|
|
testTimeout: 120_000 } },
|
|
{ extends: './vite.config.js',
|
|
test: {
|
|
name: 'navigateur',
|
|
include: ['src/**/*.navigateur.test.js', 'test/**/*.navigateur.test.js'],
|
|
provide: { captures: { mode: commandesDocumentation.modeCaptures(process.env) } },
|
|
browser: { enabled: true, headless: true, provider: playwright(optionsNavigateur(process.env)),
|
|
instances: [{ browser: 'chromium' }],
|
|
commands: COMMANDES_NAVIGATEUR } } },
|
|
],
|
|
},
|
|
});
|