"""Tests for the text environment interface.""" import json from pathlib import Path import pytest from turnabout.envs.text_env import TextCourtEnv CASES_DIR = Path(__file__).parent.parent / "turnabout" / "cases" @pytest.fixture def case_path(): p = CASES_DIR / "stolen_prototype.json" if not p.exists(): pytest.skip("stolen_prototype.json not yet created") return str(p) class TestTextEnvEasy: def test_reset(self, case_path): env = TextCourtEnv(case_path=case_path, difficulty="easy") obs = env.reset() assert "COURT" in obs or "TESTIMONY" in obs def test_system_prompt(self, case_path): env = TextCourtEnv(case_path=case_path, difficulty="easy") prompt = env.system_prompt assert "defense attorney" in prompt assert "press" in prompt def test_step_returns_4_tuple(self, case_path): env = TextCourtEnv(case_path=case_path, difficulty="easy") env.reset() obs, reward, done, info = env.step("next") assert isinstance(obs, str) assert isinstance(reward, float) assert isinstance(done, bool) assert isinstance(info, dict) assert "valid_actions" in info def test_invalid_action(self, case_path): env = TextCourtEnv(case_path=case_path, difficulty="easy") env.reset() obs, reward, done, info = env.step("fly to the moon") assert "parse" in info.get("parse_error", "").lower() or "parse_error" in info assert reward < 0 def test_full_easy_win(self, case_path): env = TextCourtEnv(case_path=case_path, difficulty="easy") env.reset() actions = [ "next", "present patrol_schedule", "next", "next", "press revised_2", "next", "present cloning_device", "next", "present alex_alibi", ] done = False for action in actions: obs, reward, done, info = env.step(action) if done: break assert done assert "NOT GUILTY" in obs metrics = env.get_metrics() assert metrics.won assert metrics.contradiction_accuracy == 1.0 def test_max_steps(self, case_path): env = TextCourtEnv(case_path=case_path, difficulty="easy", max_steps=3) env.reset() for _ in range(5): obs, reward, done, info = env.step("next") if done: break assert done class TestTextEnvHard: def test_reset_investigation(self, case_path): env = TextCourtEnv(case_path=case_path, difficulty="hard") obs = env.reset() assert "INVESTIGATION" in obs def test_investigate_then_court(self, case_path): env = TextCourtEnv(case_path=case_path, difficulty="hard") env.reset() investigation_actions = [ "talk alex_park", "move lab", "move security_office", "examine filing_cabinet", "examine monitor_desk", "move lab", "present security_footage to chen", "move main_hallway", "move hale_office", "examine hale_desk", "go to court", ] for action in investigation_actions: obs, reward, done, info = env.step(action) assert not done, f"Game ended unexpectedly after '{action}': {obs}" assert "COURT" in obs court_actions = [ "next", "present patrol_schedule", "next", "next", "press revised_2", "next", "present cloning_device", "next", "present alex_alibi", ] for action in court_actions: obs, reward, done, info = env.step(action) if done: break assert done assert "NOT GUILTY" in obs