# Masoi E2e Testing

> Create and maintain automated tests for Ma Sói game engine, night/vote resolution, Socket.IO event contracts, race conditions, and role-specific edge cases. Use when adding test coverage, debugging flaky behavior, verifying concurrent action handling, or setting up CI testing.

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

---


# Ma Sói E2E Testing

## Workflow

1. Identify the component to test:
   - `server/gameEngine.js` → pure function unit tests.
   - `server/index.js` resolution logic → integration tests with mock socket/redis.
   - Socket contract → client-server event flow tests.
2. Write tests following patterns in `references/test-patterns.md`.
3. Run tests:
   - `cd server && npm test` (if test script configured).
   - `node --check server/index.js` (syntax baseline).
4. For race condition tests, simulate concurrent socket events and verify single resolution.

## Test Categories

### Unit Tests (Pure Functions)
- `calcWolfCount(n)` for various player counts.
- `getRoleConfig(n, customRoles)` produces valid role lists.
- `sanitizeCustomRoles(roles, n)` enforces wolf count limits.
- `assignRoles(players, customRoles)` returns exactly n assignments.
- `checkWinCondition(players)` for all win/draw states.
- `generateRoomCode()` produces valid 6-character codes.

### Integration Tests (Game Flow)
- Night resolution: wolf kill, doctor save, witch save, witch poison, combinations.
- Vote resolution: majority vote, tie, idiot reveal, wolf king drag, hunter shoot.
- Phase transitions: night → discuss → vote → night cycle.
- Game end: village win (all wolves dead), wolf win (wolves >= others).
- Timer-driven resolution: night timeout forces skip, vote timeout forces resolve.

### Contract Tests (Socket Events)
- Every client emit has a matching server handler.
- Every server emit used by gameplay has a matching client listener.
- Payload shapes match between server emit and client handler.
- Reconnect emits restore full game state.

### Race Condition Tests
- Two wolves choosing different targets simultaneously.
- All players voting at the same time.
- Night resolve and timer-forced resolve firing concurrently.
- Vote resolve and timer-forced resolve firing concurrently.
- Disconnect and reconnect during night resolution.

### Edge Case Tests
- Doctor saves wolf target, then witch also saves same target.
- Witch poisons the same player wolves attacked (double kill?).
- Hunter dies from poison, shoots another player who triggers chain effects.
- Wolf King hanged, drags Hunter, Hunter shoots → chain resolution.
- Idiot hanged twice — second time should kill.
- Only 1 wolf vs 1 villager — wolf wins immediately.
- All special roles dead — game still resolves correctly.

## Test Infrastructure

### Recommended Setup
- **Test runner**: Node.js built-in test runner (`node --test`) or Jest/Vitest.
- **Mock Redis**: In-memory Map-based mock for `server/db/redis.js`.
- **Mock PostgreSQL**: No-op mock for `server/db/postgres.js` (game logic doesn't depend on DB reads).
- **Mock Socket.IO**: Track emitted events and payloads for assertion.

### Test File Structure
```
server/
  __tests__/
    gameEngine.test.js     # Unit tests for pure functions
    nightResolve.test.js   # Integration tests for night resolution
    voteResolve.test.js    # Integration tests for vote resolution
    socketContract.test.js # Contract verification
    raceCondition.test.js  # Concurrent action tests
```

## References

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

