Completa la copertura test del badge Presenza fissa e ne documenta il comportamento
Nessun bug trovato: contaPresenzeGiocatore() filtra correttamente per convocati, tipo evento e stato (presente/ritardo contano, assente/forse no), gli eventi futuri restano esclusi. Confermato che, a differenza di MVP/pagelle/badge social, questo badge non ha bisogno dell'estensione RLS di M13: il filtro sui convocati è già nella funzione pura, non solo in UI. Aggiunti test unit sulle soglie (badges.test.ts) e un nuovo end-to-end (presenze-badge.test.ts) che scrive eventi e risposte reali sul database locale e verifica l'intera pipeline fetchPresenze()/daRiga() -> contaPresenzeGiocatore() -> statoBadge() attraverso le tre soglie, incluso il caso "non convocato, la riga esiste ma non conta". docs/modules/badge.md aggiornato con la pipeline, la copertura test e la correzione della dicitura "in stagione" (il conteggio è sull'intero storico, coerente con gli altri badge). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+31
-9
@@ -92,7 +92,7 @@ soglia raggiunta o superata (soglie inclusive), oltre l'oro resta oro.
|
|||||||
| `mvp` | MVP | partite vinte nettamente al voto MVP dei compagni (`g.mvp`, vedi pipeline sopra) | 1 / 3 / 5 |
|
| `mvp` | MVP | partite vinte nettamente al voto MVP dei compagni (`g.mvp`, vedi pipeline sopra) | 1 / 3 / 5 |
|
||||||
| `pagella` | Pagellone | media dei voti pagella ricevuti dai compagni a fine partita (`g.mediaVoto`), solo se ne ha ricevuti almeno `VOTI_MINIMI_PAGELLA` (5) | 6.5 / 7.5 / 8.5 |
|
| `pagella` | Pagellone | media dei voti pagella ricevuti dai compagni a fine partita (`g.mediaVoto`), solo se ne ha ricevuti almeno `VOTI_MINIMI_PAGELLA` (5) | 6.5 / 7.5 / 8.5 |
|
||||||
| `palloni` | Sherpa dei palloni | quante volte hai fatto (o ti è stato proposto, vedi sopra) il turno palloni (`g.palloni`) | 3 / 6 / 10 |
|
| `palloni` | Sherpa dei palloni | quante volte hai fatto (o ti è stato proposto, vedi sopra) il turno palloni (`g.palloni`) | 3 / 6 / 10 |
|
||||||
| `presenze` | Presenza fissa | totale presenze a eventi/partite in stagione (`g.presenze`) | 5 / 15 / 30 |
|
| `presenze` | Presenza fissa | totale presenze (presente o ritardo) a eventi/partite di sempre, non solo della stagione in corso (`g.presenze`) | 5 / 15 / 30 |
|
||||||
| `serie-allenamenti` | Sempre in palestra | allenamenti consecutivi presenti, senza saltarne uno (`g.serieAllenamenti`) | 3 / 6 / 10 |
|
| `serie-allenamenti` | Sempre in palestra | allenamenti consecutivi presenti, senza saltarne uno (`g.serieAllenamenti`) | 3 / 6 / 10 |
|
||||||
| `serie-conferme` | Risposta lampo | conferme di presenza consecutive date entro 24h dalla convocazione (`g.serieConferme`) | 3 / 8 / 15 |
|
| `serie-conferme` | Risposta lampo | conferme di presenza consecutive date entro 24h dalla convocazione (`g.serieConferme`) | 3 / 8 / 15 |
|
||||||
|
|
||||||
@@ -151,13 +151,16 @@ categoria): nessun bug trovato nella logica di calcolo di nessuno dei 16 badge.
|
|||||||
- `palloni`: soglie 3/6/10 testate esplicitamente (bronzo/argento/oro, confine incluso e
|
- `palloni`: soglie 3/6/10 testate esplicitamente (bronzo/argento/oro, confine incluso e
|
||||||
oltre l'oro resta oro, `badges.test.ts:94-104`), oltre a un caso di progresso non tondo
|
oltre l'oro resta oro, `badges.test.ts:94-104`), oltre a un caso di progresso non tondo
|
||||||
(5/6 → 83%). Pipeline end-to-end sotto, come `mvp`/`pagella`.
|
(5/6 → 83%). Pipeline end-to-end sotto, come `mvp`/`pagella`.
|
||||||
- `presenze`, `serie-allenamenti`, `serie-conferme`: stessa funzione di soglia già testata a
|
- `presenze`: soglie 5/15/30 testate esplicitamente (confine incluso, oltre l'oro resta oro,
|
||||||
fondo su `mvp`/`pagella`/`palloni`, coperti dagli invarianti generali
|
`badges.test.ts:108-116`). Pipeline end-to-end sotto, come `mvp`/`pagella`/`palloni`.
|
||||||
(`badges.test.ts:154-159`: soglie crescenti, testi presenti, id unici) e da
|
- `serie-allenamenti`, `serie-conferme`: stessa funzione di soglia già testata a fondo sugli
|
||||||
`collezioneBadge`/`prossimoTraguardo` con valori al massimo (`:119-144`).
|
altri badge normali, coperti dagli invarianti generali (`badges.test.ts:154-159`: soglie
|
||||||
- Nessun integration dedicato per questi 3: non toccano il database, le statistiche sorgente
|
crescenti, testi presenti, id unici) e da `collezioneBadge`/`prossimoTraguardo` con valori
|
||||||
(`presenze.test.ts`, ecc.) sono già coperte nei rispettivi moduli. `mvp`, `pagella` e
|
al massimo (`:119-144`).
|
||||||
`palloni` fanno eccezione (sotto) perché la loro fonte passa da una tabella di voto/turni.
|
- Nessun integration dedicato per questi 2: non toccano il database, le statistiche sorgente
|
||||||
|
(`serie.test.ts`) sono già coperte nel modulo Serie. `mvp`, `pagella`, `palloni` e
|
||||||
|
`presenze` fanno eccezione (sotto) perché la loro fonte passa da una tabella di voto/turni/
|
||||||
|
presenze, non da un contatore già calcolato altrove.
|
||||||
|
|
||||||
**Badge segreti** — ognuno testato con la propria condizione esatta e il confine appena sotto
|
**Badge segreti** — ognuno testato con la propria condizione esatta e il confine appena sotto
|
||||||
(`badges.test.ts:77-109`): `s-tiebreak` (mediaVoto 7.9 non basta, serve 8), `s-mai-forfait`
|
(`badges.test.ts:77-109`): `s-tiebreak` (mediaVoto 7.9 non basta, serve 8), `s-mai-forfait`
|
||||||
@@ -214,6 +217,25 @@ dedicata: nessun bug trovato, ma il comportamento "le proposte contano" — già
|
|||||||
confermato nulla; verifica anche che un evento futuro non conti, pur avendo già
|
confermato nulla; verifica anche che un evento futuro non conti, pur avendo già
|
||||||
un'assegnazione.
|
un'assegnazione.
|
||||||
|
|
||||||
|
**Badge Presenza fissa — pipeline end-to-end** (analisi dedicata: nessun bug trovato; a
|
||||||
|
differenza di MVP/pagelle/badge social, per questo badge **non serve** l'estensione RLS di
|
||||||
|
M13 — vedi sotto):
|
||||||
|
- Unit: `badges.test.ts:108-116` — soglie 5/15/30 (confine incluso, oltre l'oro resta oro) +
|
||||||
|
`presenze.test.ts`, già molto completo prima di questa sessione (`contaPresenzeGiocatore()`
|
||||||
|
con ritardo che conta come presenza, denominatore uguale per tutti, eventi futuri esclusi,
|
||||||
|
filtro sui convocati, solo partite/allenamenti).
|
||||||
|
- Integration (`npx supabase start` richiesto):
|
||||||
|
- `obiettivi.test.ts` — copre già `contaPresenzeGiocatore()` end-to-end per l'obiettivo
|
||||||
|
"250 presenze complessive" (o3), la stessa funzione usata dal badge.
|
||||||
|
- `presenze-badge.test.ts` (nuovo) — end-to-end reale sul badge: scrive eventi e risposte
|
||||||
|
su `eventi_app`/`risposte_presenze`, rilegge via REST come fa `fetchPresenze()`/`daRiga()`
|
||||||
|
e verifica che `statoBadge()` attraversi le tre soglie con dati veri (incluso un ritardo
|
||||||
|
che conta come presenza e un'assenza che non conta). Dimostra anche che una risposta
|
||||||
|
scritta per un evento senza convocazione **non conta comunque**, perché
|
||||||
|
`contaPresenzeGiocatore()` filtra già per `convocati` lato applicazione — a differenza di
|
||||||
|
MVP/pagelle/badge social, qui non serve una policy RLS aggiuntiva: il filtro è nella
|
||||||
|
funzione pura che il badge consuma, non solo in UI.
|
||||||
|
|
||||||
**Badge social** — nessuna delle 5 categorie ha logica *propria* nel codice: l'id è solo una
|
**Badge social** — nessuna delle 5 categorie ha logica *propria* nel codice: l'id è solo una
|
||||||
chiave di raggruppamento, `conteggioCategoria`/`vincitoreCategoria`/`badgeSocialVinti` sono
|
chiave di raggruppamento, `conteggioCategoria`/`vincitoreCategoria`/`badgeSocialVinti` sono
|
||||||
identici per tutte (`badge-social.ts:107-158`). Testare a fondo 2-3 categorie copre l'intero
|
identici per tutte (`badge-social.ts:107-158`). Testare a fondo 2-3 categorie copre l'intero
|
||||||
@@ -232,7 +254,7 @@ meccanismo:
|
|||||||
| 1 | `mvp` | normale | ✅ | ✅ (`scritture`, `permessi`, `mvp-badge`) |
|
| 1 | `mvp` | normale | ✅ | ✅ (`scritture`, `permessi`, `mvp-badge`) |
|
||||||
| 2 | `pagella` | normale | ✅ (incl. soglia minima voti) | ✅ (`scritture`, `permessi`, `pagella-badge`) |
|
| 2 | `pagella` | normale | ✅ (incl. soglia minima voti) | ✅ (`scritture`, `permessi`, `pagella-badge`) |
|
||||||
| 3 | `palloni` | normale | ✅ | ✅ (`scritture`, `palloni-badge`) |
|
| 3 | `palloni` | normale | ✅ | ✅ (`scritture`, `palloni-badge`) |
|
||||||
| 4 | `presenze` | normale | ✅ | non necessario |
|
| 4 | `presenze` | normale | ✅ | ✅ (`obiettivi`, `presenze-badge`) |
|
||||||
| 5 | `serie-allenamenti` | normale | ✅ (limite noto sotto) | non necessario |
|
| 5 | `serie-allenamenti` | normale | ✅ (limite noto sotto) | non necessario |
|
||||||
| 6 | `serie-conferme` | normale | ✅ (limite noto sotto) | non necessario |
|
| 6 | `serie-conferme` | normale | ✅ (limite noto sotto) | non necessario |
|
||||||
| 7 | `s-tiebreak` | segreto | ✅ | non necessario |
|
| 7 | `s-tiebreak` | segreto | ✅ | non necessario |
|
||||||
|
|||||||
@@ -0,0 +1,197 @@
|
|||||||
|
/**
|
||||||
|
* Badge Presenza fissa end-to-end contro il database locale:
|
||||||
|
* `bun test/integration/presenze-badge.test.ts`.
|
||||||
|
*
|
||||||
|
* I test unitari (`test/unit/presenze.test.ts`, `test/unit/badges.test.ts`) verificano
|
||||||
|
* `contaPresenzeGiocatore()` e `statoBadge()` come funzioni pure, con eventi e risposte
|
||||||
|
* costruiti a mano. Qui invece si scrivono eventi e risposte veri su `eventi_app`/
|
||||||
|
* `risposte_presenze`, si rileggono via REST con la stessa forma di `fetchPresenze()`/
|
||||||
|
* `daRiga()`, e si passa il risultato attraverso `contaPresenzeGiocatore()` fino a
|
||||||
|
* `statoBadge()` sul badge `presenze`: se una colonna cambia nome o la mappatura si rompe, qui
|
||||||
|
* il grado del badge torna sbagliato anche se i test unitari restano verdi, perché quelli non
|
||||||
|
* toccano mai il database.
|
||||||
|
*
|
||||||
|
* Copre anche un punto verificato nell'analisi ma non ovvio: **non serve nessun controllo a
|
||||||
|
* database sui convocati** per questo badge (a differenza di MVP/pagelle/badge social, vedi
|
||||||
|
* M13 in `docs/modules/badge.md`) perché `contaPresenzeGiocatore()` filtra già gli eventi per
|
||||||
|
* `convocati` lato applicazione — una risposta scritta per un evento a cui non si era
|
||||||
|
* convocati non conta comunque, anche se la riga esiste nel database.
|
||||||
|
*
|
||||||
|
* Gira solo sullo stack locale (`npx supabase start`) e cancella le proprie righe alla fine:
|
||||||
|
* usa id con il prefisso `test-presenze-badge`, che nessun dato vero può avere.
|
||||||
|
*/
|
||||||
|
import assert from "node:assert/strict";
|
||||||
|
import { badgeDefs, statoBadge } from "@/lib/badges";
|
||||||
|
import { contaPresenzeGiocatore } from "@/lib/presenze";
|
||||||
|
import { daRiga, type RigaEvento, type Evento } from "@/lib/eventi";
|
||||||
|
import { giocatori, type Giocatore } from "@/lib/crapp-data";
|
||||||
|
import { statoLocale } from "../helpers/locale";
|
||||||
|
import { prova, riepilogo, salta } from "../helpers/prova";
|
||||||
|
|
||||||
|
const locale = statoLocale();
|
||||||
|
|
||||||
|
if (!locale) {
|
||||||
|
salta("badge presenze sul database", "stack locale non attivo (npx supabase start)");
|
||||||
|
riepilogo("presenze-badge");
|
||||||
|
} else {
|
||||||
|
const { url: URL_BASE, servizio: SERVIZIO } = locale;
|
||||||
|
console.log(`badge presenze su ${URL_BASE}`);
|
||||||
|
|
||||||
|
const PREFISSO = "test-presenze-badge";
|
||||||
|
const presenzeDef = badgeDefs.find((b) => b.id === "presenze")!;
|
||||||
|
// "Oggi" fissato nel futuro: gli eventi scritti sotto sono datati nel passato remoto, così
|
||||||
|
// restano "passati" (quindi contati) a prescindere da quando gira il test.
|
||||||
|
const OGGI = "2099-01-01";
|
||||||
|
|
||||||
|
const rest = (percorso: string, init?: RequestInit) =>
|
||||||
|
fetch(`${URL_BASE}/rest/v1/${percorso}`, {
|
||||||
|
...init,
|
||||||
|
headers: {
|
||||||
|
apikey: SERVIZIO,
|
||||||
|
Authorization: `Bearer ${SERVIZIO}`,
|
||||||
|
"content-type": "application/json",
|
||||||
|
...(init?.headers ?? {}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/** `2020-01-01` per i=1, avanzando di un giorno per ogni evento: niente collisioni di data. */
|
||||||
|
const dataEvento = (i: number) => {
|
||||||
|
const d = new Date(Date.UTC(2020, 0, 1));
|
||||||
|
d.setUTCDate(d.getUTCDate() + i - 1);
|
||||||
|
return d.toISOString().slice(0, 10);
|
||||||
|
};
|
||||||
|
|
||||||
|
async function creaEvento(id: string, i: number, convocati?: string[]) {
|
||||||
|
const res = await rest("eventi_app", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { Prefer: "resolution=merge-duplicates,return=representation" },
|
||||||
|
body: JSON.stringify({
|
||||||
|
id,
|
||||||
|
tipo: "allenamento",
|
||||||
|
titolo: `Allenamento ${id}`,
|
||||||
|
data: dataEvento(i),
|
||||||
|
...(convocati ? { convocati } : {}),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
if (!res.ok) throw new Error(`creazione evento ${id}: ${res.status} ${await res.text()}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function rispondi(eventoId: string, giocatoreId: string, stato: string) {
|
||||||
|
const res = await rest("risposte_presenze?on_conflict=evento_id,giocatore_id", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { Prefer: "resolution=merge-duplicates,return=representation" },
|
||||||
|
body: JSON.stringify({ evento_id: eventoId, giocatore_id: giocatoreId, stato }),
|
||||||
|
});
|
||||||
|
if (!res.ok) throw new Error(`upsert su risposte_presenze: ${res.status} ${await res.text()}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Rilegge esattamente come fa l'app: `daRiga()` per gli eventi. */
|
||||||
|
async function leggiEventi(): Promise<Evento[]> {
|
||||||
|
const res = await rest(
|
||||||
|
"eventi_app?id=like." +
|
||||||
|
PREFISSO +
|
||||||
|
"*&select=id,tipo,titolo,luogo,data,ora,note,convocati,campionato,casa,pagelle_chiuse,creato_il",
|
||||||
|
);
|
||||||
|
const righe = (await res.json()) as RigaEvento[];
|
||||||
|
return righe.map(daRiga);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Rilegge esattamente come `fetchPresenze()`. */
|
||||||
|
async function leggiPresenze(): Promise<Record<string, Record<string, string>>> {
|
||||||
|
const res = await rest(
|
||||||
|
`risposte_presenze?evento_id=like.${PREFISSO}*&select=evento_id,giocatore_id,stato`,
|
||||||
|
);
|
||||||
|
const righe = (await res.json()) as Array<{
|
||||||
|
evento_id: string;
|
||||||
|
giocatore_id: string;
|
||||||
|
stato: string;
|
||||||
|
}>;
|
||||||
|
const mappa: Record<string, Record<string, string>> = {};
|
||||||
|
for (const r of righe) (mappa[r.evento_id] ??= {})[r.giocatore_id] = r.stato;
|
||||||
|
return mappa;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Un giocatore azzerato, come in `test/unit/badges.test.ts`. */
|
||||||
|
function giocatoreAzzerato(presenze: number): Giocatore {
|
||||||
|
return { ...giocatori[0]!, presenze, mvp: 0, mediaVoto: 0, votiPagella: 0, palloni: 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await prova(
|
||||||
|
"il badge presenze passa da bronzo a oro con presenze vere lette dal database",
|
||||||
|
async () => {
|
||||||
|
// 30 allenamenti passati. "pp1" risponde a tutti e 30 (i primi 5 "presente", un
|
||||||
|
// "ritardo" nel mezzo per verificare che conti come presenza, il resto "presente"),
|
||||||
|
// così una sola scrittura basta a verificare le tre soglie 5/15/30.
|
||||||
|
for (let i = 1; i <= 30; i += 1) {
|
||||||
|
await creaEvento(`${PREFISSO}-a${String(i).padStart(2, "0")}`, i);
|
||||||
|
}
|
||||||
|
for (let i = 1; i <= 30; i += 1) {
|
||||||
|
const stato = i === 10 ? "ritardo" : "presente";
|
||||||
|
await rispondi(`${PREFISSO}-a${String(i).padStart(2, "0")}`, "pp1", stato);
|
||||||
|
}
|
||||||
|
// "pp2" risponde solo ai primi 5: resta a bronzo, non oltre.
|
||||||
|
for (let i = 1; i <= 5; i += 1) {
|
||||||
|
await rispondi(`${PREFISSO}-a${String(i).padStart(2, "0")}`, "pp2", "presente");
|
||||||
|
}
|
||||||
|
// "pp2" risponde anche "assente" a un evento: non deve contare.
|
||||||
|
await rispondi(`${PREFISSO}-a06`, "pp2", "assente");
|
||||||
|
|
||||||
|
const eventi = await leggiEventi();
|
||||||
|
assert.equal(eventi.length, 30, "tutti gli eventi scritti si rileggono");
|
||||||
|
const presenze = await leggiPresenze();
|
||||||
|
|
||||||
|
const contoPp1 = contaPresenzeGiocatore("pp1", eventi, presenze, OGGI);
|
||||||
|
assert.equal(contoPp1, 30, "30 risposte, incluso un ritardo contato come presenza");
|
||||||
|
assert.equal(
|
||||||
|
statoBadge(presenzeDef, giocatoreAzzerato(contoPp1)).grado,
|
||||||
|
"oro",
|
||||||
|
"30 presenze: soglia oro raggiunta",
|
||||||
|
);
|
||||||
|
|
||||||
|
const contoPp2 = contaPresenzeGiocatore("pp2", eventi, presenze, OGGI);
|
||||||
|
assert.equal(contoPp2, 5, "5 presenti, l'assente su a06 non conta");
|
||||||
|
const badgePp2 = statoBadge(presenzeDef, giocatoreAzzerato(contoPp2));
|
||||||
|
assert.equal(badgePp2.grado, "bronzo", "5 presenze: soglia bronzo raggiunta, non oltre");
|
||||||
|
assert.equal(badgePp2.prossimo, "argento");
|
||||||
|
assert.equal(badgePp2.prossimaSoglia, 15);
|
||||||
|
|
||||||
|
// Un pp2 a metà strada (15 presenze) sblocca l'argento.
|
||||||
|
for (let i = 7; i <= 16; i += 1) {
|
||||||
|
await rispondi(`${PREFISSO}-a${String(i).padStart(2, "0")}`, "pp2", "presente");
|
||||||
|
}
|
||||||
|
const eventiDopo = await leggiEventi();
|
||||||
|
const presenzeDopo = await leggiPresenze();
|
||||||
|
const contoPp2Dopo = contaPresenzeGiocatore("pp2", eventiDopo, presenzeDopo, OGGI);
|
||||||
|
assert.equal(contoPp2Dopo, 15, "5 + 10 nuove presenze");
|
||||||
|
assert.equal(
|
||||||
|
statoBadge(presenzeDef, giocatoreAzzerato(contoPp2Dopo)).grado,
|
||||||
|
"argento",
|
||||||
|
"15 presenze: soglia argento raggiunta",
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
await prova(
|
||||||
|
"una risposta a un evento senza convocazione non conta per il badge, anche se la riga esiste",
|
||||||
|
async () => {
|
||||||
|
// "pp3" non è tra i convocati di questo evento (lista esplicita che lo esclude), ma
|
||||||
|
// scrive comunque una risposta "presente" — bypassando l'interfaccia, come farebbe
|
||||||
|
// chi parla direttamente con PostgREST. Deve restare a zero: la difesa è nella
|
||||||
|
// funzione pura, non in una policy RLS (a differenza di MVP/pagelle/badge social).
|
||||||
|
await creaEvento(`${PREFISSO}-ristretto`, 40, ["pp1"]);
|
||||||
|
await rispondi(`${PREFISSO}-ristretto`, "pp3", "presente");
|
||||||
|
|
||||||
|
const eventi = await leggiEventi();
|
||||||
|
const presenze = await leggiPresenze();
|
||||||
|
const conto = contaPresenzeGiocatore("pp3", eventi, presenze, OGGI);
|
||||||
|
assert.equal(conto, 0, "pp3 non era convocato: la risposta non conta");
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
await rest(`risposte_presenze?evento_id=like.${PREFISSO}*`, { method: "DELETE" });
|
||||||
|
await rest(`eventi_app?id=like.${PREFISSO}*`, { method: "DELETE" });
|
||||||
|
}
|
||||||
|
|
||||||
|
riepilogo("presenze-badge");
|
||||||
|
}
|
||||||
@@ -105,6 +105,16 @@ assert.equal(
|
|||||||
"5 turni su 6 per l'argento: 83%",
|
"5 turni su 6 per l'argento: 83%",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// --- presenze: soglie 5 / 15 / 30 ---------------------------------------------
|
||||||
|
const presenzeDef = badgeDefs.find((b) => b.id === "presenze")!;
|
||||||
|
assert.equal(gradoRaggiunto(presenzeDef, 4), null, "sotto la prima soglia nessun grado");
|
||||||
|
assert.equal(gradoRaggiunto(presenzeDef, 5), "bronzo", "la soglia è inclusiva");
|
||||||
|
assert.equal(gradoRaggiunto(presenzeDef, 14), "bronzo");
|
||||||
|
assert.equal(gradoRaggiunto(presenzeDef, 15), "argento");
|
||||||
|
assert.equal(gradoRaggiunto(presenzeDef, 29), "argento");
|
||||||
|
assert.equal(gradoRaggiunto(presenzeDef, 30), "oro");
|
||||||
|
assert.equal(gradoRaggiunto(presenzeDef, 999), "oro", "oltre l'oro resta oro");
|
||||||
|
|
||||||
// --- badgeGiocatore ----------------------------------------------------------
|
// --- badgeGiocatore ----------------------------------------------------------
|
||||||
assert.equal(badgeGiocatore(g()).length, badgeDefs.length, "i badge normali sono sempre tutti");
|
assert.equal(badgeGiocatore(g()).length, badgeDefs.length, "i badge normali sono sempre tutti");
|
||||||
assert.ok(
|
assert.ok(
|
||||||
|
|||||||
Reference in New Issue
Block a user