Skip to content

test: regression test suites for server and client#13

Merged
mateuseap merged 1 commit into
mainfrom
test/regression-suite
Jul 23, 2026
Merged

test: regression test suites for server and client#13
mateuseap merged 1 commit into
mainfrom
test/regression-suite

Conversation

@mateuseap

Copy link
Copy Markdown
Owner

The MVP is feature-complete, so this PR adds a regression safety net over the behavior that works today. All tests are characterization tests: they lock in current semantics (mocked Prisma and Redis, no real database) so future iterations cannot silently break move handling, game endings, ratings, matchmaking, auth, or the trilingual UI.

Changes made

Backend (jest, mocked Prisma/Redis, 7 new spec files, 87 new tests):

  • games.service.spec.ts: game creation per time control, bot vs human rating snapshots, the trimmed getGameCore selection shape (scalars plus move count, never the move list), pagination, endGame transitions (active to ended, idempotent re-end, pgn rebuild, rating updates skipped for bot and abandoned games), move recording, abandon
  • game-state.service.spec.ts: init state, clock charging with increment, zero clamp, promotion uci, draw offer lifecycle, move clears pending draw offer. Locks in that chess.js v1 throws on illegal moves instead of returning null
  • clock.service.spec.ts: 500ms grace period, cancel, reschedule replacement, per-game isolation
  • matchmaking.service.spec.ts: queue join/leave/re-join, 1200 default rating, base 100-point window, 50 points per 10s expansion capped at 400, cross-time-control isolation, coin-flip color assignment, expired entry sweep, bot game creation
  • auth.service.spec.ts: credential validation (banned, wrong password), registration conflicts and the four rating rows, sha256-only refresh token storage, 7-day expiry, refresh rotation (old token revoked, new hash issued), expired token revocation, logout revoking all sessions
  • leaderboards.service.spec.ts: Redis cache hit skips the database, cache miss queries only 5+ game players and writes back with a 300s TTL, Redis read and write failures fall through safely, rank offsets by page, provisional players excluded from ranks
  • game.gateway.spec.ts: full move flow (inactive game, non-player, out of turn, illegal move, legal move broadcast plus clock scheduling), checkmate ends the game with rating deltas, resign awards the opponent, draw offer/accept/decline, spectate replays ended games and sends live clocks, queue matched notifications for both colors

Frontend (vitest + @testing-library/react + jsdom, 5 new test files, 33 new tests):

  • Navbar.test.tsx: renders in en/pt/es with translated labels, asserts the ch-based min-width classes that prevent layout shift on language switch, language buttons call i18n.changeLanguage and persist to chesskernel-lang, auth vs anonymous variants, logout calls the API and clears the session
  • i18n.test.ts: pt and es have exactly the same key set as en, meta.title/meta.description exist and are translated, document.title and the meta description sync on languageChanged, pt maps to the pt-BR html lang tag
  • auth.store.test.ts and theme.store.test.ts: zustand state transitions and localStorage persistence keys
  • utils.test.ts: cn tailwind conflict resolution and formatMs clock formatting

Infrastructure:

  • Added client/vitest.config.ts (jsdom, reuses the vite aliases), fixing the empty-suite exit 1 that broke root pnpm test
  • Added jsdom and @testing-library/react as client devDependencies
  • Wired a Test job into .github/workflows/ci.yml (shared build, prisma generate, pnpm test), between Type Check and Build

Test plan

  • pnpm test at the root passes end to end: client 33/33 (5 files), server 95/95 (8 files, 87 new plus the pre-existing 8 glicko2 tests)
  • pnpm -r build clean (shared, client, server)
  • pnpm typecheck clean for all three packages
  • No real database or Redis needed: Prisma and Redis are mocked or faked in-memory, suites run in about 15s total

Intentionally not covered: Stockfish analysis service and bots service (spawn external engine processes), presence service, controllers (thin passthroughs over the tested services), react-chessboard and Phaser internals, and socket reconnection flows (need a real socket server, better suited to an e2e suite). Client eslint was already failing on main because no eslint config file is committed; left untouched as out of scope.

Backend (jest, 87 new tests across 7 spec files):
- games.service: move recording, game state transitions, result and
  rating handling, trimmed getGameCore selection shape
- game-state.service: clock accounting, move application, draw offers
- clock.service: timeout scheduling with grace period
- matchmaking.service: queue join/leave, rating windows, expiry sweep
- auth.service: credential validation, registration, refresh rotation
- leaderboards.service: cache hit/miss and rank computation
- game.gateway: move flow, resign, draw, spectate, queue handlers

Frontend (vitest + testing-library + jsdom, 33 new tests):
- Navbar: three-language rendering, ch-based width reservations,
  language switch persistence, auth vs anonymous variants, logout
- i18n: locale key parity, meta title/description sync, html lang
- auth and theme zustand stores: transitions and persistence keys
- lib/utils: cn merging and clock formatting

Also fixes the empty-suite vitest exit 1 that broke root pnpm test,
and wires a Test job into the CI workflow.
@mateuseap mateuseap self-assigned this Jul 23, 2026
@mateuseap
mateuseap merged commit c4c0a5a into main Jul 23, 2026
1 check passed
@mateuseap
mateuseap deleted the test/regression-suite branch July 23, 2026 14:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant