"""Tests for clickup_runner.skill_map.""" import pytest from clickup_runner.skill_map import ( SKILL_MAP, SkillRoute, get_route, get_supported_task_types, get_valid_stages, ) class TestGetRoute: def test_content_creation_run_cora(self): route = get_route("Content Creation", "run_cora") assert route is not None assert route.handler == "autocora" assert route.next_stage == "outline" assert route.next_status == "review" def test_content_creation_outline(self): route = get_route("Content Creation", "outline") assert route is not None assert route.handler == "claude" assert route.skill_file == "content_outline.md" assert route.next_stage == "draft" def test_content_creation_draft(self): route = get_route("Content Creation", "draft") assert route is not None assert route.next_stage == "final" assert route.max_turns == 30 def test_on_page_optimization_has_hidden_div(self): route = get_route("On Page Optimization", "hidden div") assert route is not None assert route.skill_file == "content_hidden_div.md" assert route.next_stage == "final" def test_on_page_draft_goes_to_hidden_div(self): route = get_route("On Page Optimization", "draft") assert route is not None assert route.next_stage == "hidden div" def test_press_release_single_stage(self): route = get_route("Press Release", "draft") assert route is not None assert route.skill_file == "press_release_prompt.md" assert route.next_stage == "final" assert route.next_status == "review" def test_press_release_no_run_cora(self): """Press releases don't need Cora.""" route = get_route("Press Release", "run_cora") assert route is None def test_link_building_run_cora(self): route = get_route("Link Building", "run_cora") assert route is not None assert route.handler == "autocora" assert route.next_stage == "build" def test_link_building_build(self): route = get_route("Link Building", "build") assert route is not None assert route.handler == "claude" assert route.skill_file == "linkbuilding.md" def test_unknown_task_type_returns_none(self): assert get_route("Banana Farming", "draft") is None def test_unknown_stage_returns_none(self): assert get_route("Content Creation", "nonexistent") is None def test_stage_is_case_insensitive(self): route = get_route("Content Creation", "RUN_CORA") assert route is not None assert route.handler == "autocora" def test_stage_strips_whitespace(self): route = get_route("Content Creation", " outline ") assert route is not None assert route.handler == "claude" class TestGetValidStages: def test_content_creation(self): stages = get_valid_stages("Content Creation") assert stages == ["run_cora", "outline", "draft"] def test_on_page_optimization(self): stages = get_valid_stages("On Page Optimization") assert "hidden div" in stages assert len(stages) == 4 def test_press_release(self): stages = get_valid_stages("Press Release") assert stages == ["draft"] def test_link_building(self): stages = get_valid_stages("Link Building") assert stages == ["run_cora", "build"] def test_unknown_type(self): assert get_valid_stages("Nope") == [] class TestGetSupportedTaskTypes: def test_returns_all_four(self): types = get_supported_task_types() assert "Content Creation" in types assert "On Page Optimization" in types assert "Press Release" in types assert "Link Building" in types assert len(types) == 4 class TestSkillRouteDataclass: def test_defaults(self): route = SkillRoute(next_stage="x", next_status="y") assert route.handler == "claude" assert route.skill_file == "" assert route.tools == "" assert route.max_turns == 10 def test_frozen(self): route = SkillRoute(next_stage="x", next_status="y") with pytest.raises(AttributeError): route.next_stage = "z" # type: ignore[misc] class TestAllRoutesHaveRequiredFields: """Every route in the map should be well-formed.""" @pytest.mark.parametrize( "task_type,stage", [ (tt, s) for tt, stages in SKILL_MAP.items() for s in stages ], ) def test_route_has_required_fields(self, task_type, stage): route = get_route(task_type, stage) assert route is not None assert route.next_stage, f"{task_type}/{stage} missing next_stage" assert route.next_status, f"{task_type}/{stage} missing next_status" if route.handler == "claude": assert route.skill_file, f"{task_type}/{stage} missing skill_file" assert route.tools, f"{task_type}/{stage} missing tools"