Skip to content

Commit d8d6a69

Browse files
committed
test(lua): cover challenge routes in start endpoint
Extend tests/lua/endpoints/test_start.py with a TestStartChallenge class covering the new challenge branch. No new fixtures: challenges start from MENU like the existing start tests, and the wrong-state case reuses the existing start/state-BLIND_SELECT fixture. fixtures.json is unchanged. - happy_path (parametrized c_omelette_1, c_jokerless_1, c_mad_world_1): lands in BLIND_SELECT with deck=b_challenge, stake=stake_white, and the challenge id echoed in the gamestate. - with_seed: proves challenge composes freely with seed. - effect_applied (deep): The Omelette starts with 5 Eggs — asserts the challenge actually took effect, not just the flag. - conflict_with_deck / _stake / _both: BAD_REQUEST "cannot be combined". - invalid_id: BAD_REQUEST "Expected a c_* challenge id". - wrong_type: schema-level BAD_REQUEST "must be of type string". The existing TestStartEndpoint / validation / state-requirement tests stay green unchanged — they are the regression guard for the normal path (deck/stake are now schema-optional, enforced in execute with the same verbatim error strings).
1 parent aa1e781 commit d8d6a69

1 file changed

Lines changed: 104 additions & 0 deletions

File tree

tests/lua/endpoints/test_start.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,107 @@ def test_start_from_BLIND_SELECT(self, client: httpx.Client):
164164
"INVALID_STATE",
165165
"Method 'start' requires one of these states: MENU",
166166
)
167+
168+
169+
class TestStartChallenge:
170+
"""Tests for the challenge-run branch of the start endpoint.
171+
172+
Challenges are Balatro's 20 fixed-preset runs. The `challenge` param is
173+
mutually exclusive with `deck`/`stake` but composes freely with `seed`.
174+
"""
175+
176+
@pytest.mark.parametrize(
177+
"challenge_id",
178+
[
179+
"c_omelette_1",
180+
"c_jokerless_1",
181+
"c_mad_world_1",
182+
],
183+
)
184+
def test_start_challenge_happy_path(self, client: httpx.Client, challenge_id: str):
185+
"""A challenge run lands in BLIND_SELECT under the b_challenge deck."""
186+
response = api(client, "menu", {})
187+
assert_gamestate_response(response, state="MENU")
188+
response = api(client, "start", {"challenge": challenge_id})
189+
assert_gamestate_response(
190+
response,
191+
state="BLIND_SELECT",
192+
challenge=challenge_id,
193+
deck="b_challenge",
194+
stake="stake_white",
195+
)
196+
197+
def test_start_challenge_with_seed(self, client: httpx.Client):
198+
"""challenge composes freely with seed."""
199+
response = api(client, "menu", {})
200+
assert_gamestate_response(response, state="MENU")
201+
response = api(
202+
client, "start", {"challenge": "c_omelette_1", "seed": "TEST123"}
203+
)
204+
assert_gamestate_response(
205+
response,
206+
state="BLIND_SELECT",
207+
challenge="c_omelette_1",
208+
seed="TEST123",
209+
)
210+
211+
def test_start_challenge_effect_applied(self, client: httpx.Client):
212+
"""Deep check: The Omelette starts with 5 Eggs — proves the challenge
213+
actually took effect, not just the challenge flag."""
214+
response = api(client, "menu", {})
215+
assert_gamestate_response(response, state="MENU")
216+
response = api(client, "start", {"challenge": "c_omelette_1"})
217+
gamestate = assert_gamestate_response(response, state="BLIND_SELECT")
218+
assert gamestate["jokers"]["count"] == 5
219+
assert {c["key"] for c in gamestate["jokers"]["cards"]} == {"j_egg"}
220+
221+
def test_start_challenge_conflict_with_deck(self, client: httpx.Client):
222+
"""challenge cannot be combined with deck."""
223+
response = api(client, "menu", {})
224+
assert_gamestate_response(response, state="MENU")
225+
response = api(
226+
client,
227+
"start",
228+
{"challenge": "c_omelette_1", "deck": "b_red"},
229+
)
230+
assert_error_response(response, "BAD_REQUEST", "cannot be combined")
231+
232+
def test_start_challenge_conflict_with_stake(self, client: httpx.Client):
233+
"""challenge cannot be combined with stake."""
234+
response = api(client, "menu", {})
235+
assert_gamestate_response(response, state="MENU")
236+
response = api(
237+
client,
238+
"start",
239+
{"challenge": "c_omelette_1", "stake": "stake_white"},
240+
)
241+
assert_error_response(response, "BAD_REQUEST", "cannot be combined")
242+
243+
def test_start_challenge_conflict_with_both(self, client: httpx.Client):
244+
"""challenge cannot be combined with deck and stake together."""
245+
response = api(client, "menu", {})
246+
assert_gamestate_response(response, state="MENU")
247+
response = api(
248+
client,
249+
"start",
250+
{
251+
"challenge": "c_omelette_1",
252+
"deck": "b_red",
253+
"stake": "stake_white",
254+
},
255+
)
256+
assert_error_response(response, "BAD_REQUEST", "cannot be combined")
257+
258+
def test_start_challenge_invalid_id(self, client: httpx.Client):
259+
"""An unknown challenge id is rejected against live G.CHALLENGES."""
260+
response = api(client, "menu", {})
261+
assert_gamestate_response(response, state="MENU")
262+
response = api(client, "start", {"challenge": "c_nope_1"})
263+
assert_error_response(response, "BAD_REQUEST", "Expected a c_* challenge id")
264+
265+
def test_start_challenge_wrong_type(self, client: httpx.Client):
266+
"""challenge must be a string (schema-level type check)."""
267+
response = api(client, "menu", {})
268+
assert_gamestate_response(response, state="MENU")
269+
response = api(client, "start", {"challenge": 123})
270+
assert_error_response(response, "BAD_REQUEST", "must be of type string")

0 commit comments

Comments
 (0)