diff --git a/README.md b/README.md index b2c3fd7..330ef90 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,8 @@ Commands: statuses Manage test statuses in TestRail casefields List case fields in TestRail resultfields List result fields in TestRail + priorities List test case priorities in TestRail + casetypes List test case types in TestRail update Update TRCLI to the latest version from PyPI. ``` @@ -2394,157 +2396,110 @@ Case Status ID: 2 Case status listing completed successfully. ``` -### Statuses Command - -The TestRail CLI provides the `statuses` command for retrieving status information from TestRail. This includes both test result statuses (Passed, Failed, Blocked, etc.) and case statuses (Approved, Draft, etc.). These statuses are crucial for mapping test results correctly and managing test case workflows. - -#### Statuses Command Overview - -The `statuses` command supports two subcommands: +### Priorities Command -| Subcommand | Purpose | API Endpoint | -|------------|---------|--------------| -| `all` | List all test result statuses | Retrieve available test result statuses (Passed, Failed, Blocked, etc.) | -| `case` | List all case statuses (Enterprise 7.3+) | Retrieve test case statuses (Approved, Draft, etc.) for case workflows | +The TestRail CLI provides the `priorities` command for retrieving all available test case priorities from TestRail. This command helps you understand the priority levels configured in your TestRail instance, including their IDs, names, short names, display order, and which priority is set as the default. #### Reference ```shell -$ trcli statuses --help +$ trcli priorities --help -Usage: trcli statuses [OPTIONS] COMMAND [ARGS]... - Manage test statuses in TestRail +Usage: trcli priorities [OPTIONS] COMMAND [ARGS]... + Manage test case priorities in TestRail Options: --help Show this message and exit. Commands: - all List all test result statuses from TestRail - case List all case statuses from TestRail (Enterprise 7.3+) + list List all test case priorities from TestRail ``` -##### Listing Test Result Statuses - -List all test result statuses available for a project: +#### Listing Priorities ```shell -# List all test result statuses (using config file) -$ trcli -c config.yml statuses all +# List all priorities +$ trcli priorities list -h https://yourinstance.testrail.io -u user@example.com -p password -# List all statuses with all parameters -$ trcli statuses all \ - --host https://yourinstance.testrail.io \ - --username \ - --password \ - --project "Your Project" +# Show all fields including priority order +$ trcli priorities list -c config.yml --show-all-fields -# Show all fields including color values -$ trcli -c config.yml statuses all --show-all-fields - -# JSON output for integration with other tools -$ trcli -c config.yml statuses all --json-output | jq '.[].name' +# JSON output +$ trcli priorities list -c config.yml --json-output ``` -**Example Output:** +#### Example Output ```shell -$ trcli -c config.yml statuses all - -Statuses List (Test Result Statuses) Execution Parameters -> TestRail instance: https://yourinstance.testrail.io (user: test@example.com) -> Project: Your Project - -Retrieving test result statuses for project ID 1... -Found 5 test result status(es): - -Status ID: 1 - Name: passed - Label: Passed - System Status: Yes - Is Untested: No - Is Final: Yes +$ trcli priorities list -c config.yml -Status ID: 2 - Name: blocked - Label: Blocked - System Status: Yes - Is Untested: No - Is Final: No - -Status ID: 3 - Name: untested - Label: Untested - System Status: Yes - Is Untested: Yes - Is Final: No +Priorities List Execution Parameters +> TestRail instance: https://yourinstance.testrail.io (user: your@email.com) +Retrieving priorities... +Found 4 priority level(s). -Status ID: 4 - Name: retest - Label: Retest - System Status: Yes - Is Untested: No - Is Final: No +ID: 1 | Name: 1 - Don't Test | Short: 1 - Don't +ID: 2 | Name: 2 - Low | Short: 2 - Low +ID: 3 | Name: 3 - Medium | Short: 3 - Med +ID: 4 | Name: 4 - Must Test | Short: 4 - Must [DEFAULT] -Status ID: 5 - Name: failed - Label: Failed - System Status: Yes - Is Untested: No - Is Final: Yes +Priority listing completed successfully. +``` +**Note:** The `[DEFAULT]` marker indicates which priority is set as the default for new test cases in TestRail. Priorities are global settings and apply across all projects in your TestRail instance. -Status listing completed successfully. -``` +### Case Types Command -##### Listing Case Statuses +The TestRail CLI provides the `casetypes` command for retrieving all available test case types from TestRail. This command helps you understand the different case type classifications configured in your TestRail instance, such as Automated, Functionality, Performance, and others, including which type is set as the default. -List all case statuses (requires TestRail Enterprise 7.3+): +#### Reference ```shell -# List all case statuses (using config file) -$ trcli -c config.yml statuses case +$ trcli casetypes --help -# List case statuses with all parameters -$ trcli statuses case \ - --host https://yourinstance.testrail.io \ - --username \ - --password \ - --project "Your Project" +Usage: trcli casetypes [OPTIONS] COMMAND [ARGS]... + Manage test case types in TestRail -# Show all fields including abbreviations -$ trcli -c config.yml statuses case --show-all-fields +Options: + --help Show this message and exit. -# JSON output for integration -$ trcli -c config.yml statuses case --json-output | jq '.[].name' +Commands: + list List all test case types from TestRail ``` -**Example Output:** +#### Listing Case Types ```shell -$ trcli -c config.yml statuses case +# List all case types +$ trcli -h https://yourinstance.testrail.io -u user@example.com -p password casetypes list -Statuses List (Case Statuses) Execution Parameters -> TestRail instance: https://yourinstance.testrail.io (user: test@example.com) -> Project: Your Project +# With config file +$ trcli casetypes list -c config.yml -Retrieving case statuses... -Note: This command requires TestRail Enterprise 7.3 or later. -Found 2 case status(es): +# JSON output +$ trcli casetypes list -c config.yml --json-output +``` -Case Status ID: 1 - Name: Approved - Is Default: No - Is Approved: Yes +#### Example Output -Case Status ID: 2 - Name: Draft - Is Default: Yes - Is Approved: No +```shell +$ trcli casetypes list -c config.yml +Case Types List Execution Parameters +> TestRail instance: https://yourinstance.testrail.io (user: your@email.com) +Retrieving case types... +Found 4 case type(s). -Case status listing completed successfully. +ID: 1 | Name: Automated +ID: 2 | Name: Functionality +ID: 3 | Name: Performance +ID: 6 | Name: Other [DEFAULT] + +Case type listing completed successfully. ``` +**Note:** The `[DEFAULT]` marker indicates which case type is set as the default for new test cases in TestRail. Case types are global settings and apply across all projects in your TestRail instance. + ### Case Fields Command The TestRail CLI provides the `casefields` command for retrieving all available test case custom fields from TestRail. This command helps you understand what custom fields are available for test cases, their types, configurations, and which projects they apply to. diff --git a/tests/test_cmd_casetypes.py b/tests/test_cmd_casetypes.py new file mode 100644 index 0000000..18ec37d --- /dev/null +++ b/tests/test_cmd_casetypes.py @@ -0,0 +1,119 @@ +import pytest +from unittest import mock +from unittest.mock import MagicMock, patch +from click.testing import CliRunner + +from trcli.cli import Environment +from trcli.commands import cmd_casetypes + + +class TestCmdCaseTypes: + """Test class for casetypes command functionality""" + + def setup_method(self): + """Set up test environment""" + self.runner = CliRunner() + self.environment = Environment(cmd="casetypes") + self.environment.host = "https://test.testrail.com" + self.environment.username = "test@example.com" + self.environment.password = "password" + self.environment.api_key = None + + def _setup_project_client_mock(self, mock_project_client): + """Helper to setup ProjectBasedClient mock""" + mock_client_instance = MagicMock() + mock_project_client.return_value = mock_client_instance + return mock_client_instance + + @mock.patch("trcli.commands.cmd_casetypes.ProjectBasedClient") + def test_list_case_types_success(self, mock_project_client): + """Test successful case types listing""" + mock_client = self._setup_project_client_mock(mock_project_client) + mock_client.api_request_handler.case_type_handler.get_case_types.return_value = ( + [ + {"id": 1, "is_default": False, "name": "Automated"}, + {"id": 2, "is_default": False, "name": "Functionality"}, + {"id": 3, "is_default": False, "name": "Performance"}, + {"id": 6, "is_default": True, "name": "Other"}, + ], + "", + ) + + with patch.object(self.environment, "log") as mock_log, patch.object( + self.environment, "set_parameters" + ), patch.object(self.environment, "check_for_required_parameters"): + result = self.runner.invoke(cmd_casetypes.list, [], obj=self.environment) + + assert result.exit_code == 0 + mock_client.api_request_handler.case_type_handler.get_case_types.assert_called_once() + assert mock_log.called + + @mock.patch("trcli.commands.cmd_casetypes.ProjectBasedClient") + def test_list_case_types_json_output(self, mock_project_client): + """Test case types listing with JSON output""" + mock_client = self._setup_project_client_mock(mock_project_client) + case_types_data = [ + {"id": 1, "is_default": False, "name": "Automated"}, + {"id": 6, "is_default": True, "name": "Other"}, + ] + mock_client.api_request_handler.case_type_handler.get_case_types.return_value = (case_types_data, "") + + with patch.object(self.environment, "set_parameters"), patch.object( + self.environment, "check_for_required_parameters" + ): + result = self.runner.invoke(cmd_casetypes.list, ["--json-output"], obj=self.environment) + + assert result.exit_code == 0 + # Check for prettified JSON + assert '"name": "Automated"' in result.output + assert "\n" in result.output + + @mock.patch("trcli.commands.cmd_casetypes.ProjectBasedClient") + def test_list_case_types_empty_result(self, mock_project_client): + """Test case types listing with no case types (edge case)""" + mock_client = self._setup_project_client_mock(mock_project_client) + mock_client.api_request_handler.case_type_handler.get_case_types.return_value = ([], "") + + with patch.object(self.environment, "log") as mock_log, patch.object( + self.environment, "set_parameters" + ), patch.object(self.environment, "check_for_required_parameters"): + result = self.runner.invoke(cmd_casetypes.list, [], obj=self.environment) + + assert result.exit_code == 0 + assert mock_log.called + + @mock.patch("trcli.commands.cmd_casetypes.ProjectBasedClient") + def test_list_case_types_api_error(self, mock_project_client): + """Test case types listing with API error""" + mock_client = self._setup_project_client_mock(mock_project_client) + mock_client.api_request_handler.case_type_handler.get_case_types.return_value = ([], "Connection timeout") + + with patch.object(self.environment, "elog") as mock_elog, patch.object( + self.environment, "set_parameters" + ), patch.object(self.environment, "check_for_required_parameters"): + result = self.runner.invoke(cmd_casetypes.list, [], obj=self.environment) + + assert result.exit_code == 1 + mock_elog.assert_called_with("Error: Failed to retrieve case types: Connection timeout") + + @mock.patch("trcli.commands.cmd_casetypes.ProjectBasedClient") + def test_list_case_types_default_marked(self, mock_project_client): + """Test that default case type is properly marked""" + mock_client = self._setup_project_client_mock(mock_project_client) + mock_client.api_request_handler.case_type_handler.get_case_types.return_value = ( + [ + {"id": 1, "is_default": False, "name": "Automated"}, + {"id": 6, "is_default": True, "name": "Other"}, + ], + "", + ) + + with patch.object(self.environment, "log") as mock_log, patch.object( + self.environment, "set_parameters" + ), patch.object(self.environment, "check_for_required_parameters"): + result = self.runner.invoke(cmd_casetypes.list, [], obj=self.environment) + + assert result.exit_code == 0 + # Verify DEFAULT marker appears for the default case type + log_calls = [str(call) for call in mock_log.call_args_list] + assert any("[DEFAULT]" in str(call) for call in log_calls) diff --git a/tests/test_cmd_priorities.py b/tests/test_cmd_priorities.py new file mode 100644 index 0000000..28b4f4b --- /dev/null +++ b/tests/test_cmd_priorities.py @@ -0,0 +1,199 @@ +import pytest +from unittest import mock +from unittest.mock import MagicMock, patch +from click.testing import CliRunner + +from trcli.cli import Environment +from trcli.commands import cmd_priorities + + +class TestCmdPriorities: + """Test class for priorities command functionality""" + + def setup_method(self): + """Set up test environment""" + self.runner = CliRunner() + self.environment = Environment(cmd="priorities") + self.environment.host = "https://test.testrail.com" + self.environment.username = "test@example.com" + self.environment.password = "password" + self.environment.api_key = None + + def _setup_project_client_mock(self, mock_project_client): + """Helper to setup ProjectBasedClient mock""" + mock_client_instance = MagicMock() + mock_project_client.return_value = mock_client_instance + return mock_client_instance + + @mock.patch("trcli.commands.cmd_priorities.ProjectBasedClient") + def test_list_priorities_success(self, mock_project_client): + """Test successful priorities listing""" + mock_client = self._setup_project_client_mock(mock_project_client) + mock_client.api_request_handler.priority_handler.get_priorities.return_value = ( + [ + { + "id": 1, + "is_default": False, + "name": "1 - Don't Test", + "priority": 1, + "short_name": "1 - Don't", + }, + { + "id": 2, + "is_default": False, + "name": "2 - Low", + "priority": 2, + "short_name": "2 - Low", + }, + { + "id": 3, + "is_default": False, + "name": "3 - Medium", + "priority": 3, + "short_name": "3 - Med", + }, + { + "id": 4, + "is_default": True, + "name": "4 - Must Test", + "priority": 4, + "short_name": "4 - Must", + }, + ], + "", + ) + + with patch.object(self.environment, "log") as mock_log, patch.object( + self.environment, "set_parameters" + ), patch.object(self.environment, "check_for_required_parameters"): + result = self.runner.invoke(cmd_priorities.list, [], obj=self.environment) + + assert result.exit_code == 0 + mock_client.api_request_handler.priority_handler.get_priorities.assert_called_once() + assert mock_log.called + + @mock.patch("trcli.commands.cmd_priorities.ProjectBasedClient") + def test_list_priorities_json_output(self, mock_project_client): + """Test priorities listing with JSON output""" + mock_client = self._setup_project_client_mock(mock_project_client) + priorities_data = [ + { + "id": 1, + "is_default": False, + "name": "1 - Don't Test", + "priority": 1, + "short_name": "1 - Don't", + }, + { + "id": 4, + "is_default": True, + "name": "4 - Must Test", + "priority": 4, + "short_name": "4 - Must", + }, + ] + mock_client.api_request_handler.priority_handler.get_priorities.return_value = (priorities_data, "") + + with patch.object(self.environment, "set_parameters"), patch.object( + self.environment, "check_for_required_parameters" + ): + result = self.runner.invoke(cmd_priorities.list, ["--json-output"], obj=self.environment) + + assert result.exit_code == 0 + # Check for prettified JSON + assert '"name": "4 - Must Test"' in result.output + assert "\n" in result.output + + @mock.patch("trcli.commands.cmd_priorities.ProjectBasedClient") + def test_list_priorities_show_all_fields(self, mock_project_client): + """Test priorities listing with show all fields""" + mock_client = self._setup_project_client_mock(mock_project_client) + mock_client.api_request_handler.priority_handler.get_priorities.return_value = ( + [ + { + "id": 1, + "is_default": False, + "name": "1 - Don't Test", + "priority": 1, + "short_name": "1 - Don't", + }, + { + "id": 4, + "is_default": True, + "name": "4 - Must Test", + "priority": 4, + "short_name": "4 - Must", + }, + ], + "", + ) + + with patch.object(self.environment, "log") as mock_log, patch.object( + self.environment, "set_parameters" + ), patch.object(self.environment, "check_for_required_parameters"): + result = self.runner.invoke(cmd_priorities.list, ["--show-all-fields"], obj=self.environment) + + assert result.exit_code == 0 + assert mock_log.called + + @mock.patch("trcli.commands.cmd_priorities.ProjectBasedClient") + def test_list_priorities_empty_result(self, mock_project_client): + """Test priorities listing with no priorities (edge case)""" + mock_client = self._setup_project_client_mock(mock_project_client) + mock_client.api_request_handler.priority_handler.get_priorities.return_value = ([], "") + + with patch.object(self.environment, "log") as mock_log, patch.object( + self.environment, "set_parameters" + ), patch.object(self.environment, "check_for_required_parameters"): + result = self.runner.invoke(cmd_priorities.list, [], obj=self.environment) + + assert result.exit_code == 0 + assert mock_log.called + + @mock.patch("trcli.commands.cmd_priorities.ProjectBasedClient") + def test_list_priorities_api_error(self, mock_project_client): + """Test priorities listing with API error""" + mock_client = self._setup_project_client_mock(mock_project_client) + mock_client.api_request_handler.priority_handler.get_priorities.return_value = ([], "Connection timeout") + + with patch.object(self.environment, "elog") as mock_elog, patch.object( + self.environment, "set_parameters" + ), patch.object(self.environment, "check_for_required_parameters"): + result = self.runner.invoke(cmd_priorities.list, [], obj=self.environment) + + assert result.exit_code == 1 + mock_elog.assert_called_with("Error: Failed to retrieve priorities: Connection timeout") + + @mock.patch("trcli.commands.cmd_priorities.ProjectBasedClient") + def test_list_priorities_default_marked(self, mock_project_client): + """Test that default priority is properly marked""" + mock_client = self._setup_project_client_mock(mock_project_client) + mock_client.api_request_handler.priority_handler.get_priorities.return_value = ( + [ + { + "id": 2, + "is_default": False, + "name": "2 - Low", + "priority": 2, + "short_name": "2 - Low", + }, + { + "id": 3, + "is_default": True, + "name": "3 - Medium", + "priority": 3, + "short_name": "3 - Med", + }, + ], + "", + ) + + with patch.object(self.environment, "log") as mock_log, patch.object( + self.environment, "set_parameters" + ), patch.object(self.environment, "check_for_required_parameters"): + result = self.runner.invoke(cmd_priorities.list, [], obj=self.environment) + + assert result.exit_code == 0 + # Verify DEFAULT marker appears for the default priority + log_calls = [str(call) for call in mock_log.call_args_list] + assert any("[DEFAULT]" in str(call) for call in log_calls) diff --git a/tests/test_data/cli_test_data.py b/tests/test_data/cli_test_data.py index 4094e2b..e107785 100644 --- a/tests/test_data/cli_test_data.py +++ b/tests/test_data/cli_test_data.py @@ -83,6 +83,8 @@ " - statuses: Query test statuses\n" " - casefields: Query test case custom fields\n" " - resultfields: Query test result custom fields\n" + " - priorities: Query test case priorities\n" + " - casetypes: Query test case types\n" " - results: Query and update test results (list, update)\n" ) diff --git a/trcli/api/api_request_handler.py b/trcli/api/api_request_handler.py index ddfe02b..801cda3 100644 --- a/trcli/api/api_request_handler.py +++ b/trcli/api/api_request_handler.py @@ -21,6 +21,8 @@ from trcli.api.status_handler import StatusHandler from trcli.api.case_field_handler import CaseFieldHandler from trcli.api.result_field_handler import ResultFieldHandler +from trcli.api.priority_handler import PriorityHandler +from trcli.api.case_type_handler import CaseTypeHandler from trcli.cli import Environment from trcli.constants import ( ProjectErrors, @@ -96,6 +98,8 @@ def __init__( self.status_handler = StatusHandler(api_client) self.case_field_handler = CaseFieldHandler(api_client) self.result_field_handler = ResultFieldHandler(api_client) + self.priority_handler = PriorityHandler(api_client) + self.case_type_handler = CaseTypeHandler(api_client) # BDD case cache for feature name matching (shared by CucumberParser and JunitParser) # Structure: {"{project_id}_{suite_id}": {normalized_name: [case_dict, case_dict, ...]}} diff --git a/trcli/api/case_type_handler.py b/trcli/api/case_type_handler.py new file mode 100644 index 0000000..74d5744 --- /dev/null +++ b/trcli/api/case_type_handler.py @@ -0,0 +1,38 @@ +""" +Handler for TestRail case type operations. +Provides methods to retrieve test case type information. +""" + +from typing import List, Tuple + + +class CaseTypeHandler: + """Handles case type-related API operations.""" + + def __init__(self, api_client): + """ + Initialize CaseTypeHandler. + + Args: + api_client: APIClient instance for making API calls + """ + self.api_client = api_client + + def get_case_types(self) -> Tuple[List[dict], str]: + """ + Get all available test case types. + + Returns: + Tuple of (list of case type dictionaries, error message) + Case type dict contains: id, name, is_default + """ + response = self.api_client.send_get("get_case_types") + + if response.error_message: + return [], response.error_message + + case_types = response.response_text + if not isinstance(case_types, list): + return [], "Invalid response format: expected list of case types" + + return case_types, "" diff --git a/trcli/api/priority_handler.py b/trcli/api/priority_handler.py new file mode 100644 index 0000000..219a27f --- /dev/null +++ b/trcli/api/priority_handler.py @@ -0,0 +1,38 @@ +""" +Handler for TestRail priority operations. +Provides methods to retrieve test case priority information. +""" + +from typing import List, Tuple + + +class PriorityHandler: + """Handles priority-related API operations.""" + + def __init__(self, api_client): + """ + Initialize PriorityHandler. + + Args: + api_client: APIClient instance for making API calls + """ + self.api_client = api_client + + def get_priorities(self) -> Tuple[List[dict], str]: + """ + Get all available test case priorities. + + Returns: + Tuple of (list of priority dictionaries, error message) + Priority dict contains: id, name, short_name, priority, is_default + """ + response = self.api_client.send_get("get_priorities") + + if response.error_message: + return [], response.error_message + + priorities = response.response_text + if not isinstance(priorities, list): + return [], "Invalid response format: expected list of priorities" + + return priorities, "" diff --git a/trcli/commands/cmd_casetypes.py b/trcli/commands/cmd_casetypes.py new file mode 100644 index 0000000..174cfe3 --- /dev/null +++ b/trcli/commands/cmd_casetypes.py @@ -0,0 +1,75 @@ +import builtins +import click +import json + +from trcli.api.project_based_client import ProjectBasedClient +from trcli.cli import pass_environment, CONTEXT_SETTINGS, Environment +from trcli.data_classes.dataclass_testrail import TestRailSuite + + +def print_config(env: Environment, action: str): + env.log(f"Case Types {action} Execution Parameters" f"\n> TestRail instance: {env.host} (user: {env.username})") + + +@click.group(context_settings=CONTEXT_SETTINGS) +@click.pass_context +@pass_environment +def cli(environment: Environment, context: click.Context, *args, **kwargs): + """Manage test case types in TestRail""" + environment.cmd = "casetypes" + environment.set_parameters(context) + + +@cli.command() +@click.option("--json-output", is_flag=True, help="Output case types as raw JSON from API.") +@click.pass_context +@pass_environment +def list( + environment: Environment, + context: click.Context, + json_output: bool, + *args, + **kwargs, +): + """List all test case types from TestRail""" + environment.check_for_required_parameters() + + print_config(environment, "List") + + # Create ProjectBasedClient (case types are global, but we use this for consistent API access) + project_client = ProjectBasedClient( + environment=environment, + suite=TestRailSuite(name=environment.suite_name, suite_id=environment.suite_id), + ) + + environment.log("Retrieving case types...") + + # Retrieve case types using CaseTypeHandler + case_types, error_message = project_client.api_request_handler.case_type_handler.get_case_types() + + if error_message: + environment.elog(f"Error: Failed to retrieve case types: {error_message}") + raise SystemExit(1) + + if json_output: + # Output prettified JSON response + print(json.dumps(case_types, indent=2)) + else: + environment.log(f"Found {len(case_types)} case type(s).") + environment.log("") + + if not case_types: + environment.log("No case types found.") + else: + # Display case types in a simple format + for case_type in case_types: + case_type_id = case_type.get("id") + name = case_type.get("name", "N/A") + is_default = case_type.get("is_default", False) + + default_marker = " [DEFAULT]" if is_default else "" + environment.log(f"ID: {case_type_id} | Name: {name}{default_marker}") + + environment.log("") + + environment.log("Case type listing completed successfully.") diff --git a/trcli/commands/cmd_priorities.py b/trcli/commands/cmd_priorities.py new file mode 100644 index 0000000..0660b28 --- /dev/null +++ b/trcli/commands/cmd_priorities.py @@ -0,0 +1,86 @@ +import builtins +import click +import json + +from trcli.api.project_based_client import ProjectBasedClient +from trcli.cli import pass_environment, CONTEXT_SETTINGS, Environment +from trcli.data_classes.dataclass_testrail import TestRailSuite + + +def print_config(env: Environment, action: str): + env.log(f"Priorities {action} Execution Parameters" f"\n> TestRail instance: {env.host} (user: {env.username})") + + +@click.group(context_settings=CONTEXT_SETTINGS) +@click.pass_context +@pass_environment +def cli(environment: Environment, context: click.Context, *args, **kwargs): + """Manage test case priorities in TestRail""" + environment.cmd = "priorities" + environment.set_parameters(context) + + +@cli.command() +@click.option("--json-output", is_flag=True, help="Output priorities as raw JSON from API.") +@click.option("--show-all-fields", is_flag=True, help="Show all fields including priority order and default flag.") +@click.pass_context +@pass_environment +def list( + environment: Environment, + context: click.Context, + json_output: bool, + show_all_fields: bool, + *args, + **kwargs, +): + """List all test case priorities from TestRail""" + environment.check_for_required_parameters() + + print_config(environment, "List") + + # Create ProjectBasedClient (priorities are global, but we use this for consistent API access) + project_client = ProjectBasedClient( + environment=environment, + suite=TestRailSuite(name=environment.suite_name, suite_id=environment.suite_id), + ) + + environment.log("Retrieving priorities...") + + # Retrieve priorities using PriorityHandler + priorities, error_message = project_client.api_request_handler.priority_handler.get_priorities() + + if error_message: + environment.elog(f"Error: Failed to retrieve priorities: {error_message}") + raise SystemExit(1) + + if json_output: + # Output prettified JSON response + print(json.dumps(priorities, indent=2)) + else: + environment.log(f"Found {len(priorities)} priority level(s).") + environment.log("") + + if not priorities: + environment.log("No priorities found.") + else: + # Display priorities in a table-like format + for priority in priorities: + priority_id = priority.get("id") + name = priority.get("name", "N/A") + short_name = priority.get("short_name", "N/A") + is_default = priority.get("is_default", False) + priority_order = priority.get("priority", "N/A") + + default_marker = " [DEFAULT]" if is_default else "" + + if show_all_fields: + environment.log( + f"ID: {priority_id} | Name: {name} | Short: {short_name} | " + f"Order: {priority_order}{default_marker}" + ) + else: + environment.log(f"ID: {priority_id} | Name: {name} | Short: {short_name}{default_marker}") + + environment.log("") + + environment.log("Priority listing completed successfully.") diff --git a/trcli/constants.py b/trcli/constants.py index 504374c..b8963ab 100644 --- a/trcli/constants.py +++ b/trcli/constants.py @@ -100,6 +100,8 @@ statuses=dict(**FAULT_MAPPING), casefields=dict(**FAULT_MAPPING), resultfields=dict(**FAULT_MAPPING), + priorities=dict(**FAULT_MAPPING), + casetypes=dict(**FAULT_MAPPING), ) PROMPT_MESSAGES = dict( @@ -136,6 +138,8 @@ - statuses: Query test statuses - casefields: Query test case custom fields - resultfields: Query test result custom fields + - priorities: Query test case priorities + - casetypes: Query test case types - results: Query and update test results (list, update)""" MISSING_COMMAND_SLOGAN = """Usage: trcli [OPTIONS] COMMAND [ARGS]...\nTry 'trcli --help' for help.