From cb89060e347de71c489e748f0980d3fca0e69256 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sat, 10 Oct 2026 14:36:21 -0400 Subject: [PATCH] [ADD] captures: badge control page and first sheet, rasterised from PDF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The walkthrough produces the retained plan's badge sheet through the Badges section and rasterises the PDF under node with pdfjs at 96 dpi: page 1 becomes the control page, page 2 the first sheet of four A6. Manifest entries carry the PDF's sha256, so an unchanged PDF leaves the images unchanged; two productions under the driven clock must hash the same, and a missing canvas fails the step by name with nothing written. No capture remains pending. Checked: node 3787, browser 758, node-long 101 from the index alone. --- FR --- [ADD] captures : feuille de contrôle et planche, tramées du PDF Le parcours produit la planche du retenu par la section Badges et trame le PDF sous node par pdfjs à 96 ppp : la page 1 donne la feuille de contrôle, la page 2 la première planche de quatre A6. Les entrées du manifeste portent le sha256 du PDF : un PDF inchangé laisse les images inchangées ; deux productions sous l'horloge pilotée ont même empreinte, et un canevas absent fait échouer l'étape en le nommant, rien d'écrit. Plus aucune capture n'est à venir. Vérifié : node 3787, navigateur 758, longues 101 depuis l'index seul. Assisted-by: Claude Opus 5.5 --- GUIDE-USAGE.md | 27 ++ doc/captures/24-badges-controle.png | Bin 0 -> 44007 bytes doc/captures/25-badges-planche.png | Bin 0 -> 87679 bytes doc/captures/manifeste.json | 4 +- scripts/documentation/manifeste.js | 3 +- scripts/documentation/manifeste.test.js | 28 +- src/interface/parcours.navigateur.test.js | 229 +++++++++++- test/navigateur/commandes_documentation.js | 202 ++++++++++- .../commandes_documentation.test.js | 332 ++++++++++++++++++ vitest.config.js | 7 +- 10 files changed, 802 insertions(+), 30 deletions(-) create mode 100644 doc/captures/24-badges-controle.png create mode 100644 doc/captures/25-badges-planche.png create mode 100644 test/navigateur/commandes_documentation.test.js diff --git a/GUIDE-USAGE.md b/GUIDE-USAGE.md index d22333d..ead44e5 100644 --- a/GUIDE-USAGE.md +++ b/GUIDE-USAGE.md @@ -378,6 +378,33 @@ Revenu au placement retenu, l’aperçu sort sans filigrane : porte l’instant de ce placement. C’est cette page qui part à l’imprimante pour le montage de la salle.* +La planche se produit dans la section « Badges » de l’événement. On y choisit +l’imposition — feuille par feuille, ou en pile pour un massicot qui tranche +toute la rame — et l’ordre des badges, alphabétique ou par table du premier +tour. « Préparer » annonce ce qui sortira : le nombre de badges et de planches, +les homonymes, les caractères que la police ne dessine pas. « Produire la +planche » écrit le PDF à côté des fichiers de l’événement et en affiche le +chemin ; dans un navigateur, le PDF se télécharge. Sa première page est la +feuille de contrôle : + +![La feuille de contrôle de la planche : la règle de 100 mm, puis les comptes de la soirée](doc/captures/24-badges-controle.png) + +*La règle du haut mesure 100 mm sur le papier : posez-y une vraie règle. Si les +deux ne coïncident pas, l’imprimante a mis la page à l’échelle, et les badges +ne tomberont pas sur les traits de coupe. Suivent le format du badge et du +papier, l’imposition, le nombre de planches, les comptes de la soirée — un +badge par personne présente, les exclus comptés à part —, l’instant du +placement et la version du logiciel.* + +Viennent ensuite les planches, quatre badges A6 par feuille A4 : + +![La première planche : quatre badges A6 et leurs traits de coupe](doc/captures/25-badges-planche.png) + +*Chaque badge porte le nom, l’appartenance et la table de chaque tour ; en +pied, le nom de l’événement et l’instant du placement. Les traits fins +marquent la coupe : un vertical au milieu de la feuille, un horizontal sous +chaque rangée de badges.* + Une fois le plan imprimé, bloquez-le : choisissez l’état « Bloqué » en haut de l’événement. Plus rien ne le modifie, jusqu’à « Débloquer ». diff --git a/doc/captures/24-badges-controle.png b/doc/captures/24-badges-controle.png new file mode 100644 index 0000000000000000000000000000000000000000..b5cc767eadc257dd8e8b7643fbb90ebf90666a91 GIT binary patch literal 44007 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 { for (const reportee of REPORTEES) assert.ok(Object.isFrozen(reportee), reportee.fichier); }); - test('A_VENIR nomme les deux captures de la planche, à l’étape 12, déclarées ; 22 et 23 sont photographiées', () => { - assert.deepEqual(A_VENIR, ['24-badges-controle', '25-badges-planche']); - for (const fichier of A_VENIR) assert.equal(CAPTURES.find((c) => c.fichier === fichier)?.etape, '12', fichier); - const declarees = new Set(CAPTURES.map((c) => c.fichier)); - for (const fichier of A_VENIR) assert.ok(declarees.has(fichier), fichier); + test('A_VENIR est vide : chaque capture déclarée est photographiée, 24 et 25 tramées du PDF de la planche', () => { + assert.deepEqual(A_VENIR, []); assert.ok(Object.isFrozen(A_VENIR)); + const tramees = CAPTURES.filter((c) => c.source === 'pdf').map((c) => [c.fichier, c.etape]); + assert.deepEqual(tramees, [['24-badges-controle', '12'], ['25-badges-planche', '12']]); }); test('CAPTURES ∪ REPORTEES : des noms uniques, et l’ordre des noms suit celui des étapes', () => { @@ -316,21 +315,22 @@ describe('manifeste : l’ordre contre les étapes du § 2.1 (§ 19.3)', () => { assert.deepEqual(verifierOrdre(manifesteDeclare()), []); }); - test('les captures d’A_VENIR, absentes du manifeste, sont admises', () => { - assert.deepEqual(verifierOrdre(manifesteDeclare({ sans: A_VENIR })), []); + test('une capture à venir, absente du manifeste, couvre son étape', () => { + const etape12 = ['22-plan-brouillon', '23-plan-retenu', '24-badges-controle', '25-badges-planche']; + assert.deepEqual(verifierOrdre(manifesteDeclare({ sans: etape12 }), { aVenir: ['24-badges-controle'] }), []); }); - test('A_VENIR vidé, les captures d’A_VENIR absentes : 22 et 23 couvrent l’étape 12', () => { - assert.deepEqual(verifierOrdre(manifesteDeclare({ sans: A_VENIR }), { aVenir: [] }), []); - }); - - test('A_VENIR vidé, sans 22 ni 23 : l’étape 12 sans capture est une faute', () => { - const photographiees = ['22-plan-brouillon', '23-plan-retenu']; - assert.deepEqual(verifierOrdre(manifesteDeclare({ sans: [...photographiees, ...A_VENIR] }), { aVenir: [] }), [ + test('A_VENIR par défaut, vide : sans ses quatre captures, l’étape 12 est une faute', () => { + const etape12 = ['22-plan-brouillon', '23-plan-retenu', '24-badges-controle', '25-badges-planche']; + assert.deepEqual(verifierOrdre(manifesteDeclare({ sans: etape12 })), [ { chemin: CHEMIN_MANIFESTE, faute: 'étape 12 : aucune capture ni reportée' }, ]); }); + test('sans 24 ni 25, 22 et 23 couvrent l’étape 12 : l’appariement, non l’ordre, réclame les images de la planche', () => { + assert.deepEqual(verifierOrdre(manifesteDeclare({ sans: ['24-badges-controle', '25-badges-planche'] })), []); + }); + test('une étape sans capture ni reportée est une faute qui la nomme', () => { assert.deepEqual(verifierOrdre(manifesteDeclare({ sans: ['07b-nombre-de-tours'] })), [ { chemin: CHEMIN_MANIFESTE, faute: 'étape 5 : aucune capture ni reportée' }, diff --git a/src/interface/parcours.navigateur.test.js b/src/interface/parcours.navigateur.test.js index 72861d8..da36e74 100644 --- a/src/interface/parcours.navigateur.test.js +++ b/src/interface/parcours.navigateur.test.js @@ -15,7 +15,9 @@ // captures du § 19.3 que l'itération photographie — 01, 01b, 02, 02b, 03 à // 07, 07b, 08 à 10, les deux 07a sur la grande démonstration que 10 a // chargée, 11, 19, 20, puis 22 et 23, l'aperçu avant impression d'une -// proposition et du retenu —, puis l'ordre de lecture du § 2.1 sur +// proposition et du retenu, puis 24 et 25, la feuille de contrôle et la +// première planche du PDF que la section Badges produit, tramées sous node +// (§ 19.6) —, puis l'ordre de lecture du § 2.1 sur // l'événement retenu, les fenêtres — aucune pendant un geste non // destructeur, une qui nomme ce qui part pour chaque geste qui détruit —, // enfin chaque famille de geste modifiant en lecture puis sur un plan @@ -25,7 +27,8 @@ // état du document (§ 19.3). // // Une épreuve qui porte une capture finit, ses conditions affirmées, par -// photographier (test/navigateur/captures.js) ; une épreuve qui continue +// photographier (test/navigateur/captures.js), ou, pour une page du PDF de +// la planche, par photographierPdf ; une épreuve qui continue // au-delà de l'écran photographié se coupe en deux. Rien de la machine // n'entre dans une région photographiée : la provenance « documentation » // tient lieu de version (§ 18.6), l'exécuteur direct annonce quatre cœurs, @@ -42,7 +45,7 @@ import { flushSync } from 'svelte'; import { bilanRemplacement, cleNormalisee } from '../application/csv.js'; import { creerFormat } from '../application/format.js'; import { creerExecuteurDirect } from '../application/generation.js'; -import { TABLES_APPLICATION } from '../application/libelles.js'; +import { TABLES_APPLICATION, libelle } from '../application/libelles.js'; import { nomAffiche } from '../application/personnes.js'; import { etatPlaces } from '../application/places.js'; import { estBrouillon } from '../application/sorties.js'; @@ -69,7 +72,15 @@ import { SUFFIXES } from '../stockage/noms.js'; import { planDepuisFichier } from '../stockage/placements.js'; import { VERSION } from '../version.genere.js'; import urlCp1252 from '../../exemples/participants_cas_limites_cp1252.csv?url'; -import { CADRE, capturesPrises, cloreCaptures, entiereDansLaFenetre, modeFourni, photographier } from '../../test/navigateur/captures.js'; +import { + CADRE, + capturesPrises, + cloreCaptures, + empreinteEtat, + entiereDansLaFenetre, + modeFourni, + photographier, +} from '../../test/navigateur/captures.js'; import { NOM_CAS_LIMITES, attendre, centre, octetsCasLimites } from '../../test/navigateur/ecrans.js'; import { fixerCadre, pointer, touche } from '../../test/navigateur/entrees.js'; import { poserFeuille } from '../../test/navigateur/feuilles.js'; @@ -590,6 +601,121 @@ async function cadrerSur(elements) { await images(2); } +// --- La planche de badges photographiée (§ 19.6) -------------------------------------- + +// Les images de la planche (§ 19.3, § 19.6) : la feuille de contrôle, page 1 +// du PDF, et la première planche, page 2. +const PAGE_CONTROLE = Object.freeze({ page: 1, fichier: '24-badges-controle' }); +const PAGE_PLANCHE = Object.freeze({ page: 2, fichier: '25-badges-planche' }); + +// Les images que la production de la planche attend au plus : la police et +// pdf-lib se chargent à la première production. +const IMAGES_PLANCHE = 1800; + +// L'écart de l'horloge pilotée entre deux productions de la même planche : +// une date du document tirée de l'horloge, et non du placement, les +// séparerait à la seconde. +const ECART_PRODUCTIONS_MS = 60 * 1000; + +// Les captures tramées du PDF que le parcours a menées à leur terme. +const capturesPdf = new Set(); + +// Le texte base64 d'octets : le PDF traverse ainsi le RPC des commandes, +// qui sérialiserait un Uint8Array en objet. +function enBase64(octets) { + let binaire = ''; + for (let debut = 0; debut < octets.length; debut += 0x8000) { + binaire += String.fromCharCode(...octets.subarray(debut, debut + 0x8000)); + } + return btoa(binaire); +} + +// Le SHA-256 hexadécimal d'octets. +async function empreinte(octets) { + const tampon = await crypto.subtle.digest('SHA-256', octets); + return [...new Uint8Array(tampon)].map((octet) => octet.toString(16).padStart(2, '0')).join(''); +} + +// Le texte d'une page de PDF lue, ses fragments joints, blancs réduits. +const texteDePage = (lue) => plat(lue.textes.join(' ')); + +// Les traits droits d'une page de PDF lue, en mm : les abscisses des +// verticaux et les ordonnées des horizontaux, puis les longueurs des +// horizontaux, au centième, chacune une fois, croissantes. +function axesDe(lue) { + const centieme = (valeur) => Math.round(valeur * 100) / 100; + const uniques = (valeurs) => [...new Set(valeurs.map(centieme))].sort((a, b) => a - b); + const verticaux = lue.segments.filter(({ x1, x2 }) => Math.abs(x1 - x2) < 1e-3); + const horizontaux = lue.segments.filter(({ y1, y2 }) => Math.abs(y1 - y2) < 1e-3); + return { + x: uniques(verticaux.map(({ x1 }) => x1)), + y: uniques(horizontaux.map(({ y1 }) => y1)), + longueurs: uniques(horizontaux.map(({ x1, x2 }) => Math.abs(x2 - x1))), + }; +} + +// Compare deux textes point de code par point de code, sans tenir compte +// de la langue, comme l'ordre alphabétique de la planche (§ 11.6, § 15.5). +function parPointsDeCode(a, b) { + const [x, y] = [[...a], [...b]]; + for (let rang = 0; rang < Math.min(x.length, y.length); rang += 1) { + const ecart = x[rang].codePointAt(0) - y[rang].codePointAt(0); + if (ecart !== 0) return ecart; + } + return x.length - y.length; +} + +/** + * Photographie une page du PDF de la planche (§ 19.6) : tramerPdf la lit + * d'abord sans rien écrire, conditions(lue) affirme ce qu'elle montre, puis, + * en écriture, la trame en PNG sous le dossier d'attente et dépose l'entrée ; + * en vérification, compare l'entrée au manifeste. L'entrée porte la source + * pdf, la taille de la page à 96 ppp pour cadre, la couche de texte de la + * page pour texte, aucun style — le PDF n'a pas de thème d'écran — et le + * SHA-256 des octets pour pdf. + * + * @param {Uint8Array} octets le PDF produit + * @param {{page: number, fichier: string}} quoi + * @param {(lue: Object) => void} conditions + */ +async function photographierPdf(octets, { page, fichier }, conditions) { + const { captures } = await commands.declarationsCaptures(); + const declaree = captures.find((capture) => capture.fichier === fichier); + expect(declaree, `${fichier} déclarée`).toMatchObject({ source: 'pdf' }); + const octetsB64 = enBase64(octets); + const lu = await commands.tramerPdf({ octetsB64, pages: [{ page, fichier }], ecrire: false }); + expect(lu.pdf).toBe(await empreinte(octets)); + const [lue] = lu.pages; + conditions(lue); + const racineNeutre = etat().racine.chemin; + expect(await commands.cheminsHorsRacine({ texte: lue.textes, racine: racineNeutre }), fichier).toEqual([]); + const entree = { + fichier, + etape: declaree.etape, + source: 'pdf', + versionReelle: VERSION.affichee, + graine: GRAINE, + cadre: lue.cadre, + facteurEchelle: 1, + mode: lu.mode, + theme: 'clair', + instant: m.horloge.horodatage(), + texte: lue.textes, + styles: { clair: [], sombre: [] }, + etat: await empreinteEtat(m), + pdf: lu.pdf, + }; + if (modeFourni() === 'ecrire') { + const tramee = await commands.tramerPdf({ octetsB64, pages: [{ page, fichier }], ecrire: true }); + expect(tramee.pdf).toBe(lu.pdf); + await commands.deposerCapture({ fichier, entree, chemin: tramee.pages[0].chemin }); + } else { + const { ecarts } = await commands.comparerCapture({ fichier, entree }); + expect(ecarts, `capture ${fichier} : écart au manifeste`).toEqual([]); + } + capturesPdf.add(fichier); +} + // --- Le parcours (§ 2.1, § 19.3) ------------------------------------------------------ describe('le parcours par gestes, depuis un répertoire neuf', { timeout: DUREE }, () => { @@ -1318,9 +1444,95 @@ describe('le parcours par gestes, depuis un répertoire neuf', { timeout: DUREE await images(2); }); - // Un échec de 22 ou de 23 laisse l'aperçu ouvert, la proposition montrée - // et la fenêtre défilée : l'état est rendu ici, pour que les épreuves - // suivantes jugent leurs propres gardes et non ce reste. + // La planche du retenu, produite par la section Badges sur le papier que + // 22 a choisi, puis tramée sous node (§ 19.6) : la feuille de contrôle, + // puis la première planche. Produire n'écrit que le PDF ; deux + // productions sous l'horloge pilotée donnent les mêmes octets, que + // l'empreinte du manifeste suit. + test('24 la planche du retenu par la section Badges : seul le PDF s’écrit, deux productions identiques ; la feuille de contrôle', async () => { + expect(charge().evenement.etat).toBe('retenu'); + expect(etat().papier).toBe('A4'); + const avant = fichiers(); + let rang = m.trace.length; + await ouvrirSection('badges'); + await cliquer('[data-section="badges"] [data-commande="produirePlanche"]'); + const affiche = await attendre('la planche produite', () => dans('[data-section="badges"] [data-chemin-planche]'), IMAGES_PLANCHE); + const ecrits = cheminsEcrits(rang); + expect(ecrits).toHaveLength(1); + const [nom] = ecrits; + expect(nom.startsWith(`${base()}.badges_A4_feuille_`), nom).toBe(true); + expect(nom.endsWith('.pdf'), nom).toBe(true); + const { separateur } = await m.fs.emplacements(); + expect(texteDe(affiche)).toBe(`${etat().racine.chemin}${separateur}${nom}`); + const premiere = m.fs.octets('documents', nom); + expect(new TextDecoder().decode(premiere.slice(0, 5))).toBe('%PDF-'); + + // Une seconde production, l'horloge avancée : le même fichier, les + // mêmes octets. L'avance échoit aussi l'écriture différée du cadrage + // (reglages_locaux.json), que le plan a laissée en attente : elle passe + // avant que la trace de la seconde production ne commence. + m.horloge.avancer(ECART_PRODUCTIONS_MS); + await images(4); + rang = m.trace.length; + await cliquer('[data-section="badges"] [data-commande="produirePlanche"]'); + await attendre( + 'la seconde planche', + () => cheminsEcrits(rang).length > 0 && dans('[data-section="badges"] [data-chemin-planche]'), + IMAGES_PLANCHE, + ); + expect(cheminsEcrits(rang)).toEqual([nom]); + const seconde = m.fs.octets('documents', nom); + expect(await empreinte(seconde)).toBe(await empreinte(premiere)); + await rienEcrit(avant, 'la production de la planche'); + memoire.planche = seconde; + + // La feuille de contrôle : la règle de 100 mm, les comptes de la + // soirée, la marque de provenance à la place de la version, aucun + // BROUILLON sur le retenu. + const participants = charge().participants.length; + const exclus = charge().participants.filter(({ exclu }) => exclu).length; + const produits = participants - exclus; + const version = versionVisible('documentation', VERSION.affichee, libelle); + await photographierPdf(seconde, PAGE_CONTROLE, (lue) => { + const texte = texteDePage(lue); + expect(axesDe(lue).longueurs).toContain(100); + expect(texte).toContain(plat(libelle('planche.controle.comptes', { produits, participants, exclus }))); + expect(texte).toContain(plat(libelle('planche.controle.planches', { planches: Math.ceil(produits / 4) }))); + expect(texte).toContain(plat(libelle('planche.controle.version', { version }))); + expect(texte).not.toContain(VERSION.affichee); + expect(texte).not.toContain(libelle('planche.brouillon')); + }); + }); + + test('25 la première planche : quatre A6, ses trois filets de coupe, les quatre premiers noms dans l’ordre alphabétique', async () => { + expect(memoire.planche, 'la planche de 24').toBeInstanceOf(Uint8Array); + const presents = charge().participants.filter(({ exclu }) => !exclu); + expect(presents.length).toBeGreaterThanOrEqual(4); + // L'ordre alphabétique de la planche : le nom, puis le prénom, leurs + // clés normalisées comparées par points de code, puis l'identifiant. + const cle = (texte) => cleNormalisee(texte ?? ''); + const premiers = [...presents] + .sort((a, b) => parPointsDeCode(cle(a.nom), cle(b.nom)) || parPointsDeCode(cle(a.prenom), cle(b.prenom)) || a.id - b.id) + .slice(0, 4) + .map((personne) => nomAffiche(personne).normalize('NFC')); + await photographierPdf(memoire.planche, PAGE_PLANCHE, (lue) => { + // A4, planche pleine : la coupe verticale au milieu, les deux + // horizontales sous chaque rangée de badges (§ 11.6). + const { x, y } = axesDe(lue); + expect(x).toEqual([105]); + expect(y).toEqual([148, 296]); + const texte = texteDePage(lue); + for (const nomBadge of premiers) expect(texte, nomBadge).toContain(plat(nomBadge)); + expect(texte).not.toContain(libelle('planche.brouillon')); + }); + // Le parcours reprend sur le plan, comme 23 l'a laissé. + await ouvrirSection('plan'); + }); + + // Un échec de 22 à 25 laisse l'aperçu ouvert, la proposition montrée, la + // section Badges ouverte ou la fenêtre défilée : l'état est rendu ici, + // pour que les épreuves suivantes jugent leurs propres gardes et non ce + // reste. afterAll(async () => { if (dans('[data-ecran="apercu"] [data-commande="fermerApercu"]') !== null) { await cliquer('[data-ecran="apercu"] [data-commande="fermerApercu"]'); @@ -1330,6 +1542,7 @@ describe('le parcours par gestes, depuis un répertoire neuf', { timeout: DUREE await cliquer('[data-commande="quitterProposition"]'); await attendre('le retenu montré', () => m.ui.etat().proposition === null); } + if (dans('[data-section="plan"]') === null) await ouvrirSection('plan'); window.scrollTo(0, 0); }); }); @@ -1767,6 +1980,6 @@ describe('lecture et bloqué : tout geste modifiant refusé, rien d’écrit', { describe('les captures d’écran du parcours (§ 19.5, § 19.7)', () => { test('chaque capture déclarée photographiée : publiées d’un bloc en écriture, conformes au manifeste en vérification', async () => { const { declarees } = await cloreCaptures({ echecs: epreuvesEnEchec, racineNeutre: m?.seance.etat().racine?.chemin ?? null }); - expect([...capturesPrises()].sort()).toEqual([...declarees].sort()); + expect([...capturesPrises(), ...capturesPdf].sort()).toEqual([...declarees].sort()); }); }); diff --git a/test/navigateur/commandes_documentation.js b/test/navigateur/commandes_documentation.js index cbecd90..a8c1741 100644 --- a/test/navigateur/commandes_documentation.js +++ b/test/navigateur/commandes_documentation.js @@ -29,8 +29,20 @@ // // Le mode de vérification compare l'entrée d'une étape à celle du // manifeste (comparerCapture) et n'écrit rien. +// +// Les images de la planche (§ 19.6) ne viennent pas du navigateur : la page +// passe le PDF produit, en base64, à tramerPdf, qui lit chaque page demandée +// par pdfjs-dist — sa couche de texte et ses traits (test/pdf.js), sa taille +// à 96 ppp — et, en écriture, la trame en PNG sous le dossier d'attente, par +// le canevas natif que pdfjs-dist charge lui-même, @napi-rs/canvas, sa +// dépendance optionnelle. Seul make captures exige ce canevas : la lecture +// s'en passe, et le tramage refuse en le nommant quand il manque. pdfjs-dist +// et test/pdf.js se chargent au premier appel : la configuration du lanceur +// importe ce module sans eux. La publication tire son pilote des seules +// captures du navigateur : une page de PDF a la taille de sa page. import { createHash } from 'node:crypto'; import { mkdir, mkdtemp, readdir, readFile, rename, rm, writeFile } from 'node:fs/promises'; +import { createRequire } from 'node:module'; import { tmpdir } from 'node:os'; import { dirname, isAbsolute, join, relative, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; @@ -71,6 +83,7 @@ export const COMMANDES = Object.freeze([ 'effacerDossierEpreuve', 'empreintesDossier', 'copierDansEpreuve', + 'tramerPdf', ]); /** @@ -293,10 +306,14 @@ async function deposees(attente) { } // Le pilote du manifeste : le navigateur et sa version, le mode nommé, le -// facteur d'échelle et le cadre, communs à toutes les captures. +// facteur d'échelle et le cadre, communs à toutes les captures du +// navigateur. Une page de PDF n'en relève pas : son cadre est sa page à +// PPP_TRAMAGE (§ 19.6). Sans capture du navigateur, aucun pilote : refus. function piloteDe(context, captures) { - const [premiere] = captures; - for (const capture of captures) { + const duNavigateur = captures.filter(({ source }) => source !== 'pdf'); + const [premiere] = duNavigateur; + if (premiere === undefined) throw new Error('publication : aucune capture du navigateur — le manifeste n’aurait aucun pilote'); + for (const capture of duNavigateur) { if (capture.facteurEchelle !== premiere.facteurEchelle || canonique(capture.cadre) !== canonique(premiere.cadre)) { throw new Error(`publication : ${capture.fichier} n’a pas le cadre ni le facteur d’échelle de ${premiere.fichier}`); } @@ -476,3 +493,182 @@ export async function empreintesDossier(_context, { racine = null } = {}) { await parcourir(join(base, DOSSIER_CAPTURES)); return fichiers.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)); } + +// --- Le tramage des pages de la planche (§ 19.6) --------------------------------- + +/** La résolution du tramage, en points par pouce : celle du pixel CSS, que + * mesurent les captures du navigateur. */ +export const PPP_TRAMAGE = 96; + +/** Le mode qu'inscrit l'entrée d'une page de PDF : le lecteur qui la trame et + * sa résolution, là où une capture du navigateur inscrit son mode + * d'affichage. */ +export const MODE_TRAMAGE = `pdfjs-dist-${PPP_TRAMAGE}ppp`; + +// Le canevas natif que pdfjs-dist charge pour tramer sous node, sa +// dépendance optionnelle ; le point PDF et le millimètre, par pouce. +const CANEVAS = '@napi-rs/canvas'; +const PT_PAR_POUCE = 72; +const MM_PAR_POUCE = 25.4; + +// Le chargeur CommonJS du paquet pdfjs-dist : un module qu'il résout est +// celui que pdfjs-dist charge lui-même. +const depuisPdfjs = () => createRequire(createRequire(import.meta.url).resolve('pdfjs-dist/package.json')); + +// Les polices standard de pdfjs-dist, lues du disque quand un document en +// appelle une sans l'embarquer, comme test/pdf.js les lui donne. +const policesStandard = () => `${join(dirname(createRequire(import.meta.url).resolve('pdfjs-dist/package.json')), 'standard_fonts')}/`; + +/** Le canevas natif de pdfjs-dist, chargé depuis son paquet. Lève quand il + * manque, ou que sa liaison native n'existe pas pour ce système. */ +export function chargerCanevas() { + return depuisPdfjs()(CANEVAS); +} + +/** Vrai quand le canevas natif de pdfjs-dist se charge sur ce système. */ +export function canevasDisponible() { + try { + chargerCanevas(); + return true; + } catch { + return false; + } +} + +// Les octets que porte un texte base64 ; lève sur un texte vide ou qui +// n'est pas du base64 canonique, que la relecture ne rendrait pas tel quel. +function octetsDe(octetsB64) { + if (typeof octetsB64 !== 'string' || octetsB64.length === 0) { + throw new TypeError('tramerPdf : octetsB64 est le texte base64, non vide, du PDF'); + } + const octets = Buffer.from(octetsB64, 'base64'); + if (octets.toString('base64') !== octetsB64) throw new TypeError('tramerPdf : octetsB64 n’est pas du base64'); + return new Uint8Array(octets.buffer, octets.byteOffset, octets.byteLength); +} + +// Les pages demandées, [{page, fichier}] : au moins une, chaque nom de +// capture valide et une seule fois, chaque page un entier. +function pagesDemandees(pages) { + if (!Array.isArray(pages) || pages.length === 0) throw new Error('tramerPdf : aucune page demandée'); + const vus = new Set(); + return pages.map(({ page, fichier }) => { + exigerNom(fichier); + if (vus.has(fichier)) throw new Error(`tramerPdf : « ${fichier} » demandée deux fois`); + vus.add(fichier); + if (!Number.isSafeInteger(page)) throw new TypeError(`tramerPdf : page ${JSON.stringify(page)}, un entier attendu`); + return { page, fichier }; + }); +} + +// La taille en pixels d'une longueur en millimètres, à PPP_TRAMAGE. +const enPixels = (mm) => Math.round((mm * PPP_TRAMAGE) / MM_PAR_POUCE); + +// Trame les pages données, [{page, cadre}], en PNG, dans l'ordre : chaque +// page sur un canevas de son cadre, fond blanc, à PPP_TRAMAGE. Rend leurs +// octets ; lève quand la page tramée n'a pas la taille de son cadre — une +// page tournée par /Rotate, que le cadre lu des boîtes ne suit pas. +async function tramerPages(octets, pages, canevas) { + const { getDocument } = await import('pdfjs-dist/legacy/build/pdf.mjs'); + const tache = getDocument({ + data: new Uint8Array(octets), + verbosity: 0, + isEvalSupported: false, + disableFontFace: true, + useSystemFonts: false, + standardFontDataUrl: policesStandard(), + }); + const document = await tache.promise; + try { + const images = []; + for (const { page: rang, cadre } of pages) { + const page = await document.getPage(rang); + const viewport = page.getViewport({ scale: PPP_TRAMAGE / PT_PAR_POUCE }); + const largeur = Math.round(viewport.width); + const hauteur = Math.round(viewport.height); + if (largeur !== cadre.largeur || hauteur !== cadre.hauteur) { + throw new Error(`tramerPdf : page ${rang} tramée à ${largeur} × ${hauteur}, son cadre est ${cadre.largeur} × ${cadre.hauteur}`); + } + const toile = canevas.createCanvas(largeur, hauteur); + const contexte = toile.getContext('2d'); + await page.render({ canvasContext: contexte, canvas: toile, viewport, background: '#ffffff' }).promise; + images.push(new Uint8Array(await toile.encode('png'))); + } + return images; + } finally { + await tache.destroy(); + } +} + +/** + * Lit les pages demandées d'un PDF et, quand ecrire est vrai, les trame en + * PNG sous le dossier d'attente de la racine, à .png (§ 19.6). + * Dans l'ordre : les pages demandées et les octets se contrôlent, le PDF se + * lit (test/pdf.js), chaque page doit exister ; puis, en écriture, le + * canevas se charge — absent, le refus le nomme et rien ne s'écrit —, toutes + * les pages se trament, et alors seulement les images s'écrivent. Sans + * écriture, aucun canevas n'est chargé. + * + * @param {{octetsB64: string, pages: Array<{page: number, fichier: string}>, + * racine?: string|null, ecrire?: boolean}} demande + * @param {{chargerCanevas?: () => Object}} [options] le chargeur du canevas + * @returns {Promise<{pdf: string, mode: string, pages: Array<{fichier: string, + * page: number, cadre: {largeur: number, hauteur: number}, chemin: string|null, + * textes: string[], segments: Array<{x1: number, y1: number, x2: number, y2: number}>}>}>} + * pdf : le SHA-256 des octets ; cadre : la boîte de média à PPP_TRAMAGE, + * en pixels arrondis ; chemin : l'image écrite, null sans écriture ; + * textes : les fragments de la couche de texte, dans l'ordre du flux ; + * segments : les traits droits, en mm, l'origine au coin haut gauche + */ +export async function tramer({ octetsB64, pages, racine = null, ecrire = true }, { chargerCanevas: charger = chargerCanevas } = {}) { + const base = racineDe(racine); + const demandees = pagesDemandees(pages); + const octets = octetsDe(octetsB64); + const { lirePdf } = await import('../pdf.js'); + let lu; + try { + lu = await lirePdf(octets); + } catch (erreur) { + throw new Error(`tramerPdf : PDF illisible : ${erreur.message}`); + } + for (const { page } of demandees) { + if (page < 1 || page > lu.pages.length) throw new Error(`tramerPdf : page ${page} hors du document de ${lu.pages.length} pages`); + } + const lues = demandees.map(({ page, fichier }) => { + const { boite, textes, segments } = lu.pages[page - 1]; + return { + fichier, + page, + cadre: { largeur: enPixels(boite.largeur), hauteur: enPixels(boite.hauteur) }, + chemin: null, + textes: textes.map(({ texte }) => texte), + segments, + }; + }); + if (ecrire) { + let canevas; + try { + canevas = charger(); + } catch (erreur) { + throw new Error( + `tramerPdf : le canevas « ${CANEVAS} » manque — make captures l’exige pour tramer les pages du PDF ; rien n’est écrit (${erreur.message})`, + ); + } + const images = await tramerPages(octets, lues, canevas); + const dossier = join(base, ATTENTE); + await mkdir(dossier, { recursive: true }); + for (const [rang, lue] of lues.entries()) { + lue.chemin = join(dossier, `${lue.fichier}.png`); + await ecrireAtomique(lue.chemin, images[rang]); + } + } + return { pdf: sha256(octets), mode: MODE_TRAMAGE, pages: lues }; +} + +/** + * La commande de la page : tramer, sur le PDF que la page passe en base64 + * (octetsB64) — aucun octet ne traverse en Uint8Array. Rend ce que le PDF + * donne à lire et les chemins des images, jamais d'octets. + */ +export async function tramerPdf(_context, demande) { + return tramer(demande ?? {}); +} diff --git a/test/navigateur/commandes_documentation.test.js b/test/navigateur/commandes_documentation.test.js new file mode 100644 index 0000000..92ac4e4 --- /dev/null +++ b/test/navigateur/commandes_documentation.test.js @@ -0,0 +1,332 @@ +// © 2026 TechnoLibre (http://www.technolibre.ca) +// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) + +// Épreuves sous node des commandes des captures qui touchent au PDF de la +// planche (§ 19.5, § 19.6) : tramerPdf lit chaque page demandée — texte, +// traits, taille à 96 ppp —, la trame en PNG sous le dossier d'attente quand +// on le lui demande, et refuse en nommant le canevas quand il manque ; la +// publication admet, à côté des captures du navigateur, une page de PDF à la +// taille de sa page. Chaque épreuve travaille dans un dossier d'épreuve +// (dossierEpreuve), effacé à la fin. +// +// Les PDF des épreuves se construisent ici par pdf-lib, une fois par +// fichier : le premier, une page A4 qui porte un trait de 100 mm et une ligne +// de texte, une page A6 qui porte un nom inventé, dans la police embarquée ; +// le second, deux pages vides aux dimensions de deux cadres d'écran. Toute +// image s'écrit par tramerPdf : l'épreuve n'écrit rien elle-même. +import assert from 'node:assert/strict'; +import { createHash } from 'node:crypto'; +import { readFile } from 'node:fs/promises'; +import { join } from 'node:path'; +import fontkit from '@pdf-lib/fontkit'; +import { PDFDocument, grayscale } from 'pdf-lib'; +import { describe, test } from '../lanceur.js'; +import { lirePolices } from '../polices.js'; +import { VERSION } from '../../src/version.genere.js'; +import { CHEMIN_MANIFESTE, DOSSIER_CAPTURES, lireEntetePng } from '../../scripts/documentation/manifeste.js'; +import { + COMMANDES, + MODE_TRAMAGE, + PPP_TRAMAGE, + canevasDisponible, + chargerCanevas, + deposerCapture, + dossierEpreuve, + effacerDossierEpreuve, + empreintesDossier, + lireManifeste, + publierCaptures, + tramer, + tramerPdf, +} from './commandes_documentation.js'; + +const sha256 = (octets) => createHash('sha256').update(octets).digest('hex'); +const enBase64 = (octets) => Buffer.from(octets).toString('base64'); + +// Le point typographique et le pixel CSS, en millimètres. +const PT_PAR_MM = 72 / 25.4; +const PX_PAR_MM = 96 / 25.4; + +// Les deux pages du PDF des épreuves, en mm, et ce que chacune porte. +const A4 = Object.freeze({ largeur: 210, hauteur: 297 }); +const A6 = Object.freeze({ largeur: 105, hauteur: 148 }); +const LIGNE_A4 = 'Feuille témoin'; +const NOM_A6 = 'Ondine Lacasse'; +// Le trait de la page A4 : 100 mm, à 20 mm du bord gauche et 30 mm du haut. +const TRAIT = Object.freeze({ x: 20, y: 30, longueur: 100 }); + +// La racine neutre des textes relevés : inventée, elle n'existe nulle part +// ailleurs dans le dépôt. +const RACINE_NEUTRE = 'C:\\Seance\\Tables'; + +// Le dossier d'attente d'une racine, et le chemin d'une image déposée. +const ATTENTE = `${DOSSIER_CAPTURES}/.attente`; +const deposee = (racine, fichier) => join(racine, ATTENTE, `${fichier}.png`); + +// La taille attendue d'une page à 96 ppp : ses millimètres en pixels CSS, +// arrondis à l'entier. +const enPixels = ({ largeur, hauteur }) => ({ largeur: Math.round(largeur * PX_PAR_MM), hauteur: Math.round(hauteur * PX_PAR_MM) }); + +async function construirePdf() { + const document = await PDFDocument.create({ updateMetadata: false }); + document.registerFontkit(fontkit); + const police = await document.embedFont(lirePolices().regulier, { subset: true }); + const a4 = document.addPage([A4.largeur * PT_PAR_MM, A4.hauteur * PT_PAR_MM]); + const yTrait = (A4.hauteur - TRAIT.y) * PT_PAR_MM; + a4.drawLine({ + start: { x: TRAIT.x * PT_PAR_MM, y: yTrait }, + end: { x: (TRAIT.x + TRAIT.longueur) * PT_PAR_MM, y: yTrait }, + thickness: 0.5, + color: grayscale(0), + }); + a4.drawText(LIGNE_A4, { x: TRAIT.x * PT_PAR_MM, y: yTrait - 40, size: 14, font: police, color: grayscale(0) }); + const a6 = document.addPage([A6.largeur * PT_PAR_MM, A6.hauteur * PT_PAR_MM]); + a6.drawText(NOM_A6, { x: 30, y: 200, size: 18, font: police, color: grayscale(0) }); + return document.save(); +} + +// Deux pages vides de la taille de deux cadres d'écran, en px CSS : le +// cadre des captures du navigateur, et un autre. +const ECRAN = Object.freeze({ largeur: 1366, hauteur: 700 }); +const AUTRE_ECRAN = Object.freeze({ largeur: 1280, hauteur: 700 }); +async function construireEcrans() { + const document = await PDFDocument.create({ updateMetadata: false }); + for (const { largeur, hauteur } of [ECRAN, AUTRE_ECRAN]) document.addPage([(largeur * 72) / 96, (hauteur * 72) / 96]); + return document.save(); +} + +const OCTETS = await construirePdf(); +const B64 = enBase64(OCTETS); +const PAGES = Object.freeze([ + { page: 1, fichier: '24-badges-controle' }, + { page: 2, fichier: '25-badges-planche' }, +]); + +// Un chargeur de canevas qui échoue comme un paquet optionnel absent. +const canevasAbsent = () => { + const erreur = new Error("Cannot find module '@napi-rs/canvas'"); + erreur.code = 'MODULE_NOT_FOUND'; + throw erreur; +}; + +// Exécute faire(racine) dans un dossier d'épreuve neuf, effacé ensuite. +async function dansUnDossier(faire) { + const racine = await dossierEpreuve(); + try { + return await faire(racine); + } finally { + await effacerDossierEpreuve(null, racine); + } +} + +// La raison d'un saut quand le canevas manque : le tramage ne s'éprouve que +// là où make captures peut tramer. +const SANS_CANEVAS = 'le canevas de pdfjs (@napi-rs/canvas) manque sur ce système : le tramage ne s’y éprouve pas'; + +// Le nombre de pixels d'une image PNG plus sombres que le gris moyen. +async function pixelsSombres(octets) { + const { createCanvas, loadImage } = chargerCanevas(); + const image = await loadImage(Buffer.from(octets)); + const canevas = createCanvas(image.width, image.height); + const contexte = canevas.getContext('2d'); + contexte.drawImage(image, 0, 0); + const { data } = contexte.getImageData(0, 0, image.width, image.height); + let sombres = 0; + for (let i = 0; i < data.length; i += 4) if (data[i] + data[i + 1] + data[i + 2] < 3 * 128) sombres += 1; + return sombres; +} + +describe('tramerPdf : la lecture des pages d’un PDF (§ 19.6)', () => { + test('déclarée parmi les commandes, exportée sous son nom', () => { + assert.ok(COMMANDES.includes('tramerPdf')); + assert.equal(typeof tramerPdf, 'function'); + }); + + test('sans écrire : le texte, les traits et la taille à 96 ppp de chaque page demandée, l’empreinte des octets ; aucun canevas chargé, rien d’écrit', async () => { + await dansUnDossier(async (racine) => { + const lu = await tramer({ octetsB64: B64, pages: PAGES, racine, ecrire: false }, { chargerCanevas: canevasAbsent }); + assert.equal(lu.pdf, sha256(OCTETS)); + assert.equal(lu.mode, MODE_TRAMAGE); + assert.equal(PPP_TRAMAGE, 96); + assert.deepEqual( + lu.pages.map(({ fichier, page, cadre, chemin }) => ({ fichier, page, cadre, chemin })), + [ + { fichier: '24-badges-controle', page: 1, cadre: enPixels(A4), chemin: null }, + { fichier: '25-badges-planche', page: 2, cadre: enPixels(A6), chemin: null }, + ], + ); + assert.deepEqual(enPixels(A4), { largeur: 794, hauteur: 1123 }); + assert.deepEqual(lu.pages[0].textes, [LIGNE_A4]); + assert.deepEqual(lu.pages[1].textes, [NOM_A6]); + // pdf-lib écrit ses coordonnées en points à six décimales au plus. + const pres = (a, b) => Math.abs(a - b) < 1e-3; + const horizontaux = lu.pages[0].segments.filter(({ y1, y2 }) => pres(y1, y2)); + assert.equal(horizontaux.length, 1); + const [trait] = horizontaux; + assert.ok(pres(Math.abs(trait.x2 - trait.x1), TRAIT.longueur), JSON.stringify(trait)); + assert.ok(pres(trait.y1, TRAIT.y), JSON.stringify(trait)); + assert.deepEqual(lu.pages[1].segments, []); + assert.deepEqual(await empreintesDossier(null, { racine }), []); + }); + }); + + test('une seule page, la seconde : seule lue', async () => { + const lu = await tramer({ octetsB64: B64, pages: [PAGES[1]], ecrire: false }, { chargerCanevas: canevasAbsent }); + assert.deepEqual(lu.pages.map(({ fichier, textes }) => [fichier, textes]), [['25-badges-planche', [NOM_A6]]]); + }); + + test('refus nommés, rien d’écrit : octets hors du base64, PDF illisible, aucune page, page hors du document, nom refusé, nom en double', async () => { + await dansUnDossier(async (racine) => { + const essayer = (args) => tramer({ racine, ecrire: true, ...args }, { chargerCanevas: canevasAbsent }); + await assert.rejects(essayer({ octetsB64: 42, pages: PAGES }), /tramerPdf : octetsB64/); + await assert.rejects(essayer({ octetsB64: 'pas du base64 !', pages: PAGES }), /tramerPdf : octetsB64/); + await assert.rejects(essayer({ octetsB64: enBase64(new TextEncoder().encode('%PDF-1.7 tronqué')), pages: PAGES }), /tramerPdf : PDF illisible/); + await assert.rejects(essayer({ octetsB64: B64, pages: [] }), /tramerPdf : aucune page demandée/); + await assert.rejects(essayer({ octetsB64: B64, pages: [{ page: 3, fichier: '25-badges-planche' }] }), /tramerPdf : page 3 hors du document de 2 pages/); + await assert.rejects(essayer({ octetsB64: B64, pages: [{ page: 0, fichier: '25-badges-planche' }] }), /tramerPdf : page 0 hors du document de 2 pages/); + await assert.rejects(essayer({ octetsB64: B64, pages: [{ page: 1, fichier: '../hors' }] }), /nom de capture refusé/); + await assert.rejects( + essayer({ octetsB64: B64, pages: [PAGES[0], { page: 2, fichier: PAGES[0].fichier }] }), + /tramerPdf : « 24-badges-controle » demandée deux fois/, + ); + assert.deepEqual(await empreintesDossier(null, { racine }), []); + }); + }); +}); + +describe('tramerPdf : le tramage, sous make captures (§ 19.6, décision 2)', () => { + test('canevas absent : le refus nomme le paquet, sa cause et make captures ; rien d’écrit', async () => { + await dansUnDossier(async (racine) => { + await assert.rejects( + tramer({ octetsB64: B64, pages: PAGES, racine, ecrire: true }, { chargerCanevas: canevasAbsent }), + (erreur) => { + assert.match(erreur.message, /^tramerPdf : le canevas « @napi-rs\/canvas » manque/); + assert.match(erreur.message, /make captures/); + assert.match(erreur.message, /Cannot find module/); + return true; + }, + ); + assert.deepEqual(await empreintesDossier(null, { racine }), []); + }); + }); + + test('chaque page demandée tramée en PNG sous le dossier d’attente, à la taille de sa page à 96 ppp, son encre rendue', async (contexte) => { + if (!canevasDisponible()) contexte.skip(SANS_CANEVAS); + await dansUnDossier(async (racine) => { + const lu = await tramerPdf(null, { octetsB64: B64, pages: PAGES, racine }); + assert.equal(lu.pdf, sha256(OCTETS)); + for (const [rang, format] of [A4, A6].entries()) { + const { fichier, chemin, cadre } = lu.pages[rang]; + assert.equal(chemin, deposee(racine, fichier)); + const octets = new Uint8Array(await readFile(chemin)); + assert.deepEqual(lireEntetePng(octets), enPixels(format), fichier); + assert.deepEqual(cadre, enPixels(format), fichier); + assert.ok((await pixelsSombres(octets)) > 0, `${fichier} : aucune encre tramée`); + } + const ecrits = (await empreintesDossier(null, { racine })).map(([chemin]) => chemin); + assert.deepEqual(ecrits, [`${ATTENTE}/24-badges-controle.png`, `${ATTENTE}/25-badges-planche.png`]); + }); + }); + + test('les mêmes octets de PDF donnent les mêmes octets de PNG', async (contexte) => { + if (!canevasDisponible()) contexte.skip(SANS_CANEVAS); + const tramees = []; + for (let fois = 0; fois < 2; fois += 1) { + tramees.push( + await dansUnDossier(async (racine) => { + const { pages } = await tramerPdf(null, { octetsB64: B64, pages: PAGES, racine }); + return Promise.all(pages.map(async ({ chemin }) => sha256(await readFile(chemin)))); + }), + ); + } + assert.deepEqual(tramees[1], tramees[0]); + assert.notEqual(tramees[0][0], tramees[0][1]); + }); +}); + +// Le contexte de commande que lit la publication : la version du navigateur, +// inconnue ici. +const CONTEXTE = Object.freeze({ page: { context: () => ({ browser: () => null }) } }); + +const ECRANS = await construireEcrans(); + +// Dépose sous le dossier d'attente une capture de la source donnée : la page +// donnée, tramée par tramerPdf, en est l'image, et sa taille le cadre. Une +// page de PDF se tire du PDF des épreuves, une capture du navigateur des +// pages d'écran. +async function deposer(racine, { fichier, etape, source, page }) { + const octets = source === 'pdf' ? OCTETS : ECRANS; + const { pdf, mode, pages } = await tramerPdf(null, { octetsB64: enBase64(octets), pages: [{ page, fichier }], racine }); + const [{ cadre, chemin }] = pages; + const entree = { + fichier, + etape, + source, + versionReelle: VERSION.affichee, + graine: null, + cadre, + facteurEchelle: 1, + mode: source === 'pdf' ? mode : 'chromium-headless-shell', + theme: 'clair', + instant: '2031-05-06T20:15:00-04:00', + texte: [fichier], + styles: { clair: [], sombre: [] }, + etat: null, + pdf: source === 'pdf' ? pdf : null, + }; + return deposerCapture(null, { fichier, entree, chemin, racine }); +} + +// Les images s'y écrivent par tramerPdf : sans canevas, ces épreuves ne +// s'y jouent pas. +describe('publierCaptures : une page de PDF à côté des captures du navigateur (§ 19.5, § 19.6)', () => { + test('une capture du navigateur et une page de PDF de cadres différents se publient ensemble ; le pilote porte le cadre du navigateur', async (contexte) => { + if (!canevasDisponible()) contexte.skip(SANS_CANEVAS); + await dansUnDossier(async (racine) => { + await deposer(racine, { fichier: '01-premier-ecran', etape: '1', source: 'navigateur', page: 1 }); + await deposer(racine, { fichier: '24-badges-controle', etape: '12', source: 'pdf', page: 1 }); + const bilan = await publierCaptures(CONTEXTE, { + declarees: ['01-premier-ecran', '24-badges-controle'], + racine, + racineNeutre: RACINE_NEUTRE, + }); + assert.deepEqual(bilan.ecrites, ['01-premier-ecran', '24-badges-controle']); + const manifeste = await lireManifeste(null, { racine }); + assert.deepEqual(manifeste.pilote.cadre, ECRAN); + assert.deepEqual( + manifeste.captures.map(({ fichier, source, cadre, pdf }) => ({ fichier, source, cadre, pdf })), + [ + { fichier: '01-premier-ecran', source: 'navigateur', cadre: ECRAN, pdf: null }, + { fichier: '24-badges-controle', source: 'pdf', cadre: enPixels(A4), pdf: sha256(OCTETS) }, + ], + ); + const ecrits = (await empreintesDossier(null, { racine })).map(([chemin]) => chemin); + assert.deepEqual(ecrits, [`${DOSSIER_CAPTURES}/01-premier-ecran.png`, `${DOSSIER_CAPTURES}/24-badges-controle.png`, CHEMIN_MANIFESTE]); + }); + }); + + test('deux captures du navigateur de cadres différents refusent toujours la publication, rien de publié', async (contexte) => { + if (!canevasDisponible()) contexte.skip(SANS_CANEVAS); + await dansUnDossier(async (racine) => { + await deposer(racine, { fichier: '01-premier-ecran', etape: '1', source: 'navigateur', page: 1 }); + await deposer(racine, { fichier: '02-import-apercu', etape: '2', source: 'navigateur', page: 2 }); + await assert.rejects( + publierCaptures(CONTEXTE, { declarees: ['01-premier-ecran', '02-import-apercu'], racine, racineNeutre: RACINE_NEUTRE }), + /publication : 02-import-apercu n’a pas le cadre ni le facteur d’échelle de 01-premier-ecran/, + ); + assert.deepEqual(await empreintesDossier(null, { racine }), []); + }); + }); + + test('une page de PDF seule, sans capture du navigateur, ne donne aucun pilote : refusée, rien de publié', async (contexte) => { + if (!canevasDisponible()) contexte.skip(SANS_CANEVAS); + await dansUnDossier(async (racine) => { + await deposer(racine, { fichier: '24-badges-controle', etape: '12', source: 'pdf', page: 1 }); + await assert.rejects( + publierCaptures(CONTEXTE, { declarees: ['24-badges-controle'], racine, racineNeutre: RACINE_NEUTRE }), + /publication : aucune capture du navigateur/, + ); + assert.deepEqual(await empreintesDossier(null, { racine }), []); + }); + }); +}); diff --git a/vitest.config.js b/vitest.config.js index 685f64f..e8e5bc7 100644 --- a/vitest.config.js +++ b/vitest.config.js @@ -20,9 +20,10 @@ // 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). La commande -// d'impression (test/navigateur/commandes_impression.js), qui -// imprime le document d'une épreuve en PDF par le moteur de +// 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';