# Masoi Be Testing

> Create and maintain backend unit tests, integration tests, and API tests for Ma Sói server. Covers gameEngine.js pure functions, Socket.IO handler logic, Redis/PostgreSQL data layer, authentication, room lifecycle, and timer-driven resolution. Use when adding server-side test coverage, debugging server logic, or verifying backend changes.

- Skill: `nobodyonlyc/masoi-be-testing` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add nobodyonlyc/masoi-be-testing`
- Raw SKILL.md: https://api.skillmd.com/api/skills/nobodyonlyc/masoi-be-testing/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: nobodyonlyc (https://skillmd.com/u/nobodyonlyc)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/nobodyonlyc/masoi-be-testing

---


# Ma Sói Backend Testing

## Workflow

1. Identify the backend component to test:
   - `server/gameEngine.js` → pure function unit tests (role config, win conditions, wolf count).
   - `server/index.js` socket handlers → integration tests with mock socket/Redis.
   - `server/db/redis.js` → Redis data layer tests with mock/in-memory store.
   - `server/db/postgres.js` → PostgreSQL data layer tests with mock client.
   - Authentication flow → register/login handler tests with bcrypt mock.
2. Write tests following patterns in `references/be-test-patterns.md`.
3. Run tests:
   - `node --check server/index.js` (syntax baseline).
   - `node --check server/gameEngine.js` (syntax baseline).
   - `cd server && npm test` (if test script configured).
4. For concurrency tests, simulate concurrent socket events and verify `withRoomLock` serial execution.

## Test Categories

### Unit Tests — gameEngine.js

- `calcWolfCount(n)` returns correct wolf count for player counts 4–18.
- `getRoleConfig(n, customRoles)` produces valid role list with correct wolf/villager ratio.
- `sanitizeCustomRoles(roles, n)` enforces wolf count limits and role constraints.
- `assignRoles(players, customRoles)` returns exactly n assignments with shuffled distribution.
- `checkWinCondition(players)` for all win/draw/continue states.
- `generateRoomCode()` produces valid 6-character alphanumeric codes.

### Unit Tests — Socket Handler Logic

- `auth` handler validates credentials and maps userId to socketId.
- `create_room` handler creates room with correct initial state.
- `join_room` handler enforces room existence, capacity, and game-not-started.
- `toggle_ready` handler toggles player ready state correctly.
- `start_game` handler validates player count, ready state, and assigns roles.
- `night_action` handler validates role, phase, and alive status before accepting action.
- `cast_vote` handler validates phase, alive status, and target validity.

### Integration Tests — Night Resolution

- Wolf kill with no saves → target dies.
- Doctor saves wolf target → target lives.
- Witch saves wolf target → target lives, save potion consumed.
- Witch poisons + wolf kill → 2 deaths in one night.
- Doctor saves target, witch also saves same target → no double-save error.
- Hunter dies at night → `hunter_must_shoot` triggers correctly.
- All night actions skip → peaceful night, no deaths.
- Timer-forced resolution → pending actions auto-resolved as skip.

### Integration Tests — Vote Resolution

- Majority vote → target dies.
- Tie vote → nobody dies.
- Idiot first hanging → survives, `idiotRevealed = true`.
- Idiot second hanging → actually dies.
- Wolf King hanged → `wolf_king_must_choose` triggers drag mechanic.
- Hunter hanged → `hunter_must_shoot` triggers.
- Chain: Wolf King drags Hunter → Hunter shoots → chain resolution.

### Integration Tests — Room Lifecycle

- Create room → join → ready → start → play → end → play again.
- Host disconnect → host transfer to next player.
- All players disconnect → room cleanup after timeout.
- Kick player → player removed, room state updated.
- Leave room → player removed, host transfer if needed.
- Close room → all players notified, room deleted.

### Data Layer Tests — Redis

- `saveRoom(room)` serializes and stores room state.
- `getRoom(code)` deserializes room state correctly.
- `deleteRoom(code)` removes room and associated keys.
- `saveUserRoom(userId, roomCode)` and `getUserRoom(userId)` mapping.
- `clearUserRoom(userId)` cleanup.
- Room TTL and expiry behavior.

### Data Layer Tests — PostgreSQL

- `createUser(username, passwordHash)` inserts correctly.
- `findUserByUsername(username)` returns user or null.
- `saveGameResult(gameData)` persists game history.
- `getGameHistory(userId)` returns sorted game history.
- Connection pool handling and error recovery.

### Authentication Tests

- Register with valid credentials → user created, token returned.
- Register with duplicate username → error returned.
- Login with correct password → authenticated.
- Login with wrong password → rejected.
- Guest auth → temporary userId assigned.
- Socket reconnect with existing userId → session restored.

### Concurrency & Lock Tests

- `withRoomLock(code, fn)` ensures serial execution.
- Concurrent `night_action` from two wolves → only one `WOLF_ATTACK` set.
- Concurrent `resolveNight` calls → only one resolution executes.
- Concurrent `resolveVote` calls → only one resolution executes.
- Lock cleanup after function throws error.

## Test Infrastructure

### Recommended Setup
- **Test runner**: Vitest (preferred) or Node.js built-in test runner (`node --test`).
- **Mock Redis**: In-memory Map-based mock for `server/db/redis.js`.
- **Mock PostgreSQL**: In-memory array-based mock for `server/db/postgres.js`.
- **Mock Socket.IO**: Custom mock tracking emitted events, connected clients, and rooms.
- **Mock bcrypt**: Deterministic mock for faster tests (skip real hashing).

### Test File Structure
```
server/
  __tests__/
    unit/
      gameEngine.test.js       # Pure function unit tests
      roomCode.test.js         # Room code generation tests
    integration/
      nightResolve.test.js     # Night resolution scenarios
      voteResolve.test.js      # Vote resolution scenarios
      roomLifecycle.test.js    # Room create/join/leave/close
      auth.test.js             # Register/login/guest auth
    data/
      redis.test.js            # Redis data layer tests
      postgres.test.js         # PostgreSQL data layer tests
    concurrency/
      roomLock.test.js         # withRoomLock serial execution
      raceCondition.test.js    # Concurrent action tests
    mocks/
      mockRedis.js             # In-memory Redis mock
      mockPostgres.js          # In-memory PostgreSQL mock
      mockSocket.js            # Socket.IO mock with event tracking
```

## Verification Commands

```bash
# Syntax check (always run first)
node --check server/index.js
node --check server/gameEngine.js

# Run all backend tests
cd server && npm test

# Run specific test file
cd server && npx vitest run __tests__/unit/gameEngine.test.js

# Run with coverage
cd server && npx vitest run --coverage
```

## References

Load `references/be-test-patterns.md` when writing or reviewing backend tests.

