"""Tests for automaton.dashboard.core.task.""" from pathlib import Path import pytest from automaton.dashboard.core.task import ( determine_task_state, discover_tasks, parse_sub_tasks, TaskState, ) def _make_task(tmp_path: Path, name: str, artifacts: dict[str, str]) -> Path: """Create a task folder with the given artifact contents.""" task_dir = tmp_path / name task_dir.mkdir(parents=True) for filename, content in artifacts.items(): (task_dir / filename).write_text(content) return task_dir def test_backlog_state(tmp_path: Path) -> None: task_dir = _make_task(tmp_path, "backlog-task", {}) state, artifacts = determine_task_state(task_dir) assert state == TaskState.BACKLOG assert not artifacts def test_research_state(tmp_path: Path) -> None: task_dir = _make_task(tmp_path, "research-task", {"SPEC.md": "# Spec"}) state, artifacts = determine_task_state(task_dir) assert state == TaskState.RESEARCH assert "SPEC.md" in artifacts def test_implementation_state(tmp_path: Path) -> None: task_dir = _make_task( tmp_path, "impl-task", {"SPEC.md": "# Spec", "IMPLEMENTATION.md": "# Impl"}, ) state, _ = determine_task_state(task_dir) assert state == TaskState.IMPLEMENT def test_bug_find_state(tmp_path: Path) -> None: task_dir = _make_task( tmp_path, "bug-task", {"SPEC.md": "# Spec", "IMPLEMENTATION.md": "# Impl", "BUG_REPORT.md": "# Bugs"}, ) state, _ = determine_task_state(task_dir) assert state == TaskState.BUG_FIND def test_adv_bug_find_state(tmp_path: Path) -> None: task_dir = _make_task( tmp_path, "adv-task", { "SPEC.md": "# Spec", "IMPLEMENTATION.md": "# Impl", "BUG_REPORT.md": "# Bugs", "ADVERSARIAL_BUG_REPORT.md": "# Adv", }, ) state, _ = determine_task_state(task_dir) assert state == TaskState.ADV_BUG_FIND def test_done_state(tmp_path: Path) -> None: task_dir = _make_task( tmp_path, "done-task", {"SPEC.md": "# Spec", "VERDICT.md": "## Status: PASS"}, ) state, _ = determine_task_state(task_dir) assert state == TaskState.DONE def test_blocked_state(tmp_path: Path) -> None: task_dir = _make_task( tmp_path, "blocked-task", {"SPEC.md": "# Spec", "VERDICT.md": "## Status: FAIL"}, ) state, _ = determine_task_state(task_dir) assert state == TaskState.BLOCKED def test_empty_verdict_is_blocked(tmp_path: Path) -> None: task_dir = _make_task(tmp_path, "empty-verdict", {"VERDICT.md": ""}) state, _ = determine_task_state(task_dir) assert state == TaskState.BLOCKED def test_parse_sub_tasks(tmp_path: Path) -> None: parent = tmp_path / "parent" parent.mkdir() sub = parent / "subtasks" / "sub-a" sub.mkdir(parents=True) (sub / "SPEC.md").write_text("# Spec") (sub / "VERDICT.md").write_text("## Status: PASS") sub_tasks = parse_sub_tasks(parent) assert len(sub_tasks) == 1 assert sub_tasks[0].name == "sub-a" assert sub_tasks[0].has_verdict is True assert sub_tasks[0].verdict_status == "PASS" def test_discover_tasks(tmp_path: Path) -> None: _make_task(tmp_path, "aaa", {"SPEC.md": "# Spec"}) _make_task(tmp_path, "zzz", {"VERDICT.md": "## Status: PASS"}) tasks = discover_tasks(tmp_path) assert len(tasks) == 2 # Done task should be first (sorted by advancement). assert tasks[0].state == TaskState.DONE assert tasks[1].state == TaskState.RESEARCH def test_discover_tasks_skips_subtasks_root(tmp_path: Path) -> None: parent = tmp_path / "parent" parent.mkdir() (parent / "SPEC.md").write_text("# Spec") (parent / "subtasks" / "sub-a").mkdir(parents=True) (parent / "subtasks" / "sub-a" / "SPEC.md").write_text("# Sub") tasks = discover_tasks(tmp_path) assert len(tasks) == 1 assert tasks[0].name == "parent" assert len(tasks[0].sub_tasks) == 1