The Spades Online test suite is organized into three layers: unit tests that cover pure game logic with no external service dependencies, integration tests that exercise real HTTP API routes against a live PostgreSQL database, and WebSocket tests that validate real-time event flows. All tests run viaDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Antonelli-Tech-Solutions/spades/llms.txt
Use this file to discover all available pages before exploring further.
npm test using the Node.js built-in test runner — no additional test framework is required.
Running Tests
node --test 'test/**/*.test.js', which discovers and executes every test file matching the glob pattern.
Unit tests always run. Integration tests are automatically skipped when
DATABASE_URL is not set in the environment. You can run the full unit suite locally without any external services.Test Categories
Unit Tests
Location:
test/unit/Pure logic tests with no database or Redis dependency. Covers:- Game engine — bidding logic, scoring, trick resolution, deck creation, and full game state machine (
test/unit/game/) - Auth logic — registration validation and credential checks (
test/unit/auth/) - Web client — form validation helpers and API client wrappers (
test/unit/web/) - Lobby logic — table creation and seat management (
test/unit/lobby/) - Middleware — rate limiter logic (
test/unit/middleware/)
DATABASE_URL or REDIS_URL required.Integration Tests
Location:
test/integration/End-to-end HTTP route tests that hit real Express handlers backed by a live PostgreSQL database. Covers:- Auth routes — register, verify email, login, logout, forgot/reset password (
test/integration/auth/) - Social & friends routes — player search, friend requests, blocks, presence (
test/integration/social/) - Game routes — table creation, seating, bidding, card play, state reads (
test/integration/game/)
DATABASE_URL. Game integration tests also require REDIS_URL.WebSocket Tests
Location:
test/ws/Tests for real-time event flows over live WebSocket connections. Covers:- Connection & auth — upgrade handshake, session validation, rejection of unauthenticated connections
- Disconnect handling — presence cleanup, session teardown
- Table event flows —
JOIN,LEAVE, game event broadcasts to the table room - Lobby events —
JOIN_LOBBY,TABLE_CREATED,TABLE_UPDATED,TABLE_REMOVEDpub/sub - Personal notification channel — friend request and invite delivery via
player:{id}:notify
serverHelper.js test helper spins up a real Express + WebSocket server on a random port for each test, keeping tests fully isolated.Anti-Cheat Tests
Location:
test/unit/anticheat/Server-side move validation logic tests. Covers:- Turn enforcement — verifying it is the correct player’s turn before accepting a bid or card play
- Card legality — following-suit rules, spades-breaking rules, Blind Nil eligibility
- Hand membership — confirming the played card is actually in the player’s hand
Linting
ESLint runs against the integration test directory:eslint test/integration and checks the integration test files for style and correctness issues. Linting runs in CI before the test suite — a lint failure blocks the test run.
CI Pipeline
The CI workflow runs on every push toqa and main, and on every pull request targeting dev, qa, or main.
- Redis is always available — the workflow spins up a
redis:7-alpineservice container with a health check, so all WebSocket and Redis-dependent tests run in CI DATABASE_URLis not set — integration tests that require PostgreSQL are skipped in CI by default; they are intended to be run in a separate environment with a real database- Lint runs first — the
Lintstep runsnpm run lintagainsttest/integration/before the test suite; any ESLint error fails the build immediately - Test timeout — the full test run has a 5-minute timeout to prevent hung tests from blocking the pipeline
- Node.js 24 — CI uses Node.js 24 via
actions/setup-node@v4with npm dependency caching
DEV_AUTO_VERIFY
When developing locally without an SMTP server, email verification creates a bottleneck — you can only fully register one account through the normal email flow. SetDEV_AUTO_VERIFY=true to bypass this:
POST /api/auth/register marks new accounts as verified immediately — no verification email is sent, no token is required, and you can log in right after registering. The flag is read at request time, so you can toggle it without restarting the server.
Bot Players for Testing
When testing gameplay locally, you often need all four seats filled to start a game. The table host can add bot players to any empty seat:north, east, south, west.
Bot player IDs follow the pattern bot:<seat> — for example, bot:north, bot:east. A table can have any mix of human and bot seats. Once all four seats are filled, the game starts automatically.
Bot behaviour is intentionally minimal:
- Bid: counts the number of spades in its hand and bids that number
- Play: picks a random card from the set of legal plays at each turn
GET /api/tables/:tableId/state as normal.
If a human player leaves a table mid-game, their seat is automatically filled by a bot so the game can continue. Bot players are a testing convenience — they are not the production AI opponent planned for a future release.