Spaces:
Sleeping
Sleeping
File size: 5,169 Bytes
a8afc36 39c3669 a8afc36 39c3669 a8afc36 39c3669 a8afc36 39c3669 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | import forge
from app import (
CSS,
background_selector_html,
refresh_screen,
school_asset_name,
school_selector_html,
show_background,
show_draft_from_rules,
show_name,
show_school,
start_rules,
)
from ui import new_run_shell
class AppPackClient:
# Return one deterministic draft pack for app-flow tests.
def __init__(self) -> None:
self.calls = 0
# Return a three-card model payload.
def create_pack(self, payload):
self.calls += 1
card = lambda index: {
"name": f"Flow Card {self.calls}-{index}",
"flavor": "The table waits.",
"art_prompt": "glowing spell on a wooden desk",
"effects": [{"primitive_id": "deal", "weight": 1}],
}
return {"cards": [card(index) for index in range(payload["pack_size"])]}
class AppArtClient:
# Count image requests made after card text is forged.
def __init__(self) -> None:
self.calls = 0
# Return a deterministic image URI.
def create_art(self, prompt: str) -> str:
self.calls += 1
return f"uri:{prompt}"
# Verify setup advances through one prompt per screen.
def test_setup_screen_steps() -> None:
assert show_name()[1] == "name"
assert show_background()[1] == "background"
assert show_school()[1] == "school"
# Verify the title CTA stays compact instead of full-width.
def test_play_now_button_is_compact() -> None:
assert "#play-now-btn" in CSS
assert "max-width: 220px" in CSS
assert "#start-draft-btn" in CSS
assert "max-width: 200px" in CSS
# Verify draft cards are compact enough for the draft table.
def test_draft_cards_are_compact() -> None:
assert "minmax(0, 300px)" in CSS
assert "min-height: 405px" in CSS
# Verify setup selectors are image-backed clickable panels with hover copy.
def test_setup_selectors_use_image_panels() -> None:
background = background_selector_html()
school = school_selector_html()
assert "selector-panel" in background
assert "selector-image" in background
assert "selector-copy" in background
assert "background-btn-dark-fantasy" in background
assert "You are a mage" in background
assert "school-btn-fire" in school
assert "school-btn-ice" in school
assert "school-btn-earth" in school
# Verify selector art resolves to the bundled user-provided filenames.
def test_setup_selectors_use_bundled_assets() -> None:
background = background_selector_html()
assert "data:image/png;base64" in background
assert school_asset_name("dark-fantasy", "fire") == "darkFantasyFire.png"
assert school_asset_name("dark-fantasy", "ice") == "darkFantasyIce.png"
assert school_asset_name("dark-fantasy", "earth") == "darkFantasyEarth.png"
assert school_asset_name("cyberpunk", "fire") == "cyberpunkFire.png"
assert school_asset_name("cyberpunk", "ice") == "cyberpunkice.png"
assert school_asset_name("cyberpunk", "earth") == "cyberpunkEarth.png"
assert school_asset_name("anime", "fire") == "animeFire.png"
assert school_asset_name("anime", "ice") == "animeIce.png"
assert school_asset_name("anime", "earth") == "animeEarth.png"
assert "data:image/png;base64" in school_selector_html("Cyberpunk")
# Verify the rules screen starts deck generation in the background.
def test_start_rules_queues_deck_generation(monkeypatch) -> None:
forge.reset()
client = AppPackClient()
monkeypatch.setattr("app.card_client_from_env", lambda: client)
monkeypatch.setattr("app.art_client_from_env", lambda: None)
output = start_rules("Ada", "ice", "Anime")
state = output[0]
# start_rules now lands on the boss reveal screen (rules follow on Continue).
assert output[1] == "reveal"
assert state.player_name == "Ada"
assert state.school == "ice"
assert "reveal-screen" in output[10]
assert "The Necrolich" in output[10]
forge.drain()
refresh_screen(state, "rules")
assert client.calls > 0
# Verify the rules screen starts image work once card text is ready.
def test_rules_screen_starts_art_generation(monkeypatch) -> None:
monkeypatch.setattr("ui.MIN_DRAFT_LOADING_SECONDS", 0.0)
forge.reset()
client = AppPackClient()
art_client = AppArtClient()
monkeypatch.setattr("app.card_client_from_env", lambda: client)
monkeypatch.setattr("app.art_client_from_env", lambda: art_client)
state = start_rules("Ada", "fire", "Cyberpunk")[0]
forge.drain()
state = refresh_screen(state, "rules")[0]
forge.drain()
refresh_screen(state, "rules")
assert art_client.calls >= 3
# Verify skipping rules shows a deck-loading draft state if the pack is still pending.
def test_skip_rules_shows_loading_deck(monkeypatch) -> None:
forge.reset()
monkeypatch.setattr("app.card_client_from_env", lambda: None)
monkeypatch.setattr("app.art_client_from_env", lambda: None)
state = new_run_shell("Ada", "Anime", "fire", seed=1)
output = show_draft_from_rules(state)
assert output[1] == "draft"
assert output[0].loading == "Loading your deck"
assert "Loading your deck" in output[12]
|