diff --git a/tests/test_cmd_add_run.py b/tests/test_cmd_add_run.py index eee18ef..0efc07d 100644 --- a/tests/test_cmd_add_run.py +++ b/tests/test_cmd_add_run.py @@ -147,6 +147,19 @@ def test_clear_assigned_to_id_mutually_exclusive_with_assigned_to_id(self, mock_ assert result.exit_code == 1 assert "cannot be used together" in result.output + @mock.patch("trcli.cli.Environment.check_for_required_parameters") + def test_run_case_ids_mutually_exclusive_with_run_include_all(self, mock_check): + """Test that --run-case-ids and --run-include-all are mutually exclusive""" + runner = CliRunner() + + result = runner.invoke( + cmd_add_run.cli, + ["--title", "Test Run", "--run-case-ids", "1,2,3", "--run-include-all"], + ) + + assert result.exit_code == 1 + assert "cannot be used together" in result.output + class TestApiRequestHandlerReferences: """Test class for reference management functionality""" diff --git a/trcli/api/api_request_handler.py b/trcli/api/api_request_handler.py index f0ee817..27e11c9 100644 --- a/trcli/api/api_request_handler.py +++ b/trcli/api/api_request_handler.py @@ -257,9 +257,20 @@ def update_run( refs: str = None, refs_action: str = "add", assigned_to_id: Union[int, None] = ..., + include_all: Union[bool, type(...)] = ..., + case_ids: Union[List[int], type(...)] = ..., ) -> Tuple[dict, str]: return self.run_handler.update_run( - run_id, run_name, start_date, end_date, milestone_id, refs, refs_action, assigned_to_id + run_id, + run_name, + start_date, + end_date, + milestone_id, + refs, + refs_action, + assigned_to_id, + include_all, + case_ids, ) def _manage_references(self, existing_refs: str, new_refs: str, action: str) -> str: diff --git a/trcli/api/project_based_client.py b/trcli/api/project_based_client.py index 55fbabe..fdff4ae 100644 --- a/trcli/api/project_based_client.py +++ b/trcli/api/project_based_client.py @@ -222,6 +222,18 @@ def create_or_update_test_run(self) -> Tuple[int, str]: else: assigned_to_id = ... # Don't change (sentinel value) + # Determine include_all and case_ids based on user input + if self.environment.run_include_all: + include_all = True + case_ids = ... # Ignore case_ids when include_all is True + elif self.environment.run_case_ids: + include_all = False + case_ids = self.environment.run_case_ids + else: + # Neither provided - preserve existing settings + include_all = ... + case_ids = ... + run, error_message = self.api_request_handler.update_run( run_id, self.run_name, @@ -231,6 +243,8 @@ def create_or_update_test_run(self) -> Tuple[int, str]: refs=self.environment.run_refs, refs_action=getattr(self.environment, "run_refs_action", "add"), assigned_to_id=assigned_to_id, + include_all=include_all, + case_ids=case_ids, ) if self.environment.auto_close_run: self.environment.log("Closing run. ", new_line=False) diff --git a/trcli/api/run_handler.py b/trcli/api/run_handler.py index d30e972..bfd4441 100644 --- a/trcli/api/run_handler.py +++ b/trcli/api/run_handler.py @@ -136,6 +136,8 @@ def update_run( refs: str = None, refs_action: str = "add", assigned_to_id: Union[int, None] = ..., + include_all: Union[bool, type(...)] = ..., + case_ids: Union[List[int], type(...)] = ..., ) -> Tuple[dict, str]: """ Updates an existing run @@ -148,6 +150,8 @@ def update_run( :param refs: references to manage :param refs_action: action to perform ('add', 'update', 'delete') :param assigned_to_id: user ID to assign (int), None to clear, or ... to leave unchanged + :param include_all: include all cases (bool) or ... to leave unchanged + :param case_ids: specific case IDs (List[int]) or ... to leave unchanged :returns: Tuple with run and error string. """ run_response = self.client.send_get(f"get_run/{run_id}") @@ -174,22 +178,36 @@ def update_run( add_run_data["assignedto_id"] = assigned_to_id # Can be None (clears) or int (sets) # else: Don't include assignedto_id in payload (no change to existing assignee) - existing_include_all = run_response.response_text.get("include_all", False) - add_run_data["include_all"] = existing_include_all - - if not existing_include_all: - # Only manage explicit case_ids when include_all=False - run_tests, error_message = self.__get_all_tests_in_run(run_id) - if error_message: - return None, f"Failed to get tests in run: {error_message}" - run_case_ids = [test["case_id"] for test in run_tests] - report_case_ids = add_run_data["case_ids"] - joint_case_ids = list(set(report_case_ids + run_case_ids)) - add_run_data["case_ids"] = joint_case_ids + # Handle include_all - only change if explicitly provided + if include_all is not ...: + add_run_data["include_all"] = include_all else: - # include_all=True: TestRail includes all suite cases automatically - # Do NOT send case_ids array (TestRail ignores it anyway) + # Preserve existing value + existing_include_all = run_response.response_text.get("include_all", False) + add_run_data["include_all"] = existing_include_all + + # Handle case_ids based on include_all state + if add_run_data["include_all"]: + # include_all=True: Remove case_ids (TestRail includes all suite cases automatically) add_run_data.pop("case_ids", None) + else: + # include_all=False: Handle case_ids + if case_ids is not ...: + # User explicitly provided case_ids - use them + add_run_data["case_ids"] = case_ids + else: + # Preserve existing case_ids + run_tests, error_message = self.__get_all_tests_in_run(run_id) + if error_message: + return None, f"Failed to get tests in run: {error_message}" + run_case_ids = [test["case_id"] for test in run_tests] + # Merge with any case_ids from data provider (from report files) + report_case_ids = add_run_data.get("case_ids", []) + if report_case_ids: + joint_case_ids = list(set(report_case_ids + run_case_ids)) + add_run_data["case_ids"] = joint_case_ids + else: + add_run_data["case_ids"] = run_case_ids plan_id = run_response.response_text["plan_id"] config_ids = run_response.response_text["config_ids"] diff --git a/trcli/commands/cmd_add_run.py b/trcli/commands/cmd_add_run.py index cb6ac15..421ba89 100644 --- a/trcli/commands/cmd_add_run.py +++ b/trcli/commands/cmd_add_run.py @@ -145,6 +145,10 @@ def cli(environment: Environment, context: click.Context, *args, **kwargs): if environment.run_refs_action == "delete" and not environment.run_refs and environment.run_id: environment.run_refs = "" + if environment.run_case_ids and environment.run_include_all: + environment.elog("Error: --run-case-ids and --run-include-all cannot be used together.") + exit(1) + print_config(environment) project_client = ProjectBasedClient(