gestion_table_tournante_libre/test/imprimante_simulee.test.js
Mathieu Benoit 8b7c732399 [ADD] platform: print bridge, atomic byte writes, badge sheet file name
Printed views and the badge sheet leave the app through the platform. Under
Electron a gtt:imprimer channel prints with the paper and orientation asked
for and reports sent, cancelled, failed or unknown; an exception is logged
to the console and never shown raw to the operator. Every file system,
real or simulated, writes bytes atomically from a copy taken at the call.
The sheet name carries event, date and imposition, and a failed print
becomes IMPRESSION_ECHEC.
Checked: red first, twelve mutations caught; 3502 node, 659 browser and 79
long tests green from the index alone.

--- FR ---

[ADD] plateforme : pont d'impression, octets atomiques, nom de planche

Les vues imprimables et la planche sortent de l'application par la
plateforme. Sous Electron, un canal gtt:imprimer imprime au papier et à
l'orientation demandés et rend envoyé, annulé, échec ou inconnu ; une
exception va à la console, jamais brute à l'opérateur. Chaque système de
fichiers, réel ou simulé, écrit des octets de façon atomique, depuis une
copie prise à l'appel. Le nom de la planche porte événement, date et
imposition, et une impression échouée devient IMPRESSION_ECHEC.
Vérifié : rouge d'abord, douze mutations attrapées ; 3502 node, 659
navigateur et 79 longues vertes depuis l'index seul.

Assisted-by: Claude Opus 5.5
2026-10-09 15:26:13 -04:00

74 lines
3.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

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

// © 2026 TechnoLibre (http://www.technolibre.ca)
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
// L'imprimante d'épreuve (§ 13.4) : la troisième implémentation de la
// frontière « impression », qui relève ses appels et rend l'issue qu'on lui
// règle. Son câblage — src/main.js, le montage des épreuves, App — se garde
// dans test/arborescence.test.js, que leurs motifs de surveillance relancent.
import assert from 'node:assert/strict';
import { PAPIERS } from '../src/geometrie/papiers.js';
import { creerImprimanteSimulee } from './imprimante_simulee.js';
import { describe, test } from './lanceur.js';
describe("imprimante d'épreuve", () => {
test('par défaut, chaque impression est envoyée, sans cause, et chaque appel se relève avec ses options, dans l’ordre', async () => {
const imprimante = creerImprimanteSimulee();
const demandes = [];
for (const papier of Object.keys(PAPIERS)) {
for (const orientation of ['portrait', 'paysage']) {
demandes.push({ papier, orientation });
assert.deepEqual(await imprimante.imprimer({ papier, orientation }), { issue: 'envoye', cause: null });
}
}
assert.deepEqual(imprimante.appels(), demandes);
});
test("l'issue et la cause réglées se rendent à chaque appel : annulée, échouée et sa cause, inconnue", async () => {
for (const reglage of [
{ issue: 'annule', cause: null },
{ issue: 'echec', cause: 'failed' },
{ issue: 'inconnue', cause: null },
]) {
const imprimante = creerImprimanteSimulee(reglage);
assert.deepEqual(await imprimante.imprimer({ papier: 'A4', orientation: 'portrait' }), reglage);
assert.deepEqual(await imprimante.imprimer({ papier: 'A4', orientation: 'paysage' }), reglage);
assert.equal(imprimante.appels().length, 2);
}
});
test('le relevé est une copie : ni les options reçues, ni le tableau rendu ne le changent ; seuls papier et orientation y entrent', async () => {
const imprimante = creerImprimanteSimulee();
const options = { papier: 'A4', orientation: 'portrait', silent: true };
await imprimante.imprimer(options);
options.papier = 'Lettre';
imprimante.appels().push({ papier: 'A4', orientation: 'paysage' });
imprimante.appels()[0].orientation = 'paysage';
assert.deepEqual(imprimante.appels(), [{ papier: 'A4', orientation: 'portrait' }]);
});
test('une option hors domaine rejette TypeError, comme les deux imprimantes réelles, et ne se relève pas', async () => {
const imprimante = creerImprimanteSimulee();
for (const options of [
{ papier: 'A3', orientation: 'portrait' },
{ papier: 'toString', orientation: 'portrait' },
{ papier: 'A4', orientation: 'landscape' },
{ papier: 'A4' },
undefined,
]) {
await assert.rejects(imprimante.imprimer(options), TypeError, JSON.stringify(options));
}
assert.deepEqual(imprimante.appels(), []);
});
test("un réglage hors du contrat se refuse à la construction : issue inconnue, cause d'un autre type, cause pour une issue qui n'en porte pas", () => {
for (const reglage of [
{ issue: 'imprime' },
{ issue: 'echec', cause: 3 },
{ issue: 'envoye', cause: 'failed' },
{ issue: 'annule', cause: 'cancelled' },
null,
]) {
assert.throws(() => creerImprimanteSimulee(reglage), TypeError, JSON.stringify(reglage));
}
});
});