43 lines
2.3 KiB
Markdown
43 lines
2.3 KiB
Markdown
# TESTING.md
|
|
|
|
Runner: built-in `node:test` + `node:assert/strict`. No Jest/Mocha.
|
|
Script: `"test": "node --test tests/"` (add `--test-concurrency=1` if DB tests collide).
|
|
|
|
## Layout
|
|
- `tests/unit/` — pure functions in `src/game` and `src/utils`. No DB, no HTTP.
|
|
- `tests/integration/` — boot `app` with a **temporary SQLite file**, run migrations + seeds, call the real HTTP API.
|
|
|
|
## Test DB setup helper (`tests/helpers.js`)
|
|
- Create temp path via `os.tmpdir()`; set `process.env.DB_PATH` BEFORE requiring `src/db`.
|
|
- Run migrate + seed programmatically.
|
|
- Start the app on port 0 (`app.listen(0)`), return base URL and a `close()` fn.
|
|
- Provide `registerAndLogin(base)` which returns a cookie string to reuse in `fetch` headers.
|
|
- Delete the temp file in `after()`.
|
|
|
|
## What MUST be tested
|
|
| Area | Cases |
|
|
|---|---|
|
|
| energy | no time passed; partial tick; full cap; clock went backwards; large gap |
|
|
| leveling | exact XP threshold; multi-level jump; max level cap |
|
|
| stats | each class; equipment bonuses applied |
|
|
| combat | fixed seed → identical log; hero win; hero loss; round cap; min damage 1 |
|
|
| rewards | level-diff multiplier clamps; loot chance 0% / 100% |
|
|
| auth | register ok; duplicate (case-insensitive); weak password; login ok/fail; session persists; logout |
|
|
| hunt | spends energy; insufficient energy rejected; HP too low rejected; locked zone rejected; rewards persisted |
|
|
| inventory | equip swaps slot; can't equip others' items; use potion consumes 1 |
|
|
| shop | insufficient gold; level gate; sell equipped rejected; quantities validated |
|
|
| expedition | claim before end rejected; claim once only; second start while active rejected |
|
|
| leaderboard | sort allowlist; ordering correct |
|
|
|
|
## Determinism
|
|
Inject RNG: `createRng(seed)` (mulberry32) in `src/utils/rng.js` exposing `.float()`, `.int(min,max)`, `.range(min,max)`. In integration tests, allow overriding the RNG via an `app` factory option or env seed.
|
|
Inject time: tests set `time.setNow(fn)` to fast-forward energy/expeditions instead of sleeping.
|
|
|
|
## Naming
|
|
`describe('energy.computeEnergy', () => { it('caps at max', ...) })`.
|
|
|
|
## Rules
|
|
- A failing test is never deleted to make the suite green. Fix the code or log a Known Issue.
|
|
- New bug → write the failing test first, then fix.
|
|
- Update the Test Summary table in STATUS.md after each phase.
|