Files
cleveragents-core/features/steps/plugin_cli_steps.py
T
HAL9000 d55e610f90 test(plugin-cli): expand BDD tests to cover all happy paths and long-description truncation
Add mock-based @given steps and 14 new scenarios covering the rich
table list, show, enable, disable, remove happy paths, the abort
confirmation flow, and the description truncation branch
(plugin.py:134). The @when step now patches _get_plugin_manager via
context so PluginManager isolation works without a singleton.

ISSUES CLOSED: #5756
2026-06-15 06:36:16 -04:00

95 lines
3.1 KiB
Python

"""Step definitions for plugin CLI commands."""
from __future__ import annotations
import json
from typing import Any
from unittest.mock import MagicMock, patch
from behave import given, then, when
from cleveragents.infrastructure.plugins.types import PluginState
def _make_plugin_manager(
state: PluginState, description: str = "A test plugin"
) -> MagicMock:
"""Create a mock PluginManager with one test plugin in the given state."""
descriptor = MagicMock()
descriptor.name = "test-plugin"
descriptor.version = "1.0.0"
descriptor.description = description
descriptor.module_path = "test.module"
descriptor.class_name = "TestPlugin"
descriptor.state = state
manager = MagicMock()
manager.list_plugins.return_value = [descriptor]
manager.get_plugin.return_value = descriptor
return manager
@given("a plugin manager with one active plugin")
def step_plugin_manager_active(context: Any) -> None:
"""Set up a mock PluginManager with one ACTIVATED plugin."""
context.plugin_manager = _make_plugin_manager(PluginState.ACTIVATED)
@given("a plugin manager with one inactive plugin")
def step_plugin_manager_inactive(context: Any) -> None:
"""Set up a mock PluginManager with one DEACTIVATED plugin."""
context.plugin_manager = _make_plugin_manager(PluginState.DEACTIVATED)
@given("a plugin manager with one plugin having a long description")
def step_plugin_manager_long_desc(context: Any) -> None:
"""Set up a mock PluginManager with a plugin whose description exceeds 40 chars."""
context.plugin_manager = _make_plugin_manager(
PluginState.ACTIVATED,
description="A" * 50,
)
@given('the next prompt answer is "{answer}"')
def step_set_prompt_answer(context: Any, answer: str) -> None:
"""Store stdin input to be used by the next plugin CLI invocation."""
context.cli_input = answer + "\n"
@when('I run "agents plugin {args}"')
def step_run_agents_plugin(context: Any, args: str) -> None:
"""Invoke a plugin CLI command and store output in context.command_output."""
from typer.testing import CliRunner
from cleveragents.cli.main import app
plugin_manager = getattr(context, "plugin_manager", None)
stdin = getattr(context, "cli_input", None)
runner = CliRunner()
split_args = args.split()
if plugin_manager is not None:
with patch(
"cleveragents.cli.commands.plugin._get_plugin_manager",
return_value=plugin_manager,
):
result = runner.invoke(
app, ["plugin", *split_args], input=stdin, catch_exceptions=True
)
else:
result = runner.invoke(
app, ["plugin", *split_args], input=stdin, catch_exceptions=True
)
context.command_output = result.output or ""
@then("the plugin CLI output should be valid JSON")
def step_plugin_output_is_json(context: Any) -> None:
"""Check if plugin CLI output is valid JSON."""
output = getattr(context, "command_output", "")
try:
context.json_output = json.loads(output)
except json.JSONDecodeError as e:
raise AssertionError(f"Output is not valid JSON: {e}") from e