blind-quill / tests /test_app_flow.py
JacobLinCool's picture
feat: allow warned manuscript reading
4cc2649
Raw
History Blame Contribute Delete
6.38 kB
import os
import tempfile
import unittest
import core
import story_store
from presenter import card_dict, full_story_dict, reveal_dict
from schemas import (
CharacterFact,
FragmentInterpretation,
GraftPatch,
GraftPlan,
InitialChapterPayload,
InitialStoryPayload,
PublicCapsule,
PublicCapsulePatch,
VisibleCharacter,
WorldBible,
WorldBiblePatch,
)
def initial_payload():
return InitialStoryPayload(
public_capsule=PublicCapsule(
title="The Late Glass",
genre="coastal fantasy",
tone="wistful and uncanny",
short_summary="A keeper tends a shore where storms return lost memories.",
visible_characters=[VisibleCharacter(name="Mara", one_line_description="A lighthouse keeper.")],
open_questions=["What does the storm remember?"],
),
world_bible=WorldBible(
premise="Storms return memories as objects.",
rules=["Returned memories become shore objects."],
characters=[CharacterFact(name="Mara", facts=["She keeps the lighthouse."])],
locations=["Lighthouse"],
motifs=["salt"],
open_threads=["What does the storm remember?"],
),
chapters=[
InitialChapterPayload(title="Salt Clock", summary="Mara finds a clock.", paragraphs=["A", "B", "C", "D"]),
InitialChapterPayload(title="Lantern Room", summary="Mara hides a shard.", paragraphs=["E", "F", "G", "H"]),
InitialChapterPayload(title="Low Tide", summary="Names return.", paragraphs=["I", "J", "K", "L"]),
],
)
def graft_plan():
return GraftPlan(
target_chapter_id="ch02",
target_paragraph_ids=["ch02_p0002"],
insertion_mode="replace",
player_safe_rationale="It belongs where the shard is hidden.",
continuity_risks=[],
required_preservations=[],
fragment_interpretation=FragmentInterpretation(kind="object", summary="Blue glass reflects one day late."),
)
def graft_patch():
return GraftPatch(
target_chapter_id="ch02",
target_paragraph_ids=["ch02_p0002"],
insertion_mode="replace",
replacement_paragraphs=["Mara hid the blue shard under the lamp oil, where reflections arrived one day late."],
public_reveal="Your fragment was stitched into Chapter 2, beneath the lamp oil.",
editor_rationale_for_player="The shard sharpens the lighthouse's strange rules.",
updated_chapter_summary="Mara hides a late-reflecting shard.",
public_capsule_patch=PublicCapsulePatch(
short_summary="A keeper tends a shore where storms return memories and blue glass lies.",
visible_characters=[VisibleCharacter(name="Mara", one_line_description="A lighthouse keeper avoiding blue glass.")],
open_questions=["Why does blue glass lag behind the day?"],
),
world_bible_patch=WorldBiblePatch(
rules_to_add=["Blue glass reflects one day late."],
character_facts_to_add=[CharacterFact(name="Mara", facts=["She avoids blue glass."])],
locations_to_add=[],
motifs_to_add=["blue glass"],
open_threads_to_add=["Why does blue glass lag behind the day?"],
open_threads_to_resolve=[],
),
)
class AppFlowTests(unittest.TestCase):
def test_create_blinds_capsule_then_stitch_reveals_full_story(self):
original_data_dir = os.environ.get("DATA_DIR")
original_store_generate = story_store.generate_json
original_core_generate = core.generate_json
try:
with tempfile.TemporaryDirectory() as directory:
os.environ["DATA_DIR"] = directory
story_store.generate_json = lambda *args, **kwargs: initial_payload()
story = core.create("A lighthouse seed.")
story_id = story.story_id
# Gallery + capsule are blinded: the public capsule shows, chapters never leak.
card = card_dict(story)
self.assertEqual(card["capsule"]["title"], "The Late Glass")
self.assertNotIn("chapters", card)
self.assertTrue(any(item.story_id == story_id for item in core.gallery()))
self.assertNotIn("chapters", card_dict(core.capsule(story_id)))
# The escape door can reveal an open manuscript without adding a graft.
unmodified_full = full_story_dict(core.read_manuscript(story_id))
self.assertIn("chapters", unmodified_full)
self.assertEqual(unmodified_full["graftCount"], 0)
def fake_core_generate(*args, **kwargs):
schema_model = args[1]
if schema_model is GraftPlan:
return graft_plan()
if schema_model is GraftPatch:
return graft_patch()
raise AssertionError(f"Unexpected schema: {schema_model}")
core.generate_json = fake_core_generate
result = core.stitch(story_id, "Blue glass reflects one day late.")
full = full_story_dict(result.story)
reveal = reveal_dict(result)
# The stitch unseals the full manuscript and highlights the new passage.
self.assertIn("chapters", full)
self.assertEqual(full["graftCount"], 1)
self.assertTrue(reveal["highlightIds"])
highlighted = reveal["highlightIds"][0]
paragraph_ids = [p["id"] for chapter in full["chapters"] for p in chapter["paragraphs"]]
self.assertIn(highlighted, paragraph_ids)
self.assertIn("Chapter 2", reveal["revealLine"])
self.assertEqual(reveal["targetLabel"], "Chapter II · Lantern Room")
# The graft is persisted.
self.assertEqual(core.capsule(story_id).graft_count, 1)
finally:
story_store.generate_json = original_store_generate
core.generate_json = original_core_generate
if original_data_dir is None:
os.environ.pop("DATA_DIR", None)
else:
os.environ["DATA_DIR"] = original_data_dir
if __name__ == "__main__":
unittest.main()