Calendario: si vedono tutti gli orari validi, e il PDF ne fa una pagina ciascuno

Il popup mostrava solo l'orario del momento: chi guarda ad agosto vuole sapere
com'e' settembre per intero, e una griglia sola gli fa credere che valga per
sempre. Ora ci sono tutti quelli non ancora scaduti, ognuno con la sua etichetta
- In vigore, oppure la data da cui parte - e quelli passati spariscono da soli.

Il bottone scarica /calendario/tutti.pdf: un orario per pagina, con le giornate
fuori griglia ripetute su ognuna, perche' un foglio stampato da solo deve bastare
a se stesso. Gli id singoli restano validi per mandarne uno solo.

calendarioDaMostrare (uno) diventa calendariDaMostrare (tutti): una funzione
sola, non due che dicono cose simili - e' lo stesso difetto dei due link della
pagina servizi, che erano due espressioni per lo stesso indirizzo e sono
divergute.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-17 17:22:22 +02:00
parent d03c62641e
commit 69bd17a296
7 changed files with 207 additions and 147 deletions
+16 -4
View File
@@ -1,11 +1,11 @@
import { describe, it, expect } from 'vitest';
import { avvisi, calendari } from '../src/data/calendari';
import { generaCalendarioPdf, nomeFilePdf } from '../src/lib/calendario-pdf';
import { generaCalendariPdf, nomeFilePdf } from '../src/lib/calendario-pdf';
describe('PDF del calendario', () => {
for (const cal of calendari) {
it(`${cal.id}: produce un PDF valido`, async () => {
const pdf = await generaCalendarioPdf(cal);
const pdf = await generaCalendariPdf([cal]);
// Un PDF comincia sempre con %PDF- e finisce con %%EOF: se il documento non venisse
// chiuso (`doc.end()` mancante, o un errore a metà) il file arriverebbe monco al
// browser, che mostrerebbe una pagina bianca invece di un errore.
@@ -20,7 +20,7 @@ describe('PDF del calendario', () => {
// /Type /Pages, che dichiara quante pagine contiene.
it('sta in una pagina sola, anche con le giornate fuori griglia in fondo', async () => {
for (const cal of calendari) {
const pdf = await generaCalendarioPdf(cal, avvisi);
const pdf = await generaCalendariPdf([cal], avvisi);
const conteggio = /\/Type\s*\/Pages[^>]*?\/Count\s+(\d+)/s.exec(pdf.toString('latin1'));
expect(conteggio, `${cal.id}: numero di pagine non dichiarato`).not.toBeNull();
expect(Number(conteggio![1]), `${cal.id}: il calendario occupa più di una pagina`).toBe(1);
@@ -28,8 +28,20 @@ describe('PDF del calendario', () => {
});
it('il nome del file distingue i due periodi', () => {
const nomi = calendari.map(nomeFilePdf);
const nomi = calendari.map((c) => nomeFilePdf([c]));
expect(new Set(nomi).size).toBe(nomi.length);
for (const n of nomi) expect(n).toMatch(/^insanitylab-calendario-[a-z0-9-]+\.pdf$/);
// Più orari insieme: un nome che nominasse solo il primo farebbe credere che dentro ci
// sia quello e basta.
expect(nomeFilePdf(calendari)).toBe('insanitylab-calendario-class.pdf');
});
// Un orario per pagina: due griglie sullo stesso foglio si confonderebbero fra loro, e
// spezzarne una a metà toglie proprio ciò che si va a cercare, l'incrocio giorno/ora.
it('con più orari fa una pagina per ciascuno', async () => {
const pdf = await generaCalendariPdf(calendari, avvisi);
const conteggio = /\/Type\s*\/Pages[^>]*?\/Count\s+(\d+)/s.exec(pdf.toString('latin1'));
expect(conteggio).not.toBeNull();
expect(Number(conteggio![1])).toBe(calendari.length);
});
});