test/README.md covers the commands, what each folder verifies, whether it
needs the network, and the one real limit: the app renders after
hydration, so the end-to-end tests check HTTP responses and the data
behind the pages, not the rendered interface.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
sessioneScaduta compared Date.now() against NaN when aggiornato_il was
not a valid date, and every comparison with NaN is false: the session
was reported as still active, so the Scout Live table stayed locked to a
player who could no longer release it.
An unreadable timestamp now frees the session, which is the safe
direction: at worst someone takes over a scouting session that was
already unattended.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The project had no automated verification at all, so the "Test" step in
the AGENTS.md workflow rested entirely on clicking through the app.
The suite runs on bun with node:assert and adds no dependency: every file
is a script that exits non-zero when a check fails, and test/run.ts runs
each one in its own process. Unit tests cover the rules that decide what
players see (badges, streaks, ball duty rotation, ratings, MVP ties,
scouting totals, goals, notifications, CSI parsing); integration and
end-to-end tests drive the real dev server. Nothing writes to the
database, so both can be pointed at a live environment.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Campionato page showed hardcoded demo data. It now reads the real
2025/26 season (Campionato Open Misto Eccellenza, project 767, team
3359, Girone B) from the Livescore CSI Bologna portal.
The portal has no documented API: we call the same endpoints its own
pages call over ajax, so parsing must degrade gracefully. A single
server route fetches them, caches for 6 hours and serves the last good
payload on failure; the page falls back to the previous data when
nothing is available. No browser ever contacts the portal, keeping the
request count independent of how many players open the app.
Also fixes the header, which claimed "Girone C - CSI Milano".
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>