from pathlib import Path import pytest from dojo.cli import EXIT_DESIGN_ERRORS, EXIT_FORMAT_ERRORS, EXIT_OK, main from dojo.grid import parse_grid VALID = Path(__file__).parent / "fixtures" / "quadrant_valid.txt" def test_validate_valid_board(capsys: pytest.CaptureFixture[str]) -> None: assert main(["board", "validate", "--quadrant", str(VALID)]) == EXIT_OK output = capsys.readouterr().out assert "Shortest walk Safe Room -> Dojo: Q0 10, Q1 10, Q2 10, Q3 10" in output assert output.rstrip().endswith("OK") def test_validate_reports_design_errors(tmp_path: Path, capsys: pytest.CaptureFixture[str]) -> None: no_entrance = VALID.read_text(encoding="utf-8").replace( "+ + + + + + +---+ +", "+ + + + + + +---+---+" ) quadrant = tmp_path / "quadrant.txt" quadrant.write_text(no_entrance, encoding="utf-8") assert main(["board", "validate", "--quadrant", str(quadrant)]) == EXIT_DESIGN_ERRORS assert "quadrant 0 has no Dojo entrance" in capsys.readouterr().out def test_format_errors_and_missing_files_exit_with_format_code( tmp_path: Path, capsys: pytest.CaptureFixture[str] ) -> None: malformed = tmp_path / "bad.txt" malformed.write_text("+---+\n| . |\n", encoding="utf-8") assert main(["board", "validate", "--quadrant", str(malformed)]) == EXIT_FORMAT_ERRORS assert main(["board", "validate", "--quadrant", str(tmp_path / "none")]) == EXIT_FORMAT_ERRORS assert "odd number of lines" in capsys.readouterr().err def test_render_writes_a_parseable_full_board(tmp_path: Path) -> None: output = tmp_path / "board.txt" assert main(["board", "render", "--quadrant", str(VALID), "-o", str(output)]) == EXIT_OK grid = parse_grid(output.read_text(encoding="utf-8")) assert (grid.height, grid.width) == (16, 16) def test_legend_next_to_the_quadrant_is_used_by_default( tmp_path: Path, capsys: pytest.CaptureFixture[str] ) -> None: quadrant = tmp_path / "quadrant.txt" quadrant.write_text(VALID.read_text(encoding="utf-8"), encoding="utf-8") (tmp_path / "legend.toml").write_text("[tunnels.9]\nquadrant_offset = 1\n", encoding="utf-8") assert main(["board", "validate", "--quadrant", str(quadrant)]) == EXIT_FORMAT_ERRORS assert "legend links tunnel '9'" in capsys.readouterr().err def test_sim_prints_a_summary_per_scenario_and_writes_games( tmp_path: Path, capsys: pytest.CaptureFixture[str] ) -> None: games = tmp_path / "games.csv" argv = ["sim", "--games", "2", "--variant", "A", "B", "--players", "3", "--jobs", "1"] assert main([*argv, "--csv", str(games)]) == EXIT_OK output = capsys.readouterr().out assert "== A p3 kiai+2 start0 balanced,farmer,aggressive (2 games" in output assert "== B p3 kiai+2 start0" in output rows = games.read_text(encoding="utf-8").splitlines() assert rows[0].startswith("scenario,seed,lineup,winner_seat") assert len(rows) == 1 + 4 @pytest.mark.parametrize("bad", [["--lineup", "balanced,cheater"], ["--games", "0"]]) def test_sim_rejects_bad_arguments(bad: list[str], capsys: pytest.CaptureFixture[str]) -> None: with pytest.raises(SystemExit) as exit_info: main(["sim", *bad]) assert exit_info.value.code == 2 assert "error:" in capsys.readouterr().err