diff --git a/features/m5_acms_smoke.feature b/features/m5_acms_smoke.feature index fabd244cf..315ef28b5 100644 --- a/features/m5_acms_smoke.feature +++ b/features/m5_acms_smoke.feature @@ -107,6 +107,39 @@ Feature: M5 ACMS pipeline and large-project context smoke tests When I m5 smoke invoke context clear Then the m5 smoke context clear should succeed + # --- Context CLI: multiple resources --- + + Scenario: M5 smoke context list with multiple resources + Given a m5 smoke project with multiple context entries + When I m5 smoke invoke context list + Then the m5 smoke context list should succeed + And the m5 smoke context list output should contain multiple files + + Scenario: M5 smoke context add multiple files to project + Given a m5 smoke project with mocked multi-add context service + When I m5 smoke invoke context add with paths "src/a.py" and "src/b.py" + Then the m5 smoke context add should succeed + + Scenario: M5 smoke context show with multiple resources shows summary + Given a m5 smoke project with multiple context entries + When I m5 smoke invoke context show without path + Then the m5 smoke context show should succeed + And the m5 smoke context show output should contain summary + + # --- Context CLI: clear and re-add --- + + Scenario: M5 smoke context clear then re-add restores entries + Given a m5 smoke project with context entries + When I m5 smoke invoke context clear + Then the m5 smoke context clear should succeed + When I m5 smoke re-add context entry "src/main.py" after clear + Then the m5 smoke context add should succeed + + Scenario: M5 smoke context clear on empty project succeeds + Given a m5 smoke project with no context + When I m5 smoke invoke context clear + Then the m5 smoke context clear should succeed + # --- Project context policy CLI --- Scenario: M5 smoke project context show displays policy diff --git a/features/steps/m5_acms_smoke_steps.py b/features/steps/m5_acms_smoke_steps.py index 002ad554c..853d2c560 100644 --- a/features/steps/m5_acms_smoke_steps.py +++ b/features/steps/m5_acms_smoke_steps.py @@ -572,6 +572,102 @@ def step_m5_scores_bounded(context: Context) -> None: assert 0.0 <= score <= 1.0, f"Score for {path} out of range: {score}" +# --------------------------------------------------------------------------- +# Context CLI: multiple resources +# --------------------------------------------------------------------------- + + +@given("a m5 smoke project with multiple context entries") +def step_m5_project_with_multiple_entries(context: Context) -> None: + """Set up a project with multiple context files for testing.""" + entries = [] + for i, name in enumerate(["src/a.py", "src/b.py", "src/c.py"]): + mock_entry = MagicMock(spec=ContextModel) + mock_entry.path = name + mock_entry.size = 1024 * (i + 1) + mock_entry.type = "FILE" + mock_entry.added_at = "2026-03-01T00:00:00Z" + mock_entry.content = f"# content of {name}" + entries.append(mock_entry) + context.mock_context_service.list_context.return_value = entries + context.mock_context_service.clear_context.return_value = len(entries) + + +@then("the m5 smoke context list output should contain multiple files") +def step_m5_context_list_multiple(context: Context) -> None: + output = context.m5_result.output + assert "a.py" in output or "3 total" in output, ( + f"Expected multiple files in output, got: {output}" + ) + + +@given("a m5 smoke project with mocked multi-add context service") +def step_m5_project_mocked_multi_add(context: Context) -> None: + context.mock_context_service.add_to_context.return_value = ( + [Path("src/a.py"), Path("src/b.py")], + [], + ) + + +@when('I m5 smoke invoke context add with paths "{path1}" and "{path2}"') +def step_m5_invoke_context_add_multi(context: Context, path1: str, path2: str) -> None: + container = _mock_container(context.mock_context_service) + with ( + patch( + "cleveragents.application.container.get_container", + return_value=container, + ), + patch.object(Path, "exists", return_value=True), + ): + result = context.runner.invoke(context_app, ["add", path1, path2]) + context.m5_result = result + + +@when("I m5 smoke invoke context show without path") +def step_m5_invoke_context_show_no_path(context: Context) -> None: + container = _mock_container(context.mock_context_service) + with patch( + "cleveragents.application.container.get_container", + return_value=container, + ): + result = context.runner.invoke(context_app, ["show"]) + context.m5_result = result + + +@then("the m5 smoke context show output should contain summary") +def step_m5_context_show_summary(context: Context) -> None: + output = context.m5_result.output + assert ( + "total" in output.lower() + or "summary" in output.lower() + or "files" in output.lower() + ), f"Expected summary in output, got: {output}" + + +# --------------------------------------------------------------------------- +# Context CLI: clear and re-add +# --------------------------------------------------------------------------- + + +@when('I m5 smoke re-add context entry "{path}" after clear') +def step_m5_readd_after_clear(context: Context, path: str) -> None: + """Re-add a context entry after clearing, simulating clear+re-add flow.""" + context.mock_context_service.add_to_context.return_value = ( + [Path(path)], + [], + ) + container = _mock_container(context.mock_context_service) + with ( + patch( + "cleveragents.application.container.get_container", + return_value=container, + ), + patch.object(Path, "exists", return_value=True), + ): + result = context.runner.invoke(context_app, ["add", path]) + context.m5_result = result + + # --------------------------------------------------------------------------- # Multi-project context # --------------------------------------------------------------------------- diff --git a/robot/e2e/common_e2e.resource b/robot/e2e/common_e2e.resource index 8008931d2..29bd6e3ff 100644 --- a/robot/e2e/common_e2e.resource +++ b/robot/e2e/common_e2e.resource @@ -240,6 +240,8 @@ Create Temp Git Repo Should Be Equal As Integers ${r2.rc} 0 msg=git config user.name failed ${r3}= Run Process git config user.email e2e@test.local cwd=${repo_dir} timeout=60s on_timeout=kill Should Be Equal As Integers ${r3.rc} 0 msg=git config user.email failed + ${r3b}= Run Process git config commit.gpgsign false cwd=${repo_dir} timeout=60s on_timeout=kill + Should Be Equal As Integers ${r3b.rc} 0 msg=git config commit.gpgsign failed # Create an initial commit so the repo has a HEAD Create File ${repo_dir}${/}README.md # Test Repository\n ${r4}= Run Process git add . cwd=${repo_dir} timeout=60s on_timeout=kill diff --git a/robot/e2e/m5_acceptance.robot b/robot/e2e/m5_acceptance.robot index 14f541311..8129da467 100644 --- a/robot/e2e/m5_acceptance.robot +++ b/robot/e2e/m5_acceptance.robot @@ -55,6 +55,8 @@ M5 Acceptance Suite Setup Should Be Equal As Integers ${git_cfg_name.rc} 0 msg=git config user.name failed ${git_cfg_email}= Run Process git config user.email e2e@test.local cwd=${ws} timeout=60s on_timeout=kill Should Be Equal As Integers ${git_cfg_email.rc} 0 msg=git config user.email failed + ${git_cfg_gpg}= Run Process git config commit.gpgsign false cwd=${ws} timeout=60s on_timeout=kill + Should Be Equal As Integers ${git_cfg_gpg.rc} 0 msg=git config commit.gpgsign failed ${git_add}= Run Process git add . cwd=${ws} timeout=60s on_timeout=kill Should Be Equal As Integers ${git_add.rc} 0 msg=git add failed (rc=${git_add.rc}). Check DEBUG logs above. ${git_commit}= Run Process git commit -m Initial commit cwd=${ws} timeout=60s on_timeout=kill