/** * Check del parsing CSI: `bun src/lib/csi-core.test.ts`. * Con CSI_LIVE=1 verifica anche gli endpoint reali del portale. */ import assert from "node:assert/strict"; import { CSI_COPPA_PROJECT_ID, isNostraSquadra, parseClassifica, partiteDaEventi, partiteFormatoSospetto, partiteGiocate, urlClassifica, urlPartite, } from "@/lib/csi-core"; const htmlClassifica = `
PosSquadra
1Altra Squadra Girone A 401613321421824
PosSquadra
1Paolo Poggi Volley & C. 401613321431726
4 C.R.A.P. Volley 30161063336288 14271329980.561.07
`; const righe = parseClassifica(htmlClassifica); assert.equal(righe.length, 2, "prende solo il girone che contiene la nostra squadra"); assert.deepEqual(righe[1], { pos: 4, squadra: "C.R.A.P. Volley", punti: 30, giocate: 16, vinte: 10, perse: 6, setFatti: 36, setSubiti: 28, }); assert.equal(righe[0]!.squadra, "Paolo Poggi Volley & C.", "decodifica le entità HTML"); assert.deepEqual(parseClassifica("

pagina cambiata

"), [], "portale cambiato: nessun crash"); // La Coppa ha un girone più piccolo (poche squadre) ma la stessa struttura di tabella del // campionato: `parseClassifica()` funziona invariata, non serve un parser dedicato. const htmlCoppa = `
PosSquadra
1Set in the City 73210084
2C.R.A.P. Volley 63210085
`; const righeCoppa = parseClassifica(htmlCoppa); assert.equal(righeCoppa.length, 2, "girone di Coppa più piccolo del campionato: ok comunque"); assert.equal(righeCoppa[1]!.squadra, "C.R.A.P. Volley"); assert.ok(isNostraSquadra("CRAP Volley") && isNostraSquadra("C.R.A.P. Volley ")); assert.ok(!isNostraSquadra("CRAP Volley B")); const eventi = [ { id: 1, start: "2025-11-12T22:00:00", team1: "C.R.A.P. Volley", team2: "AMCM", result: "3 - 1", partials: "25 - 23
23 - 25
25 - 18
25 - 22
", field: "Sabin Piccolo", project: "PVM - Campionato Open Misto Eccellenza", }, { id: 2, start: "2025-11-19T22:00:00", team1: "Gnu Tim SdC", team2: "C.R.A.P. Volley", result: "3 - 2", partials: "25 - 21
18 - 25
", field: "BVI", project: "PVM - Campionato Open Misto Eccellenza", }, { id: 3, start: "2026-09-10T21:00:00", team1: "C.R.A.P. Volley", team2: "Esselle", result: "" }, { id: 4, start: "2025-10-01T21:00:00", team1: "Esselle", team2: "AMCM", result: "3 - 0" }, ]; const partite = partiteDaEventi(eventi); assert.equal(partite.length, 3, "scarta le gare di altre squadre"); assert.equal(partite[0]!.data, "2026-09-10", "ordinate dalla più recente"); assert.equal(partite[0]!.setNostri, null, "gara futura senza risultato"); const casa = partite.find((p) => p.id === "1")!; assert.deepEqual([casa.casa, casa.avversario, casa.setNostri, casa.setLoro], [true, "AMCM", 3, 1]); assert.deepEqual(casa.parziali[1], [23, 25]); assert.equal(casa.ora, "22:00"); const trasferta = partite.find((p) => p.id === "2")!; assert.deepEqual( [trasferta.casa, trasferta.avversario, trasferta.setNostri, trasferta.setLoro], [false, "Gnu Tim SdC", 2, 3], "in trasferta il punteggio va ribaltato", ); assert.deepEqual(trasferta.parziali[0], [21, 25], "anche i parziali"); assert.equal(partiteGiocate(partite).length, 2); assert.deepEqual(partiteDaEventi("non è un array"), [], "risposta inattesa: nessun crash"); // --- partiteFormatoSospetto: distingue "nessuna gara ancora" da "formato rotto" ------------- assert.equal( partiteFormatoSospetto(eventi, partite), false, "eventi grezzi presenti e riconosciuti: nessun sospetto", ); assert.equal( partiteFormatoSospetto([], []), false, "nessun evento grezzo: probabilmente solo una stagione senza gare, non un formato rotto", ); assert.equal( partiteFormatoSospetto("non è un array", []), true, "la risposta non è più un array: il formato è cambiato", ); const eventiSenzaCampiRiconosciuti = [ { id: 1, quando: "2025-11-12", squadraCasa: "C.R.A.P. Volley", squadraOspite: "AMCM" }, ]; assert.equal( partiteFormatoSospetto( eventiSenzaCampiRiconosciuti, partiteDaEventi(eventiSenzaCampiRiconosciuti), ), true, "eventi presenti ma con campi rinominati: nessuno riconosciuto, sospetto fondato", ); if (process.env["CSI_LIVE"]) { const [html, htmlCoppa, json] = await Promise.all([ fetch(urlClassifica()).then((r) => r.text()), fetch(urlClassifica(CSI_COPPA_PROJECT_ID)).then((r) => r.text()), fetch(urlPartite()).then((r) => r.json()), ]); const live = parseClassifica(html); const nostra = live.find((r) => isNostraSquadra(r.squadra)); assert.ok(nostra, "la nostra squadra è in classifica"); assert.ok(live.length >= 8 && nostra.giocate > 0); const liveCoppa = parseClassifica(htmlCoppa); assert.ok( liveCoppa.some((r) => isNostraSquadra(r.squadra)), "la nostra squadra è nel girone di Coppa", ); const livePartite = partiteDaEventi(json); assert.ok(livePartite.length > 0 && partiteGiocate(livePartite).length > 0); console.log(`live: ${live.length} squadre, ${livePartite.length} partite, noi ${nostra.pos}°`); } console.log("csi-core: ok");