# pyright: reportRedeclaration=false """Step definitions for skill CLI uncovered-lines coverage.""" from __future__ import annotations from unittest.mock import patch from behave import given, then, when from typer.testing import CliRunner from cleveragents.cli.commands.skill import ( _get_skill_service, _reset_skill_service, ) from cleveragents.cli.commands.skill import ( app as skill_app, ) from cleveragents.domain.models.core.skill import ( Skill, SkillAgentSource, SkillInclude, SkillMcpSource, ) # ── helpers ───────────────────────────────────────────────── def _make_skill( name: str, description: str = "test skill", tool_refs: list[str] | None = None, includes: list[SkillInclude] | None = None, mcp_servers: list[SkillMcpSource] | None = None, agent_skills: list[SkillAgentSource] | None = None, ) -> Skill: return Skill( name=name, description=description, tool_refs=tool_refs or [], includes=includes or [], mcp_servers=mcp_servers or [], agent_skills=agent_skills or [], ) # ── Given ─────────────────────────────────────────────────── @given("a clean skill service") def step_clean_skill_service(context): _reset_skill_service() context.runner = CliRunner() context.service = _get_skill_service() @given("a skill with an include pointing to a non-registered skill") def step_skill_with_unregistered_include(context): skill = _make_skill( name="local/inc-parent", includes=[SkillInclude(name="local/missing-child")], ) context.service._skills[skill.name] = skill context.skill_name = skill.name @given("a registered skill for capability error testing") def step_skill_for_capability_error(context): skill = _make_skill( name="local/cap-error", tool_refs=["builtin/read-file"], ) context.service._skills[skill.name] = skill context.skill_name = skill.name @given("a registered skill for dependent actors testing") def step_skill_for_dependent_actors(context): skill = _make_skill( name="local/dep-actors", tool_refs=["builtin/write-file"], ) context.service._skills[skill.name] = skill context.skill_name = skill.name @given("a registered skill with agent_skill sources") def step_skill_with_agent_skills(context): skill = _make_skill( name="local/with-agents", agent_skills=[SkillAgentSource(path="./skills/my-agent")], ) context.service._skills[skill.name] = skill context.skill_name = skill.name @given("a registered skill for removal with actor dependents") def step_skill_for_removal_actors(context): skill = _make_skill( name="local/removable-actors", tool_refs=["builtin/exec"], ) context.service._skills[skill.name] = skill context.skill_name = skill.name # ── When ──────────────────────────────────────────────────── @when("I run skill show for the skill with unregistered include") def step_run_show_unregistered_include(context): context.result = context.runner.invoke(skill_app, ["show", context.skill_name]) @when("I run skill show with capability summary raising ValueError") def step_run_show_capability_error(context): with patch.object( context.service, "compute_capability_summary", side_effect=ValueError("boom"), ): context.result = context.runner.invoke(skill_app, ["show", context.skill_name]) @when("I run skill show with dependents returning actors") def step_run_show_dependent_actors(context): with patch.object( context.service, "get_dependents", return_value={"skills": [], "actors": ["actor/alpha", "actor/beta"]}, ): context.result = context.runner.invoke(skill_app, ["show", context.skill_name]) @when("I run skill tools for the agent_skill skill") def step_run_tools_agent_skill(context): context.result = context.runner.invoke(skill_app, ["tools", context.skill_name]) @when("I run skill remove with dependents returning actors") def step_run_remove_with_actor_dependents(context): with patch.object( context.service, "get_dependents", return_value={ "skills": [], "actors": ["actor/gamma", "actor/delta"], }, ): context.result = context.runner.invoke( skill_app, ["remove", context.skill_name, "--yes"], ) # ── Then ──────────────────────────────────────────────────── @then("the show output contains the not registered marker") def step_show_not_registered(context): assert context.result.exit_code == 0, ( f"exit_code={context.result.exit_code}\n{context.result.output}" ) assert "not registered" in context.result.output @then("the show output contains OK and no capability panel") def step_show_ok_no_capability(context): assert context.result.exit_code == 0, ( f"exit_code={context.result.exit_code}\n{context.result.output}" ) assert "OK" in context.result.output # The capability panel should be absent because the exception was caught assert "Capability Summary" not in context.result.output @then("the show output contains the actors reference line") def step_show_actors_reference(context): assert context.result.exit_code == 0, ( f"exit_code={context.result.exit_code}\n{context.result.output}" ) assert "actor/alpha" in context.result.output assert "actor/beta" in context.result.output assert "Actors" in context.result.output @then("the tools output contains agent_skill source type") def step_tools_agent_skill_source(context): assert context.result.exit_code == 0, ( f"exit_code={context.result.exit_code}\n{context.result.output}" ) assert "agent_skill" in context.result.output @then("the remove output contains the actor dependency warning") def step_remove_actor_warning(context): assert context.result.exit_code == 0, ( f"exit_code={context.result.exit_code}\n{context.result.output}" ) assert "actor(s) reference this skill" in context.result.output assert "actor/gamma" in context.result.output assert "actor/delta" in context.result.output