test(client): sprint 18 test suite — dialogue, journal, minimap (#151, #174, #264)

50 tests across two files: 30 dialogue tests (D-062 compliance,
D-063 confrontation beat, D-064 walk-away, BBCode guard, size
constraints) and 20 journal tests (KG parsing, confidence/source/
state enums, scene structure, UIStrings keys, POI list). Test plan
document with manual procedures and sprint completion checklist.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-25 02:30:13 +01:00
co-authored by Claude Opus 4.6
parent 86ff83d927
commit dae16326fe
3 changed files with 1195 additions and 0 deletions
+190
View File
@@ -0,0 +1,190 @@
# Test Plan: Sprint 18 — Touch (Client)
- **Date**: 2026-02-25
- **Sprint**: 18 (Touch)
- **Spec references**: D-013, D-041, D-042, D-049, D-061, D-062, D-063, D-064, D-078
- **Tickets**: #151 (minimap rendering), #174 (dialogue UI hardening + examine result), #264 (knowledge/journal display)
- **QA Engineer**: Hoshe
---
## Summary
Sprint 18 client scope delivers three UI features:
1. **#151** — Minimap overlay rendering POIs from snapshot
2. **#174** — Dialogue UI hardening (D-062/D-063/D-064) + examine result display overlay
3. **#264** — Knowledge/journal panel displaying accumulated KG facts
Automated tests: `client/tests/test_dialogue_sprint18.gd`, `client/tests/test_journal_sprint18.gd`
Manual tests: this document (section §Manual Test Procedures)
---
## #151: Minimap Rendering
### Spec reference
D-013 (diegetic insert/POI system), D-015 (fixed-north, player-centered), D-049 (z-layer 6)
### Automated (unit-testable)
- `GameState.poi_list` accessible via snapshot or `current_snapshot.poi_list`
→ Covered: `test_journal_sprint18.gd::test_gamestate_poi_list_field_exists_or_in_entities`
- `CANVAS_INSERT = 10` sanity check
→ Covered: `test_journal_sprint18.gd::test_canvas_insert_constant_is_10`
### Edge cases
- **Empty POI list**: minimap frame still renders (frame is always present per D-013)
- **POI beyond minimap radius**: renders as directional arrow at border, not dot
- **POI at exactly player position**: dot at center
- **All POI categories**: `NavPoint`, `PersonOfInterest` — distinct colors/shapes
### Manual test procedure
1. Start game with a clean save (no discovered POIs)
2. **Verify**: minimap insert frame is visible, empty, no dots/arrows
3. Move player near a NavPoint POI; trigger discovery
4. **Verify**: colored dot appears on minimap at correct compass position
5. **Verify**: dot color/shape matches expected category visual (see `data/ui-strings.yaml`)
6. Move player so a POI is beyond minimap radius
7. **Verify**: directional arrow appears at minimap border pointing toward POI
8. **Verify**: player dot remains centered; minimap does not rotate or scroll
9. Open dialogue box; **verify**: minimap remains visible (not hidden by dialogue)
### Performance check
- 150×150 map, 15 NPCs, 8+ discovered POIs → minimap renders without visible frame drop
---
## #174: Dialogue UI Hardening + Examine Result Display
### Spec reference
D-061 (box spec), D-062 (invisible locked options), D-063 (confrontation), D-064 (walk-away), D-078 (overheard log)
### Automated coverage
Test file: `client/tests/test_dialogue_sprint18.gd`
| Test | D-ref | Status |
|------|-------|--------|
| D-062: rendered options have mouse_filter=STOP | D-062 | Written |
| D-062: no lock icon children on options | D-062 | Written |
| D-062: MAX_OPTIONS = 3 | D-061 | Written |
| D-062: 4 options → only 3 render | D-061/D-062 | Written |
| D-063: CONFRONTATION_BEAT_DURATION in [1.0, 2.0] | D-063 | Written |
| D-063: CONFRONTATION_DIM_ALPHA < 1.0 | D-063 | Written |
| D-063: confrontation_monologue signal fires | D-063 | Written |
| D-063: standard option does NOT fire beat signal | D-063 | Written |
| D-064: _WALK_AWAY_ACTIONS not empty | D-064 | Written |
| D-064: cardinal directions in walk-away list | D-064 | Written |
| D-064: dialogue_dismissed signal exists | D-064 | Written |
| GameState current_dialogue set from snapshot | D-061 | Written |
| GameState current_dialogue null when absent | D-061 | Written |
| GameState current_examine_result field exists | #174 | Written (test-first) |
| GameState current_examine_result set from snapshot | #174 | Written (test-first) |
| GameState current_examine_result null when absent | #174 | Written (test-first) |
| BBCode escape brackets in server text | — | Written |
| _log_dirty flag optimization | — | Written |
| D-061 max height ratio = 0.2 | D-061 | Written |
| D-064 FADE_OUT = 0.3s | D-064 | Written |
| D-078 passive glyph = ┃ | D-078 | Written |
### Items requiring Stig implementation (test-first stubs will fail until done)
- `GameState.current_examine_result` field + `apply_snapshot()` handler
- Examine result overlay scene (`res://ui/examine_overlay.tscn` or similar)
- Auto-dismiss timer: 46 seconds (wire `current_examine_result` to overlay)
### Manual test procedure — D-062 (invisible locked options)
1. Enter dialogue with an NPC that has some filtered options (server omits locked ones)
2. **Verify**: dialogue box shows only the options the server sent — no grayed-out entries, no lock icons
3. **Verify**: all visible options respond to click/key press
4. **Verify**: pressing 1, 2, 3 selects the corresponding option (key bindings active)
5. **Red flag**: if you see any visual element that appears "disabled" or "locked" — that is a D-062 violation
### Manual test procedure — D-063 (confrontation beat)
1. Enter dialogue with an NPC that has a confrontation option (italic monologue beat)
2. **Verify**: confrontation option renders identically to standard options (same style — no bold, no icon)
3. Select the confrontation option
4. **Verify**: a first-person internal monologue appears (italic, MonologueDisplay)
5. **Verify**: dialogue box dims for ~1.5 seconds during beat
6. **Verify**: after beat, option is sent and conversation ends normally
7. **Verify**: audio dip applies during confrontation beat
### Manual test procedure — Examine result display (#174 new feature)
1. Stand adjacent to an NPC; press Examine key (TBD — coordinate with server team)
2. **Verify**: a brief text overlay appears (non-interactive, no response options)
3. **Verify**: overlay is diegetically styled (insert layer, not a dialogue box)
4. **Verify**: overlay auto-dismisses after 46 seconds without player input
5. **Verify**: different characters (detective vs smuggler) receive different text for the same NPC
6. **Verify**: overlay does not appear over a dialogue box (mutual exclusion)
---
## #264: Knowledge/Journal Display
### Spec reference
D-041 (knowledge graph data model), D-042 (UIStrings), D-013 (insert layer)
### Automated coverage
Test file: `client/tests/test_journal_sprint18.gd`
| Test | D-ref | Status |
|------|-------|--------|
| GameState.player_knowledge field exists | D-041 | Written (test-first) |
| GameState.player_knowledge set from snapshot | D-041 | Written (test-first) |
| GameState.player_knowledge null when absent | D-041 | Written (test-first) |
| Facts array survives snapshot roundtrip | D-041 | Written (test-first) |
| KnowledgeConfidence levels documented | D-041 | Written |
| Fact state values documented | D-041 | Written |
| Journal scene exists at path | #264 | Written (test-first) |
| UIStrings has journal section | D-042 | Written (test-first) |
| CANVAS_INSERT = 10 | D-013 | Written |
| POI list accessible for minimap | #151 | Written |
### Items requiring Stig implementation (test-first stubs will fail until done)
- `GameState.player_knowledge` field + `apply_snapshot()` handler
- Journal panel scene (`res://ui/journal_panel.tscn`)
- Journal panel `refresh()` or `_refresh()` method
- UIStrings keys: `journal.title`, `journal.confidence.*`, `journal.no_facts`
- Toggle key (likely `J`) wired to panel visibility
- Mutual exclusion: journal closes when dialogue opens and vice versa
### Manual test procedure
1. Accumulate KG facts by examining NPCs and participating in dialogue
2. Press the journal toggle key (likely `J`)
3. **Verify**: journal panel opens as an insert-layer overlay (diegetic styling)
4. **Verify**: entities are listed with header ("What I know about Kael Davan")
5. **Verify**: each fact shows: fact text, confidence level, source, game-time timestamp
6. **Verify**: `Direct` confidence facts are most prominent (visually)
7. **Verify**: `Stale` facts appear dimmer than `Active` facts
8. **Verify**: `Contradicted` facts are visually distinct (strikethrough or amber tint)
9. Open dialogue box; **verify**: journal panel closes automatically
10. Close dialogue; re-open journal; **verify**: state preserved
11. Press `J` again; **verify**: journal panel closes
### Edge cases
- **Empty journal**: no facts accumulated → journal shows "No data" message (UIStrings key)
- **Many facts**: 20+ facts → scroll works, panel stays within insert layer bounds
- **Contradicted + Stale**: a fact can be both — verify combined visual treatment
- **Game time 00:00**: timestamp displays correctly (midnight edge case)
---
## Test Coverage Summary
| Ticket | Automated tests | Manual procedure documented | Ready to run |
|--------|----------------|----------------------------|--------------|
| #151 minimap | 2 (structural) | Yes | Blocked on Stig (#151 in_progress) |
| #174 dialogue hardening | 25 | Yes | All pass today (code exists) |
| #174 examine result | 5 (test-first) | Yes | Blocked (GameState field missing) |
| #264 journal display | 8 (test-first) | Yes | Blocked (scene + field missing) |
### Test files to run
```bash
# gdUnit4 headless (see docs/DEVOPS.md for full command)
# test_dialogue_sprint18.gd — expect: 25 pass (dialogue), 5 fail (examine, test-first)
# test_journal_sprint18.gd — expect: 3 pass (constants), 8 fail (test-first)
```
### Sprint 18 completion criteria (client)
Per `sprint-18/joint.md`:
- [ ] Minimap renders POIs — discovered POI shows dot; player centered; at least one distant POI shows arrow
- [ ] Journal panel opens — at least one KG fact with confidence, source, game-time visible
- [ ] Examine result displays — overlay fires on Examine, auto-dismisses, differs by character
- [ ] No locked/grayed dialogue options anywhere in the UI (D-062)