| """State is the source of truth; the struct must survive a dump/validate round-trip and |
| render into the .md views. (Parsing .md back is intentionally not implemented.)""" |
|
|
| from __future__ import annotations |
|
|
| from visualnovel import state |
| from visualnovel.schemas import Character, GameState, Scene |
|
|
|
|
| def _sample() -> GameState: |
| return GameState( |
| seed=7, |
| vibe="cozy · Fantasy forest", |
| style_guide="anime, soft cel shading", |
| scene=Scene( |
| id="threshold", |
| place="The Threshold", |
| description="edge of the wood", |
| mood="cozy", |
| present=["moth"], |
| ), |
| characters={ |
| "moth": Character( |
| id="moth", |
| name="Mothlight", |
| one_line="a nervous lantern-moth", |
| appearance="amber wings", |
| ), |
| }, |
| ) |
|
|
|
|
| def test_state_struct_roundtrip(): |
| s = _sample() |
| again = GameState.model_validate(s.model_dump()) |
| assert again == s |
| assert again.characters["moth"].name == "Mothlight" |
|
|
|
|
| def test_render_world_md_contains_scene(): |
| s = _sample() |
| md = state.render_world_md(s) |
| assert "The Threshold" in md |
| assert "Mothlight" in md |
| assert "{{" not in md |
|
|
|
|
| def test_render_character_md(): |
| s = _sample() |
| md = state.render_character_md(s, s.characters["moth"]) |
| assert "Mothlight" in md and "amber wings" in md |
| assert "{{" not in md |
|
|