trcli 1.13.2__tar.gz → 1.13.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. {trcli-1.13.2 → trcli-1.13.4}/PKG-INFO +5 -1
  2. {trcli-1.13.2 → trcli-1.13.4}/README.md +172 -5
  3. {trcli-1.13.2 → trcli-1.13.4}/setup.py +4 -0
  4. {trcli-1.13.2 → trcli-1.13.4}/tests/test_cmd_add_run.py +71 -38
  5. trcli-1.13.4/tests/test_cmd_update.py +202 -0
  6. {trcli-1.13.2 → trcli-1.13.4}/tests/test_cucumber_parser.py +89 -0
  7. trcli-1.13.4/tests/test_glob_deduplication.py +380 -0
  8. trcli-1.13.4/tests/test_glob_integration.py +316 -0
  9. trcli-1.13.4/tests/test_junit_parser.py +305 -0
  10. trcli-1.13.4/tests/test_multiple_case_ids.py +521 -0
  11. trcli-1.13.4/tests/test_robot_parser.py +186 -0
  12. trcli-1.13.4/tests/test_version_checker.py +379 -0
  13. trcli-1.13.4/trcli/__init__.py +1 -0
  14. {trcli-1.13.2 → trcli-1.13.4}/trcli/api/api_request_handler.py +4 -1
  15. {trcli-1.13.2 → trcli-1.13.4}/trcli/api/case_handler.py +8 -0
  16. {trcli-1.13.2 → trcli-1.13.4}/trcli/api/project_based_client.py +10 -0
  17. {trcli-1.13.2 → trcli-1.13.4}/trcli/api/run_handler.py +17 -4
  18. {trcli-1.13.2 → trcli-1.13.4}/trcli/cli.py +13 -0
  19. {trcli-1.13.2 → trcli-1.13.4}/trcli/commands/cmd_add_run.py +58 -46
  20. {trcli-1.13.2 → trcli-1.13.4}/trcli/commands/cmd_parse_cucumber.py +8 -3
  21. {trcli-1.13.2 → trcli-1.13.4}/trcli/commands/cmd_parse_junit.py +2 -2
  22. {trcli-1.13.2 → trcli-1.13.4}/trcli/commands/cmd_parse_robot.py +2 -3
  23. trcli-1.13.4/trcli/commands/cmd_update.py +141 -0
  24. {trcli-1.13.2 → trcli-1.13.4}/trcli/data_providers/api_data_provider.py +57 -55
  25. {trcli-1.13.2 → trcli-1.13.4}/trcli/readers/cucumber_json.py +53 -1
  26. {trcli-1.13.2 → trcli-1.13.4}/trcli/readers/junit_xml.py +1 -1
  27. {trcli-1.13.2 → trcli-1.13.4}/trcli/readers/robot_xml.py +84 -24
  28. trcli-1.13.4/trcli/version_checker.py +234 -0
  29. {trcli-1.13.2 → trcli-1.13.4}/trcli.egg-info/PKG-INFO +5 -1
  30. {trcli-1.13.2 → trcli-1.13.4}/trcli.egg-info/SOURCES.txt +6 -0
  31. {trcli-1.13.2 → trcli-1.13.4}/trcli.egg-info/requires.txt +4 -0
  32. trcli-1.13.2/tests/test_junit_parser.py +0 -180
  33. trcli-1.13.2/tests/test_multiple_case_ids.py +0 -277
  34. trcli-1.13.2/tests/test_robot_parser.py +0 -80
  35. trcli-1.13.2/trcli/__init__.py +0 -1
  36. {trcli-1.13.2 → trcli-1.13.4}/LICENSE.md +0 -0
  37. {trcli-1.13.2 → trcli-1.13.4}/setup.cfg +0 -0
  38. {trcli-1.13.2 → trcli-1.13.4}/tests/test_api_client.py +0 -0
  39. {trcli-1.13.2 → trcli-1.13.4}/tests/test_api_client_proxy.py +0 -0
  40. {trcli-1.13.2 → trcli-1.13.4}/tests/test_api_data_provider.py +0 -0
  41. {trcli-1.13.2 → trcli-1.13.4}/tests/test_api_request_handler.py +0 -0
  42. {trcli-1.13.2 → trcli-1.13.4}/tests/test_api_request_handler_case_fields_update.py +0 -0
  43. {trcli-1.13.2 → trcli-1.13.4}/tests/test_api_request_handler_case_matcher.py +0 -0
  44. {trcli-1.13.2 → trcli-1.13.4}/tests/test_api_request_handler_labels.py +0 -0
  45. {trcli-1.13.2 → trcli-1.13.4}/tests/test_api_request_handler_references.py +0 -0
  46. {trcli-1.13.2 → trcli-1.13.4}/tests/test_cli.py +0 -0
  47. {trcli-1.13.2 → trcli-1.13.4}/tests/test_cmd_export_gherkin.py +0 -0
  48. {trcli-1.13.2 → trcli-1.13.4}/tests/test_cmd_import_gherkin.py +0 -0
  49. {trcli-1.13.2 → trcli-1.13.4}/tests/test_cmd_labels.py +0 -0
  50. {trcli-1.13.2 → trcli-1.13.4}/tests/test_cmd_parse_cucumber.py +0 -0
  51. {trcli-1.13.2 → trcli-1.13.4}/tests/test_cmd_references.py +0 -0
  52. {trcli-1.13.2 → trcli-1.13.4}/tests/test_cucumber_bdd_matching.py +0 -0
  53. {trcli-1.13.2 → trcli-1.13.4}/tests/test_dataclass_creation.py +0 -0
  54. {trcli-1.13.2 → trcli-1.13.4}/tests/test_junit_bdd_parser.py +0 -0
  55. {trcli-1.13.2 → trcli-1.13.4}/tests/test_junit_parse_reference.py +0 -0
  56. {trcli-1.13.2 → trcli-1.13.4}/tests/test_load_data_from_config.py +0 -0
  57. {trcli-1.13.2 → trcli-1.13.4}/tests/test_matchers_parser.py +0 -0
  58. {trcli-1.13.2 → trcli-1.13.4}/tests/test_project_based_client.py +0 -0
  59. {trcli-1.13.2 → trcli-1.13.4}/tests/test_response_verify.py +0 -0
  60. {trcli-1.13.2 → trcli-1.13.4}/tests/test_results_uploader.py +0 -0
  61. {trcli-1.13.2 → trcli-1.13.4}/trcli/api/__init__.py +0 -0
  62. {trcli-1.13.2 → trcli-1.13.4}/trcli/api/api_cache.py +0 -0
  63. {trcli-1.13.2 → trcli-1.13.4}/trcli/api/api_client.py +0 -0
  64. {trcli-1.13.2 → trcli-1.13.4}/trcli/api/api_response_verify.py +0 -0
  65. {trcli-1.13.2 → trcli-1.13.4}/trcli/api/api_utils.py +0 -0
  66. {trcli-1.13.2 → trcli-1.13.4}/trcli/api/bdd_handler.py +0 -0
  67. {trcli-1.13.2 → trcli-1.13.4}/trcli/api/case_matcher.py +0 -0
  68. {trcli-1.13.2 → trcli-1.13.4}/trcli/api/label_manager.py +0 -0
  69. {trcli-1.13.2 → trcli-1.13.4}/trcli/api/reference_manager.py +0 -0
  70. {trcli-1.13.2 → trcli-1.13.4}/trcli/api/result_handler.py +0 -0
  71. {trcli-1.13.2 → trcli-1.13.4}/trcli/api/results_uploader.py +0 -0
  72. {trcli-1.13.2 → trcli-1.13.4}/trcli/api/section_handler.py +0 -0
  73. {trcli-1.13.2 → trcli-1.13.4}/trcli/api/suite_handler.py +0 -0
  74. {trcli-1.13.2 → trcli-1.13.4}/trcli/backports.py +0 -0
  75. {trcli-1.13.2 → trcli-1.13.4}/trcli/commands/__init__.py +0 -0
  76. {trcli-1.13.2 → trcli-1.13.4}/trcli/commands/cmd_export_gherkin.py +0 -0
  77. {trcli-1.13.2 → trcli-1.13.4}/trcli/commands/cmd_import_gherkin.py +0 -0
  78. {trcli-1.13.2 → trcli-1.13.4}/trcli/commands/cmd_labels.py +0 -0
  79. {trcli-1.13.2 → trcli-1.13.4}/trcli/commands/cmd_parse_openapi.py +0 -0
  80. {trcli-1.13.2 → trcli-1.13.4}/trcli/commands/cmd_references.py +0 -0
  81. {trcli-1.13.2 → trcli-1.13.4}/trcli/commands/results_parser_helpers.py +0 -0
  82. {trcli-1.13.2 → trcli-1.13.4}/trcli/constants.py +0 -0
  83. {trcli-1.13.2 → trcli-1.13.4}/trcli/data_classes/__init__.py +0 -0
  84. {trcli-1.13.2 → trcli-1.13.4}/trcli/data_classes/data_parsers.py +0 -0
  85. {trcli-1.13.2 → trcli-1.13.4}/trcli/data_classes/dataclass_testrail.py +0 -0
  86. {trcli-1.13.2 → trcli-1.13.4}/trcli/data_classes/validation_exception.py +0 -0
  87. {trcli-1.13.2 → trcli-1.13.4}/trcli/logging/__init__.py +0 -0
  88. {trcli-1.13.2 → trcli-1.13.4}/trcli/logging/config.py +0 -0
  89. {trcli-1.13.2 → trcli-1.13.4}/trcli/logging/file_handler.py +0 -0
  90. {trcli-1.13.2 → trcli-1.13.4}/trcli/logging/structured_logger.py +0 -0
  91. {trcli-1.13.2 → trcli-1.13.4}/trcli/readers/__init__.py +0 -0
  92. {trcli-1.13.2 → trcli-1.13.4}/trcli/readers/file_parser.py +0 -0
  93. {trcli-1.13.2 → trcli-1.13.4}/trcli/readers/openapi_yml.py +0 -0
  94. {trcli-1.13.2 → trcli-1.13.4}/trcli/settings.py +0 -0
  95. {trcli-1.13.2 → trcli-1.13.4}/trcli.egg-info/dependency_links.txt +0 -0
  96. {trcli-1.13.2 → trcli-1.13.4}/trcli.egg-info/entry_points.txt +0 -0
  97. {trcli-1.13.2 → trcli-1.13.4}/trcli.egg-info/top_level.txt +0 -0
@@ -1,16 +1,20 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: trcli
3
- Version: 1.13.2
3
+ Version: 1.13.4
4
4
  License-File: LICENSE.md
5
5
  Requires-Dist: click<8.2.2,>=8.1.0
6
6
  Requires-Dist: pyyaml<7.0.0,>=6.0.0
7
7
  Requires-Dist: junitparser<4.0.0,>=3.1.0
8
8
  Requires-Dist: pyserde==0.12.*
9
9
  Requires-Dist: requests<3.0.0,>=2.31.0
10
+ Requires-Dist: urllib3<3.0.0,>=1.26.0
11
+ Requires-Dist: charset-normalizer<4.0.0,>=2.0.0
12
+ Requires-Dist: chardet<6.0.0,>=5.0.0
10
13
  Requires-Dist: tqdm<5.0.0,>=4.65.0
11
14
  Requires-Dist: humanfriendly<11.0.0,>=10.0.0
12
15
  Requires-Dist: openapi-spec-validator<1.0.0,>=0.5.0
13
16
  Requires-Dist: beartype<1.0.0,>=0.17.0
17
+ Requires-Dist: packaging>=20.0
14
18
  Requires-Dist: prance
15
19
  Dynamic: description
16
20
  Dynamic: license-file
@@ -33,7 +33,7 @@ trcli
33
33
  ```
34
34
  You should get something like this:
35
35
  ```
36
- TestRail CLI v1.13.2
36
+ TestRail CLI v1.13.4
37
37
  Copyright 2025 Gurock Software GmbH - www.gurock.com
38
38
  Supported and loaded modules:
39
39
  - parse_junit: JUnit XML Files (& Similar)
@@ -51,7 +51,7 @@ CLI general reference
51
51
  --------
52
52
  ```shell
53
53
  $ trcli --help
54
- TestRail CLI v1.13.2
54
+ TestRail CLI v1.13.4
55
55
  Copyright 2025 Gurock Software GmbH - www.gurock.com
56
56
  Usage: trcli [OPTIONS] COMMAND [ARGS]...
57
57
 
@@ -97,6 +97,7 @@ Commands:
97
97
  parse_openapi Parse OpenAPI spec and create cases in TestRail
98
98
  parse_robot Parse Robot Framework report and upload results to TestRail
99
99
  references Manage references in TestRail
100
+ update Update TRCLI to the latest version from PyPI.
100
101
  ```
101
102
 
102
103
  Uploading automated test results
@@ -190,9 +191,140 @@ Options:
190
191
  | `<testsuite>` | section |
191
192
  | `<testcase>` | case |
192
193
 
193
- For further detail, please refer to the
194
+ For further detail, please refer to the
194
195
  [JUnit to TestRail mapping](https://support.gurock.com/hc/en-us/articles/12989737200276) documentation.
195
196
 
197
+ ### Using Glob Patterns for Multiple Files
198
+
199
+ TRCLI supports glob patterns to process multiple report files in a single command. This feature is available for **JUnit XML**, **Robot Framework**, and **Cucumber JSON** parsers.
200
+
201
+ #### Important: Shell Quoting Requirement
202
+
203
+ **Glob patterns must be quoted** to prevent shell from expanding them prematurely. Without quotes, the shell will expand the pattern before passing it to TRCLI, causing unexpected errors.
204
+
205
+ ```bash
206
+ # CORRECT - Pattern quoted (TRCLI handles the expansion)
207
+ trcli parse_junit -f "reports/*.xml" --title "Test Results"
208
+ ```
209
+
210
+ #### Supported Glob Patterns
211
+
212
+ **Standard wildcards:**
213
+ ```bash
214
+ # Match all XML files in directory
215
+ -f "reports/*.xml"
216
+
217
+ # Match files with specific prefix
218
+ -f "target/surefire-reports/TEST-*.xml"
219
+
220
+ # Match files with specific suffix
221
+ -f "build/test-results/*-report.xml"
222
+ ```
223
+
224
+ **Recursive search** (matches subdirectories):
225
+ ```bash
226
+ # Search all subdirectories recursively
227
+ -f "test-results/**/*.xml"
228
+
229
+ # Match specific pattern in any subdirectory
230
+ -f "**/robot-output-*.xml"
231
+ ```
232
+
233
+ #### How File Merging Works
234
+
235
+ When a glob pattern matches **multiple files**, TRCLI automatically:
236
+
237
+ 1. **Expands the pattern** to find all matching files
238
+ 2. **Parses each file** individually
239
+ 3. **Merges test results** into a single combined report
240
+ 4. **Writes merged file** to current directory:
241
+ - JUnit: `Merged-JUnit-report.xml`
242
+ - Robot Framework: `Merged-Robot-report.xml`
243
+ - Cucumber: `merged_cucumber.json`
244
+ 5. **Processes the merged file** as a single test run upload
245
+
246
+ When a pattern matches **only one file**, TRCLI processes it directly without merging.
247
+
248
+ #### Examples
249
+
250
+ **JUnit XML - Multiple test suites:**
251
+ ```bash
252
+ # Merge all JUnit XML files from Maven surefire reports
253
+ trcli -y \
254
+ -h https://example.testrail.com \
255
+ --project "My Project" \
256
+ parse_junit \
257
+ -f "target/surefire-reports/junitreports/*.xml" \
258
+ --title "Merged Test Results"
259
+
260
+ # Merge test results from multiple modules
261
+ trcli parse_junit \
262
+ -f "build/test-results/**/*.xml" \
263
+ --title "All Module Tests" \
264
+ --case-matcher auto
265
+ ```
266
+
267
+ **Robot Framework - Multiple output files:**
268
+ ```bash
269
+ # Merge multiple Robot Framework test runs
270
+ trcli -y \
271
+ -h https://example.testrail.com \
272
+ --project "My Project" \
273
+ parse_robot \
274
+ -f "reports/robot-*.xml" \
275
+ --title "Merged Robot Tests"
276
+
277
+ # Recursive search for all Robot outputs
278
+ trcli parse_robot \
279
+ -f "test-results/**/output.xml" \
280
+ --title "All Robot Results" \
281
+ --case-matcher property
282
+ ```
283
+
284
+ **Cucumber JSON - Multiple test runs:**
285
+ ```bash
286
+ # Merge multiple Cucumber JSON reports
287
+ trcli -y \
288
+ -h https://example.testrail.com \
289
+ --project "My Project" \
290
+ parse_cucumber \
291
+ -f "reports/cucumber-*.json" \
292
+ --title "Merged Cucumber Tests"
293
+
294
+ # Recursive search for all Cucumber JSON results
295
+ trcli parse_cucumber \
296
+ -f "test-results/**/cucumber.json" \
297
+ --title "All Cucumber Results" \
298
+ --case-matcher auto
299
+ ```
300
+
301
+ #### Troubleshooting
302
+
303
+ **Error: "Got unexpected extra argument"**
304
+ - **Cause:** Glob pattern not quoted - shell expanded it before TRCLI
305
+ - **Solution:** Add quotes around the pattern: `-f "reports/*.xml"`
306
+
307
+ **Error: "File not found"**
308
+ - **Cause:** No files match the glob pattern
309
+ - **Solution:** Verify the pattern and file paths:
310
+ ```bash
311
+ # Check what files match your pattern
312
+ ls reports/*.xml
313
+
314
+ # Use absolute path if relative path doesn't work
315
+ trcli parse_junit -f "/full/path/to/reports/*.xml"
316
+ ```
317
+
318
+ **Pattern matches nothing in subdirectories:**
319
+ - **Cause:** Need recursive glob (`**`)
320
+ - **Solution:** Use `**` for recursive matching: `-f "reports/**/*.xml"`
321
+
322
+ #### Limitations
323
+
324
+ 1. Glob patterns are expanded by Python's `glob` module (not shell), so some advanced bash features may not work
325
+ 2. Very large numbers of files (100+) may cause performance issues during merging
326
+ 3. Merged files are created in the current working directory
327
+
196
328
  ### Uploading test results
197
329
  To submit test case results, the TestRail CLI will attempt to match the test cases in your automation suite to test cases in TestRail.
198
330
  There are 2 mechanisms to match test cases:
@@ -1509,7 +1641,7 @@ Options:
1509
1641
  ### Reference
1510
1642
  ```shell
1511
1643
  $ trcli add_run --help
1512
- TestRail CLI v1.13.2
1644
+ TestRail CLI v1.13.4
1513
1645
  Copyright 2025 Gurock Software GmbH - www.gurock.com
1514
1646
  Usage: trcli add_run [OPTIONS]
1515
1647
 
@@ -1526,6 +1658,8 @@ Options:
1526
1658
  --run-end-date The expected or scheduled end date of this test run in MM/DD/YYYY format
1527
1659
  --run-assigned-to-id The ID of the user the test run should be assigned
1528
1660
  to. [x>=1]
1661
+ --clear-run-assigned-to-id Clear the assignee of the test run (only valid
1662
+ when updating with --run-id).
1529
1663
  --run-include-all Use this option to include all test cases in this test run.
1530
1664
  --auto-close-run Use this option to automatically close the created run.
1531
1665
  --run-case-ids Comma separated list of test case IDs to include in
@@ -1598,6 +1732,39 @@ trcli -y -h https://example.testrail.io/ --project "My Project" \
1598
1732
  - **Action Requirements**: `update` and `delete` actions require an existing run (--run-id must be provided)
1599
1733
  - **Validation**: Invalid reference formats are rejected with clear error messages
1600
1734
 
1735
+ ### Managing Assignees in Test Runs
1736
+
1737
+ The `add_run` command supports comprehensive assignee management for test runs. You can assign runs to users when creating or updating them, and clear assignees when needed.
1738
+
1739
+ #### Assigning Runs to Users
1740
+
1741
+ When creating a new test run or updating an existing one, you can assign it to a user using the `--run-assigned-to-id` option:
1742
+
1743
+ ```bash
1744
+ # Create a new run and assign to user ID 5
1745
+ trcli -y -h https://example.testrail.io/ --project "My Project" \
1746
+ add_run --title "My Test Run" --run-assigned-to-id 5
1747
+
1748
+ # Update an existing run and change the assignee
1749
+ trcli -y -h https://example.testrail.io/ --project "My Project" \
1750
+ add_run --run-id 123 --title "My Test Run" --run-assigned-to-id 10
1751
+ ```
1752
+
1753
+ #### Clearing Assignees from Test Runs
1754
+
1755
+ To remove the assignee from an existing test run, use the `--clear-run-assigned-to-id` flag:
1756
+
1757
+ ```bash
1758
+ # Clear the assignee from an existing run
1759
+ trcli -y -h https://example.testrail.io/ --project "My Project" \
1760
+ add_run --run-id 123 --title "My Test Run" --clear-run-assigned-to-id
1761
+ ```
1762
+
1763
+ #### Assignee Management Rules
1764
+
1765
+ - **Update Mode Only**: The `--clear-run-assigned-to-id` flag can only be used when updating an existing run (requires `--run-id`)
1766
+ - **Mutually Exclusive**: You cannot use both `--run-assigned-to-id` and `--clear-run-assigned-to-id` in the same command
1767
+
1601
1768
  #### Examples
1602
1769
 
1603
1770
  **Complete Workflow Example:**
@@ -1633,7 +1800,7 @@ providing you with a solid base of test cases, which you can further expand on T
1633
1800
  ### Reference
1634
1801
  ```shell
1635
1802
  $ trcli parse_openapi --help
1636
- TestRail CLI v1.13.2
1803
+ TestRail CLI v1.13.4
1637
1804
  Copyright 2025 Gurock Software GmbH - www.gurock.com
1638
1805
  Usage: trcli parse_openapi [OPTIONS]
1639
1806
 
@@ -21,10 +21,14 @@ setup(
21
21
  "junitparser>=3.1.0,<4.0.0",
22
22
  "pyserde==0.12.*",
23
23
  "requests>=2.31.0,<3.0.0",
24
+ "urllib3>=1.26.0,<3.0.0",
25
+ "charset-normalizer>=2.0.0,<4.0.0",
26
+ "chardet>=5.0.0,<6.0.0",
24
27
  "tqdm>=4.65.0,<5.0.0",
25
28
  "humanfriendly>=10.0.0,<11.0.0",
26
29
  "openapi-spec-validator>=0.5.0,<1.0.0",
27
30
  "beartype>=0.17.0,<1.0.0",
31
+ "packaging>=20.0",
28
32
  "prance", # Does not use semantic versioning
29
33
  ],
30
34
  entry_points="""
@@ -42,9 +42,11 @@ class TestCmdAddRun:
42
42
  environment.run_assigned_to_id = assigned_to_id
43
43
  environment.run_case_ids = case_ids
44
44
  environment.run_include_all = True
45
- expected_string = (f"run_assigned_to_id: {assigned_to_id}\nrun_case_ids: '{case_ids}'\n"
46
- f"run_description: {description}\nrun_id: {run_id}\n"
47
- f"run_include_all: true\nrun_refs: {refs}\ntitle: {title}\n")
45
+ expected_string = (
46
+ f"run_assigned_to_id: {assigned_to_id}\nrun_case_ids: '{case_ids}'\n"
47
+ f"run_description: {description}\nrun_id: {run_id}\n"
48
+ f"run_include_all: true\nrun_refs: {refs}\ntitle: {title}\n"
49
+ )
48
50
  cmd_add_run.write_run_to_file(environment, run_id)
49
51
  mock_open_file.assert_called_with(file, "a")
50
52
  mock_open_file.return_value.__enter__().write.assert_called_once_with(expected_string)
@@ -52,35 +54,31 @@ class TestCmdAddRun:
52
54
  def test_cli_validation_refs_too_long(self):
53
55
  """Test that references validation fails when exceeding 250 characters"""
54
56
  from trcli.cli import Environment
55
-
57
+
56
58
  environment = Environment()
57
59
  environment.run_refs = "A" * 251 # 251 characters, exceeds limit
58
-
60
+
59
61
  assert len(environment.run_refs) > 250
60
-
62
+
61
63
  runner = CliRunner()
62
64
  long_refs = "A" * 251
63
-
64
- result = runner.invoke(cmd_add_run.cli, [
65
- '--title', 'Test Run',
66
- '--run-refs', long_refs
67
- ], catch_exceptions=False)
68
-
65
+
66
+ result = runner.invoke(
67
+ cmd_add_run.cli, ["--title", "Test Run", "--run-refs", long_refs], catch_exceptions=False
68
+ )
69
+
69
70
  # Should exit with error code 1 due to missing required parameters or validation
70
71
  assert result.exit_code == 1
71
72
 
72
73
  def test_cli_validation_refs_exactly_250_chars(self):
73
74
  """Test that references validation passes with exactly 250 characters"""
74
75
  from trcli.cli import Environment
75
-
76
+
76
77
  runner = CliRunner()
77
78
  refs_250 = "A" * 250 # Exactly 250 characters, should pass validation
78
-
79
- result = runner.invoke(cmd_add_run.cli, [
80
- '--title', 'Test Run',
81
- '--run-refs', refs_250
82
- ], catch_exceptions=False)
83
-
79
+
80
+ result = runner.invoke(cmd_add_run.cli, ["--title", "Test Run", "--run-refs", refs_250], catch_exceptions=False)
81
+
84
82
  # Should not fail due to refs validation (will fail due to missing required parameters)
85
83
  # But the important thing is that it doesn't fail with the character limit error
86
84
  assert "References field cannot exceed 250 characters" not in result.output
@@ -88,18 +86,18 @@ class TestCmdAddRun:
88
86
  def test_validation_logic_refs_action_without_run_id(self):
89
87
  """Test validation logic for refs action without run_id"""
90
88
  from trcli.cli import Environment
91
-
89
+
92
90
  # Update action validation
93
91
  environment = Environment()
94
92
  environment.run_refs_action = "update"
95
93
  environment.run_id = None
96
94
  environment.run_refs = "JIRA-123"
97
-
95
+
98
96
  # This should be invalid
99
97
  assert environment.run_refs_action == "update"
100
98
  assert environment.run_id is None
101
-
102
- # Delete action validation
99
+
100
+ # Delete action validation
103
101
  environment.run_refs_action = "delete"
104
102
  assert environment.run_refs_action == "delete"
105
103
  assert environment.run_id is None
@@ -107,37 +105,72 @@ class TestCmdAddRun:
107
105
  def test_refs_action_parameter_parsing(self):
108
106
  """Test that refs action parameter is parsed correctly"""
109
107
  runner = CliRunner()
110
-
108
+
111
109
  # Test that the CLI accepts new param without crashing! :) - acuanico
112
- result = runner.invoke(cmd_add_run.cli, ['--help'])
110
+ result = runner.invoke(cmd_add_run.cli, ["--help"])
113
111
  assert result.exit_code == 0
114
112
  assert "--run-refs-action" in result.output
115
113
  assert "Action to perform on references" in result.output
116
114
 
115
+ def test_clear_assigned_to_id_parameter_exists(self):
116
+ """Test that --clear-run-assigned-to-id parameter is available"""
117
+ runner = CliRunner()
118
+
119
+ result = runner.invoke(cmd_add_run.cli, ["--help"])
120
+ assert result.exit_code == 0
121
+ assert "--clear-run-assigned-to-id" in result.output
122
+ assert "Clear the assignee" in result.output
123
+
124
+ @mock.patch("trcli.cli.Environment.check_for_required_parameters")
125
+ def test_clear_assigned_to_id_requires_run_id(self, mock_check):
126
+ """Test that --clear-run-assigned-to-id requires --run-id"""
127
+ runner = CliRunner()
128
+
129
+ result = runner.invoke(cmd_add_run.cli, ["--title", "Test Run", "--clear-run-assigned-to-id"])
130
+
131
+ assert result.exit_code == 1
132
+ assert (
133
+ "--clear-run-assigned-to-id can only be used when updating" in result.output
134
+ or "--run-id required" in result.output
135
+ )
136
+
137
+ @mock.patch("trcli.cli.Environment.check_for_required_parameters")
138
+ def test_clear_assigned_to_id_mutually_exclusive_with_assigned_to_id(self, mock_check):
139
+ """Test that --clear-run-assigned-to-id and --run-assigned-to-id are mutually exclusive"""
140
+ runner = CliRunner()
141
+
142
+ result = runner.invoke(
143
+ cmd_add_run.cli,
144
+ ["--title", "Test Run", "--run-id", "123", "--run-assigned-to-id", "42", "--clear-run-assigned-to-id"],
145
+ )
146
+
147
+ assert result.exit_code == 1
148
+ assert "cannot be used together" in result.output
149
+
117
150
 
118
151
  class TestApiRequestHandlerReferences:
119
152
  """Test class for reference management functionality"""
120
-
153
+
121
154
  def test_manage_references_add(self):
122
155
  """Test adding references to existing ones"""
123
156
  from trcli.api.api_request_handler import ApiRequestHandler
124
157
  from trcli.cli import Environment
125
158
  from trcli.api.api_client import APIClient
126
159
  from trcli.data_classes.dataclass_testrail import TestRailSuite
127
-
160
+
128
161
  environment = Environment()
129
162
  api_client = APIClient("https://test.testrail.com")
130
163
  suite = TestRailSuite(name="Test Suite")
131
164
  handler = ApiRequestHandler(environment, api_client, suite)
132
-
165
+
133
166
  # Adding new references
134
167
  result = handler._manage_references("JIRA-100,JIRA-200", "JIRA-300,JIRA-400", "add")
135
168
  assert result == "JIRA-100,JIRA-200,JIRA-300,JIRA-400"
136
-
169
+
137
170
  # Adding duplicate references (should not duplicate)
138
171
  result = handler._manage_references("JIRA-100,JIRA-200", "JIRA-200,JIRA-300", "add")
139
172
  assert result == "JIRA-100,JIRA-200,JIRA-300"
140
-
173
+
141
174
  # Adding to empty existing references
142
175
  result = handler._manage_references("", "JIRA-100,JIRA-200", "add")
143
176
  assert result == "JIRA-100,JIRA-200"
@@ -148,16 +181,16 @@ class TestApiRequestHandlerReferences:
148
181
  from trcli.cli import Environment
149
182
  from trcli.api.api_client import APIClient
150
183
  from trcli.data_classes.dataclass_testrail import TestRailSuite
151
-
184
+
152
185
  environment = Environment()
153
186
  api_client = APIClient("https://test.testrail.com")
154
187
  suite = TestRailSuite(name="Test Suite")
155
188
  handler = ApiRequestHandler(environment, api_client, suite)
156
-
189
+
157
190
  # Test replacing all references
158
191
  result = handler._manage_references("JIRA-100,JIRA-200", "JIRA-300,JIRA-400", "update")
159
192
  assert result == "JIRA-300,JIRA-400"
160
-
193
+
161
194
  # Test replacing with empty references
162
195
  result = handler._manage_references("JIRA-100,JIRA-200", "", "update")
163
196
  assert result == ""
@@ -168,24 +201,24 @@ class TestApiRequestHandlerReferences:
168
201
  from trcli.cli import Environment
169
202
  from trcli.api.api_client import APIClient
170
203
  from trcli.data_classes.dataclass_testrail import TestRailSuite
171
-
204
+
172
205
  environment = Environment()
173
206
  api_client = APIClient("https://test.testrail.com")
174
207
  suite = TestRailSuite(name="Test Suite")
175
208
  handler = ApiRequestHandler(environment, api_client, suite)
176
-
209
+
177
210
  # Deleting specific references
178
211
  result = handler._manage_references("JIRA-100,JIRA-200,JIRA-300", "JIRA-200", "delete")
179
212
  assert result == "JIRA-100,JIRA-300"
180
-
213
+
181
214
  # Deleting multiple specific references
182
215
  result = handler._manage_references("JIRA-100,JIRA-200,JIRA-300,JIRA-400", "JIRA-200,JIRA-400", "delete")
183
216
  assert result == "JIRA-100,JIRA-300"
184
-
217
+
185
218
  # Deleting all references (empty new_refs)
186
219
  result = handler._manage_references("JIRA-100,JIRA-200", "", "delete")
187
220
  assert result == ""
188
-
221
+
189
222
  # Deleting non-existent references
190
223
  result = handler._manage_references("JIRA-100,JIRA-200", "JIRA-999", "delete")
191
224
  assert result == "JIRA-100,JIRA-200"