testbench2robotframework 0.8.0a7__tar.gz → 0.9.0a1__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 (58) hide show
  1. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/PKG-INFO +1 -1
  2. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/testbench2robotframework/__init__.py +1 -1
  3. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/testbench2robotframework/cli.py +11 -1
  4. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/testbench2robotframework/config.py +2 -0
  5. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/testbench2robotframework/model.py +261 -58
  6. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/testbench2robotframework/result_writer.py +1 -1
  7. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/testbench2robotframework/testbench2rf.py +39 -10
  8. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/testbench2robotframework/testbench2robotframework.py +2 -1
  9. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/testbench2robotframework/utils.py +52 -0
  10. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/.gitignore +0 -0
  11. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/CreatePiPWheel.bat +0 -0
  12. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/CreatePiPWheel.sh +0 -0
  13. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/DEVELOPMENT.md +0 -0
  14. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/ExampleConfiguration/json_config.json +0 -0
  15. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/ExampleConfiguration/pyproject_example.toml +0 -0
  16. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/ExampleConfiguration/toml_config.toml +0 -0
  17. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/LICENSE +0 -0
  18. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/MANIFEST.in +0 -0
  19. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/README.md +0 -0
  20. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/atest/json_config_tests/1_tfs.robot +0 -0
  21. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/atest/robot/libs/json_config.py +0 -0
  22. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/atest/robot/libs/pyproject_config.py +0 -0
  23. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/atest/robot/resources/file_management.resource +0 -0
  24. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/atest/robot/resources/testbench2robotframework_cli.resource +0 -0
  25. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/atest/robot/rf_tests/cli_interface/write/json_config.robot +0 -0
  26. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/atest/robot/rf_tests/cli_interface/write/no_config_argument.robot +0 -0
  27. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/atest/robot/rf_tests/cli_interface/write/toml_config.robot +0 -0
  28. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/create_json_schema.py +0 -0
  29. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/images/LibrarySubdivision.PNG +0 -0
  30. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/images/Unbenannt.PNG +0 -0
  31. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/images/generated.png +0 -0
  32. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/images/libraries.PNG +0 -0
  33. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/images/resources.PNG +0 -0
  34. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/images/rfLibraryRootsTestBench.PNG +0 -0
  35. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/images/testbench_rfLibraryRegex.PNG +0 -0
  36. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/images/testbench_rfResourceRegex.PNG +0 -0
  37. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/images/testthemen.PNG +0 -0
  38. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/oldModel.py +0 -0
  39. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/pydantic_model.py +0 -0
  40. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/pyproject.toml +0 -0
  41. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/requirements.txt +0 -0
  42. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/robot.toml +0 -0
  43. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/tasks.py +0 -0
  44. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/testbench-tools.zip +0 -0
  45. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/testbench2robotframework/__main__.py +0 -0
  46. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/testbench2robotframework/execution_artifacts.py +0 -0
  47. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/testbench2robotframework/html_parser.py +0 -0
  48. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/testbench2robotframework/json_reader.py +0 -0
  49. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/testbench2robotframework/json_writer.py +0 -0
  50. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/testbench2robotframework/log.py +0 -0
  51. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/testbench2robotframework/model_utils.py +0 -0
  52. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/testbench2robotframework/robotframework2testbench.py +0 -0
  53. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/testbench2robotframework/testsuite_write.py +0 -0
  54. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/tests/test_data/configurations/invalid_config.json +0 -0
  55. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/tests/test_data/configurations/valid_config.json +0 -0
  56. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/tests/test_missing_files.py +0 -0
  57. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/tests/test_robot_files_should_not_contain_invalid_characters.py +0 -0
  58. {testbench2robotframework-0.8.0a7 → testbench2robotframework-0.9.0a1}/tests/test_zip_file_generation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: testbench2robotframework
3
- Version: 0.8.0a7
3
+ Version: 0.9.0a1
4
4
  Summary: Robot Framework Code Generator from Keyword-Driven Tests in imbus TestBench 3.0 and newer
5
5
  Author-email: imbus AG <support@imbus.de>
6
6
  Requires-Python: >= 3.10
@@ -17,4 +17,4 @@ suites and enhancing the TestBench report with execution results from Robot Fram
17
17
 
18
18
  from .testbench2robotframework import testbench2robotframework # noqa: F401
19
19
 
20
- __version__ = "0.8.0a7"
20
+ __version__ = "0.9.0a1"
@@ -119,6 +119,15 @@ def testbench2robotframework_cli():
119
119
  help="""TestBench root subdivision which's direct
120
120
  children correspond to Robot Framework libraries.""",
121
121
  )
122
+ @click.option(
123
+ "--metadata",
124
+ multiple=True,
125
+ callback=parse_subdivision_mapping,
126
+ help="""Add extra metadata to the settings of the generated Robot Framework test suite.
127
+ Provide entries as key:value pairs, where *key* is the metadata name and *value* is the corresponding value.
128
+ Values may also be Python expressions.
129
+ The special variable '$tcs' gives access to the TestBench Python model of the test case set.""",
130
+ )
122
131
  @click.option(
123
132
  "--resource-regex",
124
133
  multiple=True,
@@ -157,6 +166,7 @@ def generate_tests( # noqa: PLR0913
157
166
  resource_directory_regex: str,
158
167
  library_root: tuple[str],
159
168
  log_suite_numbering: bool,
169
+ metadata: dict[str, str],
160
170
  output_directory: Path,
161
171
  resource_directory: Path,
162
172
  resource_regex: tuple[str],
@@ -187,7 +197,7 @@ def generate_tests( # noqa: PLR0913
187
197
  configuration["log-suite-numbering"] = True
188
198
  else:
189
199
  configuration["log-suite-numbering"] = configuration.get("log-suite-numbering", False)
190
-
200
+ configuration["metadata"] = metadata or configuration.get("metadata", {})
191
201
  configuration["compound-interaction-logging"] = (
192
202
  compound_interaction_logging or configuration.get("compound-interaction-logging", "GROUP")
193
203
  )
@@ -193,6 +193,7 @@ class Configuration:
193
193
  library_root: list[str]
194
194
  log_suite_numbering: bool
195
195
  loggingConfiguration: LoggingConfig
196
+ metadata: dict[str, str]
196
197
  output_directory: str
197
198
  phasePattern: str
198
199
  referenceBehaviour: ReferenceBehaviour
@@ -227,6 +228,7 @@ class Configuration:
227
228
  "file":dictionary.get("file-logging", {})
228
229
  }
229
230
  ),
231
+ metadata=dictionary.get("metadata", {}),
230
232
  compound_interaction_logging=CompoundInteractionLogging(dictionary.get("compound-interaction-logging", "GROUP").upper()),
231
233
  resource_directory=dictionary.get("resource-directory", "").replace(
232
234
  "\\", "/"
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: openapi.yml
3
- # timestamp: 2025-08-04T13:02:46+00:00
3
+ # timestamp: 2025-11-07T10:20:17+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -135,8 +135,8 @@ class SequencePhase(Enum):
135
135
 
136
136
 
137
137
  class InteractionCallType(Enum):
138
- Check = 'Check'
139
138
  Flow = 'Flow'
139
+ Check = 'Check'
140
140
 
141
141
 
142
142
  class InteractionType(Enum):
@@ -237,6 +237,12 @@ class LoginSession:
237
237
  licenseWarning: Optional[LicenseWarning] = None
238
238
 
239
239
 
240
+ @dataclass
241
+ class ActiveUser:
242
+ login: str
243
+ contexts: List[str]
244
+
245
+
240
246
  @dataclass
241
247
  class TestLabel:
242
248
  key: str
@@ -268,6 +274,13 @@ class ProjectMember:
268
274
  roles: List[ProjectRole]
269
275
 
270
276
 
277
+ @dataclass
278
+ class UserInfo:
279
+ userKey: str
280
+ userLogin: str
281
+ userName: str
282
+
283
+
271
284
  @dataclass
272
285
  class ProjectSummary:
273
286
  key: str
@@ -567,7 +580,7 @@ class UserSummary:
567
580
 
568
581
  @dataclass
569
582
  class TestBenchVersions:
570
- releaseVersion: str
583
+ version: str
571
584
  databaseVersion: str
572
585
  revision: str
573
586
 
@@ -627,6 +640,49 @@ class RequirementAssignment:
627
640
  repositoryId: str
628
641
 
629
642
 
643
+ @dataclass
644
+ class ReportItemsSummary:
645
+ testThemesCount: int
646
+ testCaseSetsCount: int
647
+ testCasesCount: int
648
+
649
+
650
+ @dataclass
651
+ class ServerLocation:
652
+ host: str
653
+ port: int
654
+
655
+
656
+ @dataclass
657
+ class ReportExportOptions:
658
+ pass
659
+
660
+
661
+ @dataclass
662
+ class ReportScope:
663
+ projectKey: str
664
+ tovKey: str
665
+ cycleKey: Optional[str] = None
666
+
667
+
668
+ @dataclass
669
+ class ReportCreation:
670
+ creator: UserInfo
671
+ startDate: str
672
+ endDate: str
673
+ scope: ReportScope
674
+ exportOptions: ReportExportOptions
675
+ summary: ReportItemsSummary
676
+
677
+
678
+ @dataclass
679
+ class ReportMetaInformation:
680
+ formatVersion: str
681
+ serverLocation: ServerLocation
682
+ reportCreation: ReportCreation
683
+ serverVersions: TestBenchVersions
684
+
685
+
630
686
  @dataclass
631
687
  class RequirementReference:
632
688
  key: str
@@ -765,17 +821,6 @@ class TestCaseExecutionDetails:
765
821
  tester: Optional[UserReference] = None
766
822
 
767
823
 
768
- @dataclass
769
- class TestCaseSetDetails:
770
- key: str
771
- numbering: str
772
- uniqueID: str
773
- name: str
774
- spec: TestCaseSetSpecificationSummary
775
- testCases: List[TestCaseSummary]
776
- exec: Optional[TestCaseSetExecutionSummary] = None
777
-
778
-
779
824
  class KindOfDataType(Enum):
780
825
  Regular = 'Regular'
781
826
  Reference = 'Reference'
@@ -799,9 +844,22 @@ class ParameterDefinitionType(Enum):
799
844
  AtomicInstance = 'AtomicInstance'
800
845
 
801
846
 
847
+ @dataclass
848
+ class ParameterValue:
849
+ name: str
850
+ key: str
851
+ dtSequenceKeys: List[str]
852
+
853
+
854
+ @dataclass
855
+ class InstanceArrayValue:
856
+ name: str
857
+ isDefaultValue: bool
858
+
859
+
802
860
  class ParameterEvaluationType(Enum):
803
- CallByReference = 'CallByReference'
804
861
  CallByValue = 'CallByValue'
862
+ CallByReference = 'CallByReference'
805
863
  CallByReferenceMandatory = 'CallByReferenceMandatory'
806
864
 
807
865
 
@@ -849,7 +907,7 @@ class FilterInfo:
849
907
 
850
908
 
851
909
  @dataclass
852
- class TovStructureOptions:
910
+ class TovStructureOptions(ReportExportOptions):
853
911
  treeRootUID: Optional[str] = None
854
912
  suppressFilteredData: Optional[bool] = None
855
913
  suppressEmptyTestThemes: Optional[bool] = None
@@ -867,7 +925,7 @@ class CycleStructureOptions:
867
925
 
868
926
 
869
927
  @dataclass
870
- class CycleReportOptions:
928
+ class CycleReportOptions(ReportExportOptions):
871
929
  treeRootUID: Optional[str] = None
872
930
  executionMode: Optional[ExecutionMode] = None
873
931
  suppressFilteredData: Optional[bool] = None
@@ -1008,6 +1066,13 @@ class ExecutionImportingFailure(ExecutionImportingResult):
1008
1066
  error: ActionFailure
1009
1067
 
1010
1068
 
1069
+ @dataclass
1070
+ class CheckedInElement:
1071
+ elementName: str
1072
+ newlyCheckedIn: bool
1073
+ versionName: str
1074
+
1075
+
1011
1076
  @dataclass
1012
1077
  class TestCaseExecutionImportResult:
1013
1078
  key: str
@@ -1019,12 +1084,15 @@ class TestCaseExecutionImportResult:
1019
1084
 
1020
1085
 
1021
1086
  @dataclass
1022
- class ExecutionImportOptions:
1087
+ class CheckInData:
1088
+ comment: str
1089
+ label: Optional[str] = None
1090
+
1091
+
1092
+ @dataclass
1093
+ class ExecutionImportSimulationOptions:
1023
1094
  fileName: str
1024
1095
  treeRootUID: Optional[str] = None
1025
- useExistingDefect: Optional[bool] = None
1026
- discardTesterInformation: Optional[bool] = None
1027
- defaultTester: Optional[str] = None
1028
1096
  filters: Optional[List[FilterInfo]] = None
1029
1097
 
1030
1098
 
@@ -1033,6 +1101,14 @@ class UploadedFile:
1033
1101
  fileName: str
1034
1102
 
1035
1103
 
1104
+ @dataclass
1105
+ class TestStructureElement:
1106
+ key: str
1107
+ uniqueID: str
1108
+ name: str
1109
+ executionKey: str
1110
+
1111
+
1036
1112
  @dataclass
1037
1113
  class TestThemeExecution:
1038
1114
  key: str
@@ -1063,6 +1139,12 @@ class TestObjectVersionCSVReportOptions:
1063
1139
  characterEncoding: Optional[str] = None
1064
1140
 
1065
1141
 
1142
+ @dataclass
1143
+ class JWTResponse:
1144
+ accessToken: str
1145
+ expiresAt: str
1146
+
1147
+
1066
1148
  @dataclass
1067
1149
  class TestCycleCSVReportOptions:
1068
1150
  reportRootUID: Optional[str] = None
@@ -1261,12 +1343,73 @@ class InteractionCallExecution:
1261
1343
  tester: Optional[UserReference] = None
1262
1344
 
1263
1345
 
1346
+ class Permission(Enum):
1347
+ AccessSecuredData = 'AccessSecuredData'
1348
+ DeleteUserAccount = 'DeleteUserAccount'
1349
+ DeleteUserSession = 'DeleteUserSession'
1350
+ DownloadReportFile = 'DownloadReportFile'
1351
+ ImportExecutionResults = 'ImportExecutionResults'
1352
+ ModifyGlobalTestLabels = 'ModifyGlobalTestLabels'
1353
+ ModifyProjectDetails = 'ModifyProjectDetails'
1354
+ ModifyProjectUDFs = 'ModifyProjectUDFs'
1355
+ ModifySpecifications = 'ModifySpecifications'
1356
+ ModifySpecManagementInfo = 'ModifySpecManagementInfo'
1357
+ ModifySpecPriorityAndDueDate = 'ModifySpecPriorityAndDueDate'
1358
+ ModifyTestElements = 'ModifyTestElements'
1359
+ ModifyTestLabels = 'ModifyTestLabels'
1360
+ ModifyUserData = 'ModifyUserData'
1361
+ ModifyUserRolesInProject = 'ModifyUserRolesInProject'
1362
+ PrivatizeGlobalTestLabels = 'PrivatizeGlobalTestLabels'
1363
+ ReadActiveUsersList = 'ReadActiveUsersList'
1364
+ ReadCompleteProjectsList = 'ReadCompleteProjectsList'
1365
+ ReadCompleteUsersList = 'ReadCompleteUsersList'
1366
+ ReadCycleReport = 'ReadCycleReport'
1367
+ ReadCycleReportOverRMI = 'ReadCycleReportOverRMI'
1368
+ ReadCycleRequirements = 'ReadCycleRequirements'
1369
+ ReadDefectsMetricDistribution = 'ReadDefectsMetricDistribution'
1370
+ ReadExecutionImportingJobDetails = 'ReadExecutionImportingJobDetails'
1371
+ ReadInvisibleProjectContent = 'ReadInvisibleProjectContent'
1372
+ ReadOwnProjectsList = 'ReadOwnProjectsList'
1373
+ ReadOwnUserDetails = 'ReadOwnUserDetails'
1374
+ ReadProjectDefectsAndTheirAssignments = 'ReadProjectDefectsAndTheirAssignments'
1375
+ ReadProjectDetails = 'ReadProjectDetails'
1376
+ ReadProjectExportOverRMI = 'ReadProjectExportOverRMI'
1377
+ ReadProjectHierarchy = 'ReadProjectHierarchy'
1378
+ ReadProjectMembers = 'ReadProjectMembers'
1379
+ ReadProjectUDFs = 'ReadProjectUDFs'
1380
+ ReadReportingJobDetails = 'ReadReportingJobDetails'
1381
+ ReadTestCaseDetails = 'ReadTestCaseDetails'
1382
+ ReadTestCaseSetDetails = 'ReadTestCaseSetDetails'
1383
+ ReadTestElements = 'ReadTestElements'
1384
+ ReadTestLabels = 'ReadTestLabels'
1385
+ ReadTestThemeDetails = 'ReadTestThemeDetails'
1386
+ ReadTestThemeStatusDistribution = 'ReadTestThemeStatusDistribution'
1387
+ ReadTestThemeTree = 'ReadTestThemeTree'
1388
+ ReadTovReport = 'ReadTovReport'
1389
+ ReadTovReportOverRMI = 'ReadTovReportOverRMI'
1390
+ ReadTovRequirements = 'ReadTovRequirements'
1391
+ ReadUserDetails = 'ReadUserDetails'
1392
+ ReadUserMemberships = 'ReadUserMemberships'
1393
+ ReadUserSessions = 'ReadUserSessions'
1394
+ RestrictProjectUDFs = 'RestrictProjectUDFs'
1395
+ SynchronizeUsers = 'SynchronizeUsers'
1396
+ UnlockForeignSpecs = 'UnlockForeignSpecs'
1397
+ UnlockForeignTestElements = 'UnlockForeignTestElements'
1398
+
1399
+
1264
1400
  @dataclass
1265
1401
  class DefaultValue:
1266
1402
  name: str
1267
1403
  valueType: ArgumentValueType
1268
1404
 
1269
1405
 
1406
+ @dataclass
1407
+ class InteractionParameterForInsert:
1408
+ name: str
1409
+ dataTypeKey: Optional[str] = None
1410
+ evaluationType: Optional[ParameterEvaluationType] = None
1411
+
1412
+
1270
1413
  @dataclass
1271
1414
  class ParameterDetails:
1272
1415
  key: str
@@ -1322,14 +1465,10 @@ class ReferenceAssignment:
1322
1465
 
1323
1466
 
1324
1467
  @dataclass
1325
- class ParameterSummary:
1326
- definitionType: ParameterDefinitionType
1327
- key: str
1468
+ class RepresentativeValue:
1328
1469
  name: str
1329
- evaluationType: ParameterEvaluationType
1330
1470
  valueType: RepresentativeType
1331
- dataType: Optional[DataTypeSummary] = None
1332
- value: Optional[str] = None
1471
+ isDefaultValue: bool
1333
1472
 
1334
1473
 
1335
1474
  @dataclass
@@ -1425,11 +1564,34 @@ class ExecutionImportingCompletion:
1425
1564
  class TestCaseSetExecutionImportResult:
1426
1565
  key: str
1427
1566
  executionKey: str
1567
+ name: str
1568
+ uid: str
1428
1569
  finished: bool
1429
1570
  testCases: List[TestCaseExecutionImportResult]
1430
1571
  error: Optional[ActionFailure] = None
1431
1572
 
1432
1573
 
1574
+ @dataclass
1575
+ class ExecutionImportOptions:
1576
+ fileName: str
1577
+ treeRootUID: Optional[str] = None
1578
+ useExistingDefect: Optional[bool] = None
1579
+ discardTesterInformation: Optional[bool] = None
1580
+ defaultTester: Optional[str] = None
1581
+ filters: Optional[List[FilterInfo]] = None
1582
+ checkInData: Optional[CheckInData] = None
1583
+
1584
+
1585
+ @dataclass
1586
+ class JWTDataOptions:
1587
+ permissions: List[Permission]
1588
+ projectKey: Optional[str] = None
1589
+ tovKey: Optional[str] = None
1590
+ cycleKey: Optional[str] = None
1591
+ subject: Optional[str] = None
1592
+ expiresAfterSeconds: Optional[int] = None
1593
+
1594
+
1433
1595
  @dataclass
1434
1596
  class UDFPosition:
1435
1597
  after: Optional[AfterUDF] = None
@@ -1483,29 +1645,6 @@ class ImageInfo:
1483
1645
  value: ImageDetails
1484
1646
 
1485
1647
 
1486
- @dataclass
1487
- class InteractionCallSpecification:
1488
- key: str
1489
- interactionType: InteractionType
1490
- name: str
1491
- sequencePhase: SequencePhase
1492
- callType: InteractionCallType
1493
- comments: str
1494
- callParameters: List[ParameterSummary]
1495
- description: Optional[str] = None
1496
- interactionKey: Optional[str] = None
1497
- callingInteractionKey: Optional[str] = None
1498
-
1499
-
1500
- @dataclass
1501
- class InteractionCall:
1502
- sequenceID: str
1503
- numbering: str
1504
- spec: InteractionCallSpecification
1505
- parentID: Optional[str] = None
1506
- exec: Optional[InteractionCallExecution] = None
1507
-
1508
-
1509
1648
  @dataclass
1510
1649
  class InteractionDetails:
1511
1650
  key: str
@@ -1538,14 +1677,17 @@ class ProjectNode:
1538
1677
 
1539
1678
 
1540
1679
  @dataclass
1541
- class TestCaseDetails:
1542
- uniqueID: str
1543
- spec: TestCaseSpecificationDetails
1544
- testSequence: List[InteractionCall]
1545
- parameters: List[ParameterSummary]
1546
- interactions: List[InteractionDetails]
1547
- exec: Optional[TestCaseExecutionDetails] = None
1548
- origin: Optional[TestCaseDetailsOrigin] = None
1680
+ class ParameterSummary:
1681
+ definitionType: ParameterDefinitionType
1682
+ key: str
1683
+ name: str
1684
+ evaluationType: ParameterEvaluationType
1685
+ dataType: Optional[DataTypeSummary] = None
1686
+ value: Optional[str] = None
1687
+ valueType: Optional[RepresentativeType] = None
1688
+ representativeValue: Optional[RepresentativeValue] = None
1689
+ parameterValue: Optional[ParameterValue] = None
1690
+ instanceArrayValue: Optional[InstanceArrayValue] = None
1549
1691
 
1550
1692
 
1551
1693
  @dataclass
@@ -1571,6 +1713,8 @@ class ExecutionImportingJob:
1571
1713
  @dataclass
1572
1714
  class ExecutionImportingSuccess(ExecutionImportingResult):
1573
1715
  testCaseSets: List[TestCaseSetExecutionImportResult]
1716
+ checkedInTestStructureElements: List[TestStructureElement]
1717
+ checkedInTestElements: List[CheckedInElement]
1574
1718
 
1575
1719
 
1576
1720
  @dataclass
@@ -1589,6 +1733,40 @@ class RichTextInfo:
1589
1733
  images: List[ImageInfo]
1590
1734
 
1591
1735
 
1736
+ @dataclass
1737
+ class InteractionCallSpecification:
1738
+ key: str
1739
+ name: str
1740
+ sequencePhase: SequencePhase
1741
+ callType: InteractionCallType
1742
+ comments: str
1743
+ callParameters: List[ParameterSummary]
1744
+ interactionType: Optional[InteractionType] = None
1745
+ description: Optional[str] = None
1746
+ interactionKey: Optional[str] = None
1747
+ callingInteractionKey: Optional[str] = None
1748
+
1749
+
1750
+ @dataclass
1751
+ class InteractionCall:
1752
+ sequenceID: str
1753
+ numbering: str
1754
+ spec: InteractionCallSpecification
1755
+ parentID: Optional[str] = None
1756
+ exec: Optional[InteractionCallExecution] = None
1757
+
1758
+
1759
+ @dataclass
1760
+ class InteractionForInsert:
1761
+ parentKey: str
1762
+ name: str
1763
+ parameters: List[InteractionParameterForInsert]
1764
+ uid: Optional[str] = None
1765
+ description: Optional[RichTextInfo] = None
1766
+ advancedContent: Optional[AdvancedContent] = None
1767
+ callType: Optional[InteractionCallType] = None
1768
+
1769
+
1592
1770
  @dataclass
1593
1771
  class InteractionDetailsForUpdate:
1594
1772
  name: Optional[str] = None
@@ -1642,6 +1820,31 @@ class TOVForUpdate:
1642
1820
  cloningVisibility: Optional[bool] = None
1643
1821
 
1644
1822
 
1823
+ @dataclass
1824
+ class TestCaseSetDetails:
1825
+ key: str
1826
+ numbering: str
1827
+ uniqueID: str
1828
+ name: str
1829
+ spec: TestCaseSetSpecificationSummary
1830
+ testCases: List[TestCaseSummary]
1831
+ testSequence: List[InteractionCall]
1832
+ parameters: List[ParameterDetails]
1833
+ interactions: List[InteractionDetails]
1834
+ exec: Optional[TestCaseSetExecutionSummary] = None
1835
+
1836
+
1837
+ @dataclass
1838
+ class TestCaseDetails:
1839
+ uniqueID: str
1840
+ spec: TestCaseSpecificationDetails
1841
+ testSequence: List[InteractionCall]
1842
+ parameters: List[ParameterSummary]
1843
+ interactions: List[InteractionDetails]
1844
+ exec: Optional[TestCaseExecutionDetails] = None
1845
+ origin: Optional[TestCaseDetailsOrigin] = None
1846
+
1847
+
1645
1848
  @dataclass
1646
1849
  class CycleForUpdate:
1647
1850
  name: Optional[str] = None
@@ -97,7 +97,7 @@ class ResultWriter(ResultVisitor):
97
97
  self.itb_test_case_catalog: dict[str, TestCaseDetails] = {}
98
98
  self.phase_pattern = config.phasePattern
99
99
  self.test_chain: list[TestCase] = []
100
- self.main_protocol = from_dict(ExecutionImportingSuccess, {"testCaseSets": []})
100
+ self.main_protocol = from_dict(ExecutionImportingSuccess, {"testCaseSets": [], "checkedInTestStructureElements":[], "checkedInTestElements": []})
101
101
 
102
102
  def _create_artifact_storage(self):
103
103
  return ExecutionArtifactStorage(
@@ -454,7 +454,17 @@ class RfTestCase:
454
454
  return cbr_parameters
455
455
 
456
456
  def _get_interaction_import_prefix(self, interaction: RFInteractionCall) -> str:
457
- return (self.config.fully_qualified or False) * f"{interaction.import_prefix}."
457
+ for resource_regex in self.config.resource_regex:
458
+ if not interaction.import_prefix:
459
+ continue
460
+ resource_name_match = re.search(
461
+ resource_regex, interaction.import_prefix, flags=re.IGNORECASE
462
+ )
463
+ if resource_name_match:
464
+ return (
465
+ self.config.fully_qualified or False
466
+ ) * f"{resource_name_match.group('resourceName').strip()}."
467
+ return ""
458
468
 
459
469
  def _get_interaction_indent(self, interaction: RFInteractionCall) -> str:
460
470
  return (
@@ -711,15 +721,19 @@ class RobotSuiteFileBuilder:
711
721
  resource_name_index = self._get_resource_path_index(resource)
712
722
  cropped_interaction_path = []
713
723
  if resource_dir_index is None:
714
- return f"{resource_name}.resource"
715
- cropped_interaction_path.extend(
716
- splitted_interaction_path[resource_dir_index + 1 : resource_name_index]
717
- )
718
- resource_path = Path(
719
- self.config.resource_directory,
720
- *cropped_interaction_path,
721
- f"{resource_name}.resource",
722
- ).as_posix()
724
+ resource_path = Path(
725
+ self.config.resource_directory,
726
+ f"{resource_name}.resource",
727
+ ).as_posix()
728
+ else:
729
+ cropped_interaction_path.extend(
730
+ splitted_interaction_path[resource_dir_index + 1 : resource_name_index]
731
+ )
732
+ resource_path = Path(
733
+ self.config.resource_directory,
734
+ *cropped_interaction_path,
735
+ f"{resource_name}.resource",
736
+ ).as_posix()
723
737
  resource_path = self.config.subdivisionsMapping.resources.get(resource_name, resource_path)
724
738
  resource_path = re.sub(
725
739
  r"^{resourceDirectory}", self.config.resource_directory, resource_path
@@ -811,6 +825,21 @@ class RobotSuiteFileBuilder:
811
825
  setting_section.body.extend(self._create_rf_resource_imports(subdivisions))
812
826
  setting_section.body.extend(self._create_rf_unknown_imports(subdivisions))
813
827
  setting_section_meta_data = self.test_case_set.metadata
828
+ for md_name, md_expression in self.config.metadata.items():
829
+ from .utils import safe_eval
830
+ md_expression = re.sub(r"\$tcs", "tcs", md_expression)
831
+ try:
832
+ setting_section_meta_data[md_name] = safe_eval(
833
+ md_expression, {"tcs": self.test_case_set.details}
834
+ )
835
+ except ValueError as ve:
836
+ logger.warning(
837
+ f"Value '{md_expression}' from the custom metadata setting could not be evaluated: {ve}"
838
+ )
839
+ except Exception as e:
840
+ logger.error(
841
+ f"Error while evaluating the custom metadata setting '{md_expression}': {e}"
842
+ )
814
843
  setting_section.body.extend(
815
844
  [
816
845
  create_meta_data(metadata_name, metadata_value)
@@ -15,6 +15,7 @@ def testbench2robotframework(testbench_report: str, config: dict):
15
15
  setup_logger(configuration)
16
16
  logger.debug("Configuration loaded.")
17
17
  testbench_report = Path(testbench_report)
18
+ temp_dir = None
18
19
  try:
19
20
  if is_zip_file(testbench_report):
20
21
  temp_dir = tempfile.TemporaryDirectory(dir=Path.cwd())
@@ -41,6 +42,6 @@ def testbench2robotframework(testbench_report: str, config: dict):
41
42
  return
42
43
  write_test_suites(test_suites, configuration)
43
44
  except Exception as exception:
44
- if temp_dir:
45
+ if temp_dir is not None:
45
46
  temp_dir.cleanup()
46
47
  raise exception
@@ -1,3 +1,4 @@
1
+ import ast
1
2
  import re
2
3
  import shutil
3
4
  import sys
@@ -96,6 +97,57 @@ class PathResolver:
96
97
  return index.zfill(max_length)
97
98
 
98
99
 
100
+ def safe_eval(expr: str, names: dict):
101
+ tree = ast.parse(expr, mode="eval")
102
+ allowed_nodes = (
103
+ ast.Expression,
104
+ ast.Call,
105
+ ast.Attribute,
106
+ ast.Load,
107
+ ast.Name,
108
+ ast.ListComp,
109
+ ast.GeneratorExp,
110
+ ast.comprehension,
111
+ ast.List,
112
+ ast.Tuple,
113
+ ast.Constant,
114
+ ast.Subscript,
115
+ ast.JoinedStr,
116
+ ast.FormattedValue,
117
+ ast.BinOp,
118
+ ast.UnaryOp,
119
+ ast.Compare,
120
+ ast.BoolOp,
121
+ ast.Eq,
122
+ ast.NotEq,
123
+ ast.Gt,
124
+ ast.Lt,
125
+ ast.GtE,
126
+ ast.LtE,
127
+ ast.In,
128
+ ast.And,
129
+ ast.Or,
130
+ ast.Not,
131
+ ast.Add,
132
+ ast.Sub,
133
+ ast.Mult,
134
+ ast.Div,
135
+ ast.Mod,
136
+ ast.Store,
137
+ ast.keyword,
138
+ )
139
+ for node in ast.walk(tree):
140
+ if not isinstance(node, allowed_nodes):
141
+ raise ValueError(f"Disallowed expression: {type(node).__name__}")
142
+ if isinstance(node, ast.Attribute) and node.attr.startswith("_"):
143
+ raise ValueError(f"Access to private attribute {node.attr} is not allowed")
144
+ if isinstance(node, ast.Name) and node.id == "__import__":
145
+ raise ValueError("Use of __import__ is forbidden")
146
+
147
+ code = compile(tree, "<safe_eval>", "eval")
148
+ return eval(code, {"__builtins__": {}}, names)
149
+
150
+
99
151
  def get_directory(json_report_path: Optional[str]) -> str:
100
152
  if json_report_path is None:
101
153
  return ""