Files
settled-reach/tests/visual.json
T
jpmschweitzerandClaude Opus 4.6 6bcdc48412 feat(client): add visual test harness with golden regression
Gives Claude eyes: `make screenshot` captures a rendered frame,
`make test-visual` compares against golden PNGs, `make visual-update`
regenerates goldens. Built to debug the Sprint 22 fog regression and
prevent future visual regressions across fog, HUD, dialogue, and UI.

Config-driven via tests/visual.json (11 scenarios, 2 flows).
Capture engine boots main.tscn with real GPU rendering (not --headless),
waits for NoiseTexture2D async gen, uses deterministic shader time.

Components:
- visual_capture.gd: SceneTree capture engine (scenario + movie modes)
- visual_scenarios.gd: per-scenario setup hooks
- tooling/visual-diff: pixel comparator (PIL primary, struct fallback)
- tooling/visual-thumbnail: contact sheet + crop tool
- tests/run-visual: suite script (xvfb wrapping, golden workflow)
- fog_state.gd: override_time for deterministic captures
- fog_shader.gd: fog_noise_ready signal for settle sequencing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 16:33:55 +01:00

86 lines
2.4 KiB
JSON

{
"resolution": [960, 540],
"settle_frames": 30,
"tolerance": 5,
"golden_dir": "client/tests/golden/visual",
"scenarios": {
"fog_3state": {
"ticks": 5,
"description": "All 3 fog states — clear/explored/unexplored"
},
"fog_diagonal": {
"ticks": 10,
"description": "Diagonal LOS boundary (staircase regression target)"
},
"fog_boundary": {
"ticks": 8,
"description": "Explored/unexplored transition centered in frame"
},
"fog_zone_tint": {
"ticks": 5,
"description": "Bar zone warm amber tint in explored fog (D-046)"
},
"fog_debug": {
"ticks": 5,
"description": "Raw exploration overlay (green/blue/red)"
},
"npc_in_fog": {
"ticks": 5,
"description": "NPC sprite visible above fog overlay (D-033)"
},
"hud_default": {
"ticks": 1,
"description": "Full HUD: time, Careful stance (green), minimap, monologue"
},
"dialogue_open": {
"ticks": 3,
"description": "Dialogue box + interaction prompt + key bar positioning"
},
"dialogue_with_monologue": {
"ticks": 4,
"description": "Confrontation beat: dialogue + monologue simultaneously"
},
"minimap_stance": {
"ticks": 2,
"description": "Minimap + Sprint stance indicator overlap (top-right)"
},
"cursor_menu": {
"ticks": 3,
"description": "Cursor rendering over dialogue option"
}
},
"flows": {
"flow_dialogue": {
"interval": 3,
"steps": [
{ "action": "MoveSouth", "label": "approaching NPC" },
{ "action": "Interact", "label": "dialogue opens" },
{ "action": "wait", "label": "reading options" },
{ "action": "select_option_1", "label": "option selected" },
{ "action": "wait", "label": "NPC response" },
{ "action": "MoveNorth", "label": "walking away" }
]
},
"flow_explore": {
"interval": 3,
"steps": [
{ "action": "MoveNorth", "label": "moving north" },
{ "action": "MoveNorth", "label": "fog revealing" },
{ "action": "MoveNorth", "label": "near wall" },
{ "action": "MoveSouth", "label": "fog hiding" }
]
}
},
"crops": {
"top-right": [760, 0, 200, 200],
"top-left": [0, 0, 250, 150],
"bottom": [0, 340, 960, 200],
"full": [0, 0, 960, 540]
},
"thumbnail": {
"width": 240,
"height": 135,
"columns": 4
}
}