robotframework-openapitools 1.0.0b3__py3-none-any.whl → 1.0.0b5__py3-none-any.whl
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.
- OpenApiDriver/openapi_executors.py +15 -11
- OpenApiDriver/openapi_reader.py +12 -13
- OpenApiDriver/openapidriver.libspec +5 -42
- OpenApiLibCore/__init__.py +0 -2
- OpenApiLibCore/annotations.py +8 -1
- OpenApiLibCore/data_generation/__init__.py +0 -2
- OpenApiLibCore/data_generation/body_data_generation.py +54 -73
- OpenApiLibCore/data_generation/data_generation_core.py +75 -82
- OpenApiLibCore/data_invalidation.py +38 -25
- OpenApiLibCore/dto_base.py +48 -105
- OpenApiLibCore/dto_utils.py +31 -3
- OpenApiLibCore/localized_faker.py +88 -0
- OpenApiLibCore/models.py +723 -0
- OpenApiLibCore/openapi_libcore.libspec +48 -284
- OpenApiLibCore/openapi_libcore.py +54 -71
- OpenApiLibCore/parameter_utils.py +20 -14
- OpenApiLibCore/path_functions.py +10 -10
- OpenApiLibCore/path_invalidation.py +5 -7
- OpenApiLibCore/protocols.py +13 -5
- OpenApiLibCore/request_data.py +67 -102
- OpenApiLibCore/resource_relations.py +6 -5
- OpenApiLibCore/validation.py +50 -167
- OpenApiLibCore/value_utils.py +46 -358
- openapi_libgen/__init__.py +0 -46
- openapi_libgen/command_line.py +7 -19
- openapi_libgen/generator.py +84 -0
- openapi_libgen/parsing_utils.py +9 -5
- openapi_libgen/spec_parser.py +41 -114
- {robotframework_openapitools-1.0.0b3.dist-info → robotframework_openapitools-1.0.0b5.dist-info}/METADATA +2 -1
- robotframework_openapitools-1.0.0b5.dist-info/RECORD +40 -0
- robotframework_openapitools-1.0.0b3.dist-info/RECORD +0 -37
- {robotframework_openapitools-1.0.0b3.dist-info → robotframework_openapitools-1.0.0b5.dist-info}/LICENSE +0 -0
- {robotframework_openapitools-1.0.0b3.dist-info → robotframework_openapitools-1.0.0b5.dist-info}/WHEEL +0 -0
- {robotframework_openapitools-1.0.0b3.dist-info → robotframework_openapitools-1.0.0b5.dist-info}/entry_points.txt +0 -0
@@ -140,17 +140,23 @@ from robot.api.exceptions import FatalError
|
|
140
140
|
from robot.libraries.BuiltIn import BuiltIn
|
141
141
|
|
142
142
|
import OpenApiLibCore.data_generation as _data_generation
|
143
|
-
import OpenApiLibCore.data_invalidation as
|
144
|
-
import OpenApiLibCore.path_functions as
|
145
|
-
import OpenApiLibCore.path_invalidation as
|
146
|
-
import OpenApiLibCore.resource_relations as
|
147
|
-
import OpenApiLibCore.validation as
|
143
|
+
import OpenApiLibCore.data_invalidation as _data_invalidation
|
144
|
+
import OpenApiLibCore.path_functions as _path_functions
|
145
|
+
import OpenApiLibCore.path_invalidation as _path_invalidation
|
146
|
+
import OpenApiLibCore.resource_relations as _resource_relations
|
147
|
+
import OpenApiLibCore.validation as _validation
|
148
148
|
from OpenApiLibCore.annotations import JSON
|
149
149
|
from OpenApiLibCore.dto_base import Dto, IdReference
|
150
150
|
from OpenApiLibCore.dto_utils import (
|
151
151
|
DEFAULT_ID_PROPERTY_NAME,
|
152
152
|
get_dto_class,
|
153
153
|
get_id_property_name,
|
154
|
+
get_path_dto_class,
|
155
|
+
)
|
156
|
+
from OpenApiLibCore.localized_faker import FAKE
|
157
|
+
from OpenApiLibCore.models import (
|
158
|
+
OpenApiObject,
|
159
|
+
PathItemObject,
|
154
160
|
)
|
155
161
|
from OpenApiLibCore.oas_cache import PARSER_CACHE, CachedParser
|
156
162
|
from OpenApiLibCore.parameter_utils import (
|
@@ -159,11 +165,10 @@ from OpenApiLibCore.parameter_utils import (
|
|
159
165
|
)
|
160
166
|
from OpenApiLibCore.protocols import ResponseValidatorType
|
161
167
|
from OpenApiLibCore.request_data import RequestData, RequestValues
|
162
|
-
from OpenApiLibCore.value_utils import FAKE
|
163
168
|
|
164
169
|
run_keyword = BuiltIn().run_keyword
|
165
170
|
default_str_mapping: Mapping[str, str] = MappingProxyType({})
|
166
|
-
|
171
|
+
default_json_mapping: Mapping[str, JSON] = MappingProxyType({})
|
167
172
|
|
168
173
|
|
169
174
|
@library(scope="SUITE", doc_format="ROBOT")
|
@@ -180,7 +185,7 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
180
185
|
source: str,
|
181
186
|
origin: str = "",
|
182
187
|
base_path: str = "",
|
183
|
-
response_validation:
|
188
|
+
response_validation: _validation.ValidationLevel = _validation.ValidationLevel.WARN,
|
184
189
|
disable_server_validation: bool = True,
|
185
190
|
mappings_path: str | Path = "",
|
186
191
|
invalid_property_default_response: int = 422,
|
@@ -355,12 +360,18 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
355
360
|
self.get_dto_class = get_dto_class(
|
356
361
|
mappings_module_name=mappings_module_name
|
357
362
|
)
|
363
|
+
self.get_path_dto_class = get_path_dto_class(
|
364
|
+
mappings_module_name=mappings_module_name
|
365
|
+
)
|
358
366
|
self.get_id_property_name = get_id_property_name(
|
359
367
|
mappings_module_name=mappings_module_name
|
360
368
|
)
|
361
369
|
sys.path.pop()
|
362
370
|
else:
|
363
371
|
self.get_dto_class = get_dto_class(mappings_module_name="no mapping")
|
372
|
+
self.get_path_dto_class = get_path_dto_class(
|
373
|
+
mappings_module_name="no mapping"
|
374
|
+
)
|
364
375
|
self.get_id_property_name = get_id_property_name(
|
365
376
|
mappings_module_name="no mapping"
|
366
377
|
)
|
@@ -434,7 +445,7 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
434
445
|
self,
|
435
446
|
path: str,
|
436
447
|
method: str,
|
437
|
-
overrides: Mapping[str,
|
448
|
+
overrides: Mapping[str, JSON] = default_json_mapping,
|
438
449
|
) -> RequestValues:
|
439
450
|
"""Return an object with all (valid) request values needed to make a request."""
|
440
451
|
json_data: dict[str, JSON] = {}
|
@@ -482,24 +493,7 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
482
493
|
)
|
483
494
|
|
484
495
|
@keyword
|
485
|
-
def
|
486
|
-
self,
|
487
|
-
schema: dict[str, JSON],
|
488
|
-
dto_class: type[Dto],
|
489
|
-
operation_id: str = "",
|
490
|
-
) -> JSON:
|
491
|
-
"""
|
492
|
-
Generate valid (json-compatible) data for the `dto_class`.
|
493
|
-
"""
|
494
|
-
return _data_generation.get_json_data_for_dto_class(
|
495
|
-
schema=schema,
|
496
|
-
dto_class=dto_class,
|
497
|
-
get_id_property_name=self.get_id_property_name,
|
498
|
-
operation_id=operation_id,
|
499
|
-
)
|
500
|
-
|
501
|
-
@keyword
|
502
|
-
def get_invalid_json_data(
|
496
|
+
def get_invalid_body_data(
|
503
497
|
self,
|
504
498
|
url: str,
|
505
499
|
method: str,
|
@@ -513,7 +507,7 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
513
507
|
> Note: applicable UniquePropertyValueConstraint and IdReference Relations are
|
514
508
|
considered before changes to `json_data` are made.
|
515
509
|
"""
|
516
|
-
return
|
510
|
+
return _data_invalidation.get_invalid_body_data(
|
517
511
|
url=url,
|
518
512
|
method=method,
|
519
513
|
status_code=status_code,
|
@@ -526,12 +520,12 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
526
520
|
self,
|
527
521
|
status_code: int,
|
528
522
|
request_data: RequestData,
|
529
|
-
) -> tuple[dict[str, JSON], dict[str,
|
523
|
+
) -> tuple[dict[str, JSON], dict[str, JSON]]:
|
530
524
|
"""
|
531
525
|
Returns a version of `params, headers` as present on `request_data` that has
|
532
526
|
been modified to cause the provided `status_code`.
|
533
527
|
"""
|
534
|
-
return
|
528
|
+
return _data_invalidation.get_invalidated_parameters(
|
535
529
|
status_code=status_code,
|
536
530
|
request_data=request_data,
|
537
531
|
invalid_property_default_response=self.invalid_property_default_response,
|
@@ -546,7 +540,7 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
546
540
|
returned by the `get_relations` implementation on the `dto` for the given
|
547
541
|
`conflict_status_code`.
|
548
542
|
"""
|
549
|
-
return
|
543
|
+
return _data_invalidation.get_json_data_with_conflict(
|
550
544
|
url=url,
|
551
545
|
base_url=self.base_url,
|
552
546
|
method=method,
|
@@ -568,10 +562,10 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
568
562
|
`PathPropertiesConstraint` Relation can be used. More information can be found
|
569
563
|
[https://marketsquare.github.io/robotframework-openapitools/advanced_use.html | here].
|
570
564
|
"""
|
571
|
-
return
|
565
|
+
return _path_functions.get_valid_url(
|
572
566
|
path=path,
|
573
567
|
base_url=self.base_url,
|
574
|
-
|
568
|
+
get_path_dto_class=self.get_path_dto_class,
|
575
569
|
openapi_spec=self.openapi_spec,
|
576
570
|
)
|
577
571
|
|
@@ -583,7 +577,7 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
583
577
|
To prevent resource conflicts with other test cases, a new resource is created
|
584
578
|
(by a POST operation) if possible.
|
585
579
|
"""
|
586
|
-
return
|
580
|
+
return _path_functions.get_valid_id_for_path(
|
587
581
|
path=path, get_id_property_name=self.get_id_property_name
|
588
582
|
)
|
589
583
|
|
@@ -596,7 +590,7 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
596
590
|
path_parts = path.split("/")
|
597
591
|
# first part will be '' since a path starts with /
|
598
592
|
path_parts.pop(0)
|
599
|
-
parameterized_path =
|
593
|
+
parameterized_path = _path_functions.get_parametrized_path(
|
600
594
|
path=path, openapi_spec=self.openapi_spec
|
601
595
|
)
|
602
596
|
return parameterized_path
|
@@ -607,7 +601,7 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
607
601
|
Perform a GET request on the `url` and return the list of resource
|
608
602
|
`ids` from the response.
|
609
603
|
"""
|
610
|
-
return
|
604
|
+
return _path_functions.get_ids_from_url(
|
611
605
|
url=url, get_id_property_name=self.get_id_property_name
|
612
606
|
)
|
613
607
|
|
@@ -624,13 +618,13 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
624
618
|
on the mapped `path` and `expected_status_code`.
|
625
619
|
If a PathPropertiesConstraint is mapped, the `invalid_value` is returned.
|
626
620
|
|
627
|
-
Raises ValueError if the valid_url cannot be invalidated.
|
621
|
+
Raises: ValueError if the valid_url cannot be invalidated.
|
628
622
|
"""
|
629
|
-
return
|
623
|
+
return _path_invalidation.get_invalidated_url(
|
630
624
|
valid_url=valid_url,
|
631
625
|
path=path,
|
632
626
|
base_url=self.base_url,
|
633
|
-
|
627
|
+
get_path_dto_class=self.get_path_dto_class,
|
634
628
|
expected_status_code=expected_status_code,
|
635
629
|
)
|
636
630
|
|
@@ -642,7 +636,7 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
642
636
|
Ensure that the (right-most) `id` of the resource referenced by the `url`
|
643
637
|
is used by the resource defined by the `resource_relation`.
|
644
638
|
"""
|
645
|
-
|
639
|
+
_resource_relations.ensure_in_use(
|
646
640
|
url=url,
|
647
641
|
base_url=self.base_url,
|
648
642
|
openapi_spec=self.openapi_spec,
|
@@ -706,14 +700,14 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
706
700
|
path: str,
|
707
701
|
status_code: int,
|
708
702
|
request_values: RequestValues,
|
709
|
-
original_data: Mapping[str,
|
703
|
+
original_data: Mapping[str, JSON] = default_json_mapping,
|
710
704
|
) -> None:
|
711
705
|
"""
|
712
706
|
This keyword first calls the Authorized Request keyword, then the Validate
|
713
707
|
Response keyword and finally validates, for `DELETE` operations, whether
|
714
708
|
the target resource was indeed deleted (OK response) or not (error responses).
|
715
709
|
"""
|
716
|
-
|
710
|
+
_validation.perform_validated_request(
|
717
711
|
path=path,
|
718
712
|
status_code=status_code,
|
719
713
|
request_values=request_values,
|
@@ -726,7 +720,7 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
726
720
|
Validate the `response` against the OpenAPI Spec that is
|
727
721
|
loaded during library initialization.
|
728
722
|
"""
|
729
|
-
|
723
|
+
_validation.validate_response_using_validator(
|
730
724
|
response=response,
|
731
725
|
response_validator=self.response_validator,
|
732
726
|
)
|
@@ -739,7 +733,7 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
739
733
|
Attempt to GET the resource referenced by the `href` and validate it's equal
|
740
734
|
to the provided `referenced_resource` object / dictionary.
|
741
735
|
"""
|
742
|
-
|
736
|
+
_validation.assert_href_to_resource_is_valid(
|
743
737
|
href=href,
|
744
738
|
origin=self.origin,
|
745
739
|
base_url=self.base_url,
|
@@ -751,7 +745,7 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
751
745
|
self,
|
752
746
|
path: str,
|
753
747
|
response: Response,
|
754
|
-
original_data: Mapping[str,
|
748
|
+
original_data: Mapping[str, JSON] = default_json_mapping,
|
755
749
|
) -> None:
|
756
750
|
"""
|
757
751
|
Validate the `response` by performing the following validations:
|
@@ -763,7 +757,7 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
763
757
|
- validate that no `original_data` is preserved when performing a PUT operation
|
764
758
|
- validate that a PATCH operation only updates the provided properties
|
765
759
|
"""
|
766
|
-
|
760
|
+
_validation.validate_response(
|
767
761
|
path=path,
|
768
762
|
response=response,
|
769
763
|
response_validator=self.response_validator,
|
@@ -775,24 +769,11 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
775
769
|
original_data=original_data,
|
776
770
|
)
|
777
771
|
|
778
|
-
@keyword
|
779
|
-
def validate_resource_properties(
|
780
|
-
self, resource: dict[str, JSON], schema: dict[str, JSON]
|
781
|
-
) -> None:
|
782
|
-
"""
|
783
|
-
Validate that the `resource` does not contain any properties that are not
|
784
|
-
defined in the `schema_properties`.
|
785
|
-
"""
|
786
|
-
val.validate_resource_properties(
|
787
|
-
resource=resource,
|
788
|
-
schema=schema,
|
789
|
-
)
|
790
|
-
|
791
772
|
@staticmethod
|
792
773
|
@keyword
|
793
774
|
def validate_send_response(
|
794
775
|
response: Response,
|
795
|
-
original_data: Mapping[str,
|
776
|
+
original_data: Mapping[str, JSON] = default_json_mapping,
|
796
777
|
) -> None:
|
797
778
|
"""
|
798
779
|
Validate that each property that was send that is in the response has the value
|
@@ -800,7 +781,9 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
800
781
|
In case a PATCH request, validate that only the properties that were patched
|
801
782
|
have changed and that other properties are still at their pre-patch values.
|
802
783
|
"""
|
803
|
-
|
784
|
+
_validation.validate_send_response(
|
785
|
+
response=response, original_data=original_data
|
786
|
+
)
|
804
787
|
|
805
788
|
# endregion
|
806
789
|
|
@@ -818,17 +801,17 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
818
801
|
return validation_spec
|
819
802
|
|
820
803
|
@property
|
821
|
-
def openapi_spec(self) ->
|
804
|
+
def openapi_spec(self) -> OpenApiObject:
|
822
805
|
"""Return a deepcopy of the parsed openapi document."""
|
823
806
|
# protect the parsed openapi spec from being mutated by reference
|
824
807
|
return deepcopy(self._openapi_spec)
|
825
808
|
|
826
809
|
@cached_property
|
827
|
-
def _openapi_spec(self) ->
|
810
|
+
def _openapi_spec(self) -> OpenApiObject:
|
828
811
|
parser, _, _ = self._load_specs_and_validator()
|
829
|
-
|
830
|
-
register_path_parameters(
|
831
|
-
return
|
812
|
+
spec_model = OpenApiObject.model_validate(parser.specification)
|
813
|
+
register_path_parameters(spec_model.paths)
|
814
|
+
return spec_model
|
832
815
|
|
833
816
|
@cached_property
|
834
817
|
def response_validator(
|
@@ -870,7 +853,7 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
870
853
|
refstring: str, # pylint: disable=unused-argument
|
871
854
|
recursions: JSON, # pylint: disable=unused-argument
|
872
855
|
) -> JSON:
|
873
|
-
return self._recursion_default
|
856
|
+
return self._recursion_default # pragma: no cover
|
874
857
|
|
875
858
|
try:
|
876
859
|
# Since parsing of the OAS and creating the Spec can take a long time,
|
@@ -918,14 +901,14 @@ class OpenApiLibCore: # pylint: disable=too-many-public-methods
|
|
918
901
|
|
919
902
|
return parser, validation_spec, response_validator
|
920
903
|
|
921
|
-
except ResolutionError as exception:
|
904
|
+
except ResolutionError as exception: # pragma: no cover
|
922
905
|
raise FatalError(
|
923
906
|
f"ResolutionError while trying to load openapi spec: {exception}"
|
924
907
|
) from exception
|
925
|
-
except ValidationError as exception:
|
908
|
+
except ValidationError as exception: # pragma: no cover
|
926
909
|
raise FatalError(
|
927
910
|
f"ValidationError while trying to load openapi spec: {exception}"
|
928
911
|
) from exception
|
929
912
|
|
930
|
-
def read_paths(self) -> dict[str,
|
931
|
-
return self.openapi_spec
|
913
|
+
def read_paths(self) -> dict[str, PathItemObject]:
|
914
|
+
return self.openapi_spec.paths
|
@@ -5,7 +5,7 @@ names and the original names in the parsed OpenApi Specification document.
|
|
5
5
|
|
6
6
|
from typing import Generator
|
7
7
|
|
8
|
-
from OpenApiLibCore.
|
8
|
+
from OpenApiLibCore.models import ParameterObject, PathItemObject
|
9
9
|
|
10
10
|
PARAMETER_REGISTRY: dict[str, str] = {
|
11
11
|
"body": "body",
|
@@ -20,7 +20,7 @@ def get_oas_name_from_safe_name(safe_name: str) -> str:
|
|
20
20
|
|
21
21
|
|
22
22
|
def get_safe_name_for_oas_name(oas_name: str) -> str:
|
23
|
-
if
|
23
|
+
if _is_python_safe(oas_name):
|
24
24
|
PARAMETER_REGISTRY[oas_name] = oas_name
|
25
25
|
return oas_name
|
26
26
|
|
@@ -42,7 +42,7 @@ def get_safe_name_for_oas_name(oas_name: str) -> str:
|
|
42
42
|
return verbose_safe_name
|
43
43
|
|
44
44
|
|
45
|
-
def
|
45
|
+
def _is_python_safe(name: str) -> bool:
|
46
46
|
return name.isidentifier()
|
47
47
|
|
48
48
|
|
@@ -71,21 +71,27 @@ def convert_string_to_python_identifier(string: str, verbose: bool = False) -> s
|
|
71
71
|
ascii_code = ord(character)
|
72
72
|
yield f"_{ascii_code}_"
|
73
73
|
|
74
|
-
if
|
74
|
+
if _is_python_safe(string):
|
75
75
|
return string
|
76
76
|
|
77
77
|
converted_string = "".join(_convert_string_to_python_identifier())
|
78
|
-
if not
|
78
|
+
if not _is_python_safe(converted_string):
|
79
79
|
raise ValueError(f"Failed to convert '{string}' to Python identifier.")
|
80
80
|
return converted_string
|
81
81
|
|
82
82
|
|
83
|
-
def register_path_parameters(paths_data: dict[str,
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
for
|
91
|
-
|
83
|
+
def register_path_parameters(paths_data: dict[str, PathItemObject]) -> None:
|
84
|
+
def _register_path_parameter(parameter_object: ParameterObject) -> None:
|
85
|
+
if parameter_object.in_ == "path":
|
86
|
+
_ = get_safe_name_for_oas_name(parameter_object.name)
|
87
|
+
|
88
|
+
for path_item in paths_data.values():
|
89
|
+
if parameters := path_item.parameters:
|
90
|
+
for parameter in path_item.parameters:
|
91
|
+
_register_path_parameter(parameter_object=parameter)
|
92
|
+
|
93
|
+
operations = path_item.get_operations()
|
94
|
+
for operation in operations.values():
|
95
|
+
if parameters := operation.parameters:
|
96
|
+
for parameter in parameters:
|
97
|
+
_register_path_parameter(parameter_object=parameter)
|
OpenApiLibCore/path_functions.py
CHANGED
@@ -8,8 +8,8 @@ from typing import Any
|
|
8
8
|
from requests import Response
|
9
9
|
from robot.libraries.BuiltIn import BuiltIn
|
10
10
|
|
11
|
-
from OpenApiLibCore.
|
12
|
-
from OpenApiLibCore.protocols import
|
11
|
+
from OpenApiLibCore.models import OpenApiObject
|
12
|
+
from OpenApiLibCore.protocols import GetIdPropertyNameType, GetPathDtoClassType
|
13
13
|
from OpenApiLibCore.request_data import RequestData
|
14
14
|
|
15
15
|
run_keyword = BuiltIn().run_keyword
|
@@ -24,14 +24,14 @@ def match_parts(parts: list[str], spec_parts: list[str]) -> bool:
|
|
24
24
|
return True
|
25
25
|
|
26
26
|
|
27
|
-
def get_parametrized_path(path: str, openapi_spec:
|
27
|
+
def get_parametrized_path(path: str, openapi_spec: OpenApiObject) -> str:
|
28
28
|
path_parts = path.split("/")
|
29
29
|
# if the last part is empty, the path has a trailing `/` that
|
30
30
|
# should be ignored during matching
|
31
31
|
if path_parts[-1] == "":
|
32
32
|
_ = path_parts.pop(-1)
|
33
33
|
|
34
|
-
spec_paths: list[str] =
|
34
|
+
spec_paths: list[str] = list(openapi_spec.paths.keys())
|
35
35
|
|
36
36
|
candidates: list[str] = []
|
37
37
|
|
@@ -63,20 +63,20 @@ def get_parametrized_path(path: str, openapi_spec: dict[str, Any]) -> str:
|
|
63
63
|
def get_valid_url(
|
64
64
|
path: str,
|
65
65
|
base_url: str,
|
66
|
-
|
67
|
-
openapi_spec:
|
66
|
+
get_path_dto_class: GetPathDtoClassType,
|
67
|
+
openapi_spec: OpenApiObject,
|
68
68
|
) -> str:
|
69
69
|
try:
|
70
70
|
# path can be partially resolved or provided by a PathPropertiesConstraint
|
71
71
|
parametrized_path = get_parametrized_path(path=path, openapi_spec=openapi_spec)
|
72
|
-
_ = openapi_spec
|
72
|
+
_ = openapi_spec.paths[parametrized_path]
|
73
73
|
except KeyError:
|
74
74
|
raise ValueError(
|
75
75
|
f"{path} not found in paths section of the OpenAPI document."
|
76
76
|
) from None
|
77
|
-
dto_class =
|
78
|
-
relations = dto_class.
|
79
|
-
paths = [p.path for p in relations
|
77
|
+
dto_class = get_path_dto_class(path=path)
|
78
|
+
relations = dto_class.get_path_relations()
|
79
|
+
paths = [p.path for p in relations]
|
80
80
|
if paths:
|
81
81
|
url = f"{base_url}{choice(paths)}"
|
82
82
|
return url
|
@@ -5,8 +5,7 @@ from uuid import uuid4
|
|
5
5
|
|
6
6
|
from robot.libraries.BuiltIn import BuiltIn
|
7
7
|
|
8
|
-
from OpenApiLibCore.
|
9
|
-
from OpenApiLibCore.protocols import GetDtoClassType
|
8
|
+
from OpenApiLibCore.protocols import GetPathDtoClassType
|
10
9
|
|
11
10
|
run_keyword = BuiltIn().run_keyword
|
12
11
|
|
@@ -15,16 +14,15 @@ def get_invalidated_url(
|
|
15
14
|
valid_url: str,
|
16
15
|
path: str,
|
17
16
|
base_url: str,
|
18
|
-
|
17
|
+
get_path_dto_class: GetPathDtoClassType,
|
19
18
|
expected_status_code: int,
|
20
19
|
) -> str:
|
21
|
-
dto_class =
|
22
|
-
relations = dto_class.
|
20
|
+
dto_class = get_path_dto_class(path=path)
|
21
|
+
relations = dto_class.get_path_relations()
|
23
22
|
paths = [
|
24
23
|
p.invalid_value
|
25
24
|
for p in relations
|
26
|
-
if
|
27
|
-
and p.invalid_value_error_code == expected_status_code
|
25
|
+
if p.invalid_value_error_code == expected_status_code
|
28
26
|
]
|
29
27
|
if paths:
|
30
28
|
url = f"{base_url}{choice(paths)}"
|
OpenApiLibCore/protocols.py
CHANGED
@@ -13,18 +13,26 @@ from OpenApiLibCore.dto_base import Dto
|
|
13
13
|
class ResponseValidatorType(Protocol):
|
14
14
|
def __call__(
|
15
15
|
self, request: RequestsOpenAPIRequest, response: RequestsOpenAPIResponse
|
16
|
-
) -> None: ...
|
16
|
+
) -> None: ... # pragma: no cover
|
17
17
|
|
18
18
|
|
19
19
|
class GetDtoClassType(Protocol):
|
20
|
-
def __init__(self, mappings_module_name: str) -> None: ...
|
20
|
+
def __init__(self, mappings_module_name: str) -> None: ... # pragma: no cover
|
21
21
|
|
22
|
-
def __call__(self, path: str, method: str) -> Type[Dto]: ...
|
22
|
+
def __call__(self, path: str, method: str) -> Type[Dto]: ... # pragma: no cover
|
23
23
|
|
24
24
|
|
25
25
|
class GetIdPropertyNameType(Protocol):
|
26
|
-
def __init__(self, mappings_module_name: str) -> None: ...
|
26
|
+
def __init__(self, mappings_module_name: str) -> None: ... # pragma: no cover
|
27
27
|
|
28
28
|
def __call__(
|
29
29
|
self, path: str
|
30
|
-
) -> tuple[
|
30
|
+
) -> tuple[
|
31
|
+
str, Callable[[str], str] | Callable[[int], int]
|
32
|
+
]: ... # pragma: no cover
|
33
|
+
|
34
|
+
|
35
|
+
class GetPathDtoClassType(Protocol):
|
36
|
+
def __init__(self, mappings_module_name: str) -> None: ... # pragma: no cover
|
37
|
+
|
38
|
+
def __call__(self, path: str) -> Type[Dto]: ... # pragma: no cover
|