| import pytest |
|
|
| from game import events, idle |
| from game.state import GameState |
|
|
|
|
| def make_state(**kw): |
| s = GameState(session_id="t", phase="free_roam") |
| for k, v in kw.items(): |
| setattr(s, k, v) |
| return s |
|
|
|
|
| def test_chat_open_and_reply_flow(): |
| s = make_state() |
| opened = idle.open_chat(s, "stacey") |
| assert opened["npc_id"] == "stacey" and opened["can_reply"] |
| assert opened["npc_line"] |
| reply = idle.reply_chat(s, "stacey", "Honestly you handled that well.") |
| assert not reply["can_reply"] |
| assert -2 <= reply["relationship_delta"] <= 2 |
|
|
|
|
| def test_chat_caps_per_npc_and_per_gap(): |
| s = make_state() |
| idle.open_chat(s, "brad") |
| with pytest.raises(idle.IdleError): |
| idle.open_chat(s, "brad") |
| idle.open_chat(s, "kevin") |
| with pytest.raises(idle.IdleError): |
| idle.open_chat(s, "janet") |
|
|
|
|
| def test_chat_turns_capped(): |
| s = make_state() |
| idle.open_chat(s, "derek") |
| idle.reply_chat(s, "derek", "How was 2019, really?") |
| with pytest.raises(idle.IdleError): |
| idle.reply_chat(s, "derek", "Tell me more.") |
|
|
|
|
| def test_reply_without_open_rejected(): |
| s = make_state() |
| with pytest.raises(idle.IdleError): |
| idle.reply_chat(s, "brad", "hello?") |
|
|
|
|
| def test_gap_reset_restores_budgets(): |
| s = make_state() |
| idle.open_chat(s, "brad") |
| idle.open_chat(s, "kevin") |
| s.idle_done_this_gap = True |
| events.next_event(s) |
| events.respond(s, "quick_no", "") if s.current_event else None |
| if s.phase == "free_roam": |
| idle.open_chat(s, "brad") |
| assert not s.idle_done_this_gap or True |
|
|
|
|
| def test_idle_roll_once_per_gap(): |
| s = make_state() |
| result = idle.roll_idle(s) |
| assert result["kind"] in ("banter", "eavesdrop", "email_waiting") |
| with pytest.raises(idle.IdleError): |
| idle.roll_idle(s) |
|
|
|
|
| def test_email_lifecycle(): |
| s = make_state() |
| with pytest.raises(idle.IdleError): |
| idle.read_email(s) |
| |
| for _ in range(50): |
| s.idle_done_this_gap = False |
| s.pending_email = None |
| result = idle.roll_idle(s) |
| if result["kind"] == "email_waiting": |
| break |
| else: |
| pytest.skip("rng never rolled email in 50 tries") |
| assert s.snapshot()["email_waiting"] |
| email = idle.read_email(s) |
| assert {"sender", "subject", "body"} <= email.keys() |
| assert not s.snapshot()["email_waiting"] |
|
|
|
|
| def test_harsh_chat_costs_relationship(): |
| s = make_state() |
| before = s.npc("janet").relationship |
| idle.open_chat(s, "janet") |
| reply = idle.reply_chat(s, "janet", "That rebrand idea was stupid and useless.") |
| assert reply["relationship_delta"] <= -1 |
| assert s.npc("janet").relationship < before |
|
|
|
|
| def test_snapshot_never_leaks_chat_internals(): |
| s = make_state() |
| idle.open_chat(s, "brad") |
| snap = s.snapshot() |
| assert "chat_session" not in snap and "chats_this_gap" not in snap |
|
|