Cappa le vittorie di "10 vittorie in campionato" e completa la copertura test

o5 non aveva il Math.min(vittorie, 10) dei fratelli o3/o4: il progresso
mostrato non cambiava (già cappato al 100%), ma il valore grezzo sì, mostrato
senza cap in squadra.tsx/index.tsx (es. "15/10 vittorie" invece di "10/10").

Nessuno dei tre obiettivi aveva test. Le vittorie non toccano Supabase -
arrivano dal portale CSI via /api/public/csi - quindi l'integration test
estende test/integration/api.test.ts (che già chiama quella route dal vivo)
invece di test/integration/obiettivi.test.ts, verificando o3/o4/o5 sui dati
CSI reali del giorno.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-08 12:01:43 +02:00
co-authored by Claude Sonnet 5
parent 7e51fe6345
commit 242941740b
3 changed files with 83 additions and 2 deletions
+29 -1
View File
@@ -4,7 +4,9 @@
* Nessun test scrive sul database: solo letture e validazioni.
*/
import assert from "node:assert/strict";
import { isNostraSquadra, type DatiCsi } from "@/lib/csi-core";
import { giocatori } from "@/lib/crapp-data";
import { isNostraSquadra, partiteGiocate, type DatiCsi } from "@/lib/csi-core";
import { obiettiviSquadra } from "@/lib/obiettivi";
import { avviaServer, haSupabase, json } from "../helpers/server";
import { prova, riepilogo, salta } from "../helpers/prova";
@@ -58,6 +60,32 @@ try {
}
});
await prova(
"le vittorie in campionato lette dal CSI reale alimentano o3/o4/o5 in modo coerente",
() => {
// Stessa logica di useObiettivi() in src/lib/rosa.ts: partite giocate e vinte.
const vittorieReali = partiteGiocate(csi?.partite ?? []).filter(
(p) => (p.setNostri ?? 0) > (p.setLoro ?? 0),
).length;
const obiettivi = obiettiviSquadra(giocatori, {
eventi: [],
presenze: {},
pagelle: [],
vittorie: vittorieReali,
});
const o3 = obiettivi.find((o) => o.id === "o3")!;
const o4 = obiettivi.find((o) => o.id === "o4")!;
const o5 = obiettivi.find((o) => o.id === "o5")!;
assert.deepEqual([o3.target, o4.target, o5.target], [1, 5, 10], "target fissi 1/5/10");
assert.equal(o3.valore, Math.min(vittorieReali, 1), "prima vittoria, cappata a 1");
assert.equal(o4.valore, Math.min(vittorieReali, 5), "5 vittorie, cappata a 5");
assert.equal(o5.valore, Math.min(vittorieReali, 10), "10 vittorie, cappata a 10");
assert.ok(o3.valore <= o4.valore && o4.valore <= o5.valore, "progressione o3 ≤ o4 ≤ o5");
},
);
await prova("la seconda chiamata arriva dalla cache del server", async () => {
const t0 = Date.now();
const secondo = (await json(await fetch(url("/api/public/csi")))) as DatiCsi;
+53
View File
@@ -325,6 +325,59 @@ assert.equal(
);
}
// --- o3/o4/o5: vittorie in campionato (1/5/10), tutte cappate al target -------
{
const conVittorie = (n: number) => obiettiviSquadra(giocatori, { ...contestoVuoto, vittorie: n });
// Senza dato CSI (undefined) o a zero vittorie: tutti fermi a 0, nessun NaN.
for (const senzaVittorie of [contestoVuoto, { ...contestoVuoto, vittorie: 0 }]) {
const obiettivi = obiettiviSquadra(giocatori, senzaVittorie);
assert.equal(trova(obiettivi, "o3").valore, 0);
assert.equal(trova(obiettivi, "o4").valore, 0);
assert.equal(trova(obiettivi, "o5").valore, 0);
}
// I target restano fissi: 1, 5, 10.
assert.deepEqual(
[trova(vuoti, "o3").target, trova(vuoti, "o4").target, trova(vuoti, "o5").target],
[1, 5, 10],
);
// Progressione realistica: con 1 vittoria tutti e tre valgono 1 (o3 già al target,
// o4/o5 solo all'inizio).
assert.deepEqual(
[1, 2, 3].map((n) => trova(conVittorie(1), `o${n + 2}`).valore),
[1, 1, 1],
"1 vittoria: o3 al target, o4/o5 ancora lontani ma valgono 1",
);
const conCinque = conVittorie(5);
assert.deepEqual(
[trova(conCinque, "o3").valore, trova(conCinque, "o4").valore, trova(conCinque, "o5").valore],
[1, 5, 5],
"5 vittorie: o3 e o4 al target, o5 a metà",
);
const conDieci = conVittorie(10);
assert.deepEqual(
[trova(conDieci, "o3").valore, trova(conDieci, "o4").valore, trova(conDieci, "o5").valore],
[1, 5, 10],
"10 vittorie: tutti e tre al target",
);
// Oltre il target: o3 e o4 restavano già cappati con Math.min, o5 no (bug fixato:
// valore = vittorie invece di Math.min(vittorie, 10), incoerente con gli altri due e
// mostrato senza cap in squadra.tsx/index.tsx come "15/10 vittorie").
const conQuindici = conVittorie(15);
assert.deepEqual(
[
trova(conQuindici, "o3").valore,
trova(conQuindici, "o4").valore,
trova(conQuindici, "o5").valore,
],
[1, 5, 10],
"oltre il target tutti e tre restano cappati, o5 incluso",
);
}
// --- progressoObiettivo ------------------------------------------------------
const o = (valore: number, target: number): ObiettivoSquadra => ({
id: "x",