diff --git a/robot/helper_plan_cli_spec.py b/robot/helper_plan_cli_spec.py index 8961aaa90..55445b841 100644 --- a/robot/helper_plan_cli_spec.py +++ b/robot/helper_plan_cli_spec.py @@ -269,6 +269,57 @@ def list_columns() -> None: print("plan-cli-list-columns-ok") +def list_regex() -> None: + """Verify list accepts a positional argument and filters by name.""" + mock_service = MagicMock() + matching_plan = _mock_plan() # name: local/smoke-plan, action: local/smoke-action + now = matching_plan.timestamps.created_at + non_matching_plan = Plan( + identity=PlanIdentity(plan_id="01KHDE6WWS2171PWW3GJEBXZ8S"), + namespaced_name=NamespacedName.parse("local/other-plan"), + description="Other plan", + definition_of_done="Done", + action_name="local/other-action", + phase=PlanPhase.STRATEGIZE, + processing_state=ProcessingState.QUEUED, + project_links=[], + arguments={}, + arguments_order=[], + automation_profile=AutomationProfileRef( + profile_name="trusted", + provenance=AutomationProfileProvenance.PLAN, + ), + estimation_actor="openai/gpt-4", + invariant_actor="openai/gpt-4", + strategy_actor="openai/gpt-4", + execution_actor="openai/gpt-4", + reusable=True, + read_only=False, + created_by=None, + timestamps=PlanTimestamps(created_at=now, updated_at=now), + ) + mock_service.list_plans.return_value = [matching_plan, non_matching_plan] + with patch( + "cleveragents.cli.commands.plan._get_lifecycle_service", + return_value=mock_service, + ): + # Use JSON format so full names are visible (rich table truncates them) + result = runner.invoke(plan_app, ["list", "--format", "json", "smoke.*"]) + if result.exit_code != 0: + print(f"FAIL: list regex returned {result.exit_code}", file=sys.stderr) + print(result.output, file=sys.stderr) + sys.exit(1) + if "smoke-plan" not in result.output: + print("FAIL: matching plan not in output", file=sys.stderr) + print(result.output, file=sys.stderr) + sys.exit(1) + if "other-plan" in result.output: + print("FAIL: non-matching plan appeared in output", file=sys.stderr) + print(result.output, file=sys.stderr) + sys.exit(1) + print("plan-cli-list-regex-ok") + + def status_fields() -> None: """Verify plan status renders required fields.""" mock_service = MagicMock() @@ -329,6 +380,7 @@ _COMMANDS = { "use-actor-overrides": use_actor_overrides, "list-filters": list_filters, "list-columns": list_columns, + "list-regex": list_regex, "status-fields": status_fields, "cancel-reason": cancel_reason, } diff --git a/robot/plan_cli_spec.robot b/robot/plan_cli_spec.robot index d730d4de8..8f7a3089c 100644 --- a/robot/plan_cli_spec.robot +++ b/robot/plan_cli_spec.robot @@ -40,6 +40,14 @@ Plan Lifecycle List Accepts Filter Flags Should Be Equal As Integers ${result.rc} 0 Should Contain ${result.stdout} plan-cli-list-filters-ok +Plan Lifecycle List Accepts Regex Positional Argument + [Documentation] Verify that ``plan list `` filters plans by name regex + ${result}= Run Process ${PYTHON} ${HELPER} list-regex cwd=${WORKSPACE} + Log ${result.stdout} + Log ${result.stderr} + Should Be Equal As Integers ${result.rc} 0 + Should Contain ${result.stdout} plan-cli-list-regex-ok + Plan Status Renders Required Fields [Documentation] Verify that ``plan status`` renders action_name, phase, state, projects, args, timestamps ${result}= Run Process ${PYTHON} ${HELPER} status-fields cwd=${WORKSPACE}