robotframework-openapitools 0.3.0__tar.gz → 0.4.0__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.
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/PKG-INFO +8 -7
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/pyproject.toml +9 -9
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/OpenApiDriver/openapi_executors.py +9 -4
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/OpenApiDriver/openapidriver.libspec +4 -4
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/OpenApiLibCore/dto_base.py +15 -6
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/OpenApiLibCore/openapi_libcore.libspec +43 -27
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/OpenApiLibCore/openapi_libcore.py +56 -3
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/LICENSE +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/docs/README.md +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/OpenApiDriver/__init__.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/OpenApiDriver/openapi_reader.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/OpenApiDriver/openapidriver.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/OpenApiDriver/py.typed +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/OpenApiLibCore/__init__.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/OpenApiLibCore/dto_utils.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/OpenApiLibCore/oas_cache.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/OpenApiLibCore/py.typed +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/OpenApiLibCore/value_utils.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/__init__.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/__main__.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/auth.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/cli.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/core.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/generate/__init__.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/generate/generate.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/generate/models/__init__.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/generate/models/api.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/generate/models/definition.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/generate/models/endpoint.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/generate/models/parameter.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/generate/models/response.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/generate/models/tag.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/generate/models/utils.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/generate/templates/api_init.jinja +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/generate/templates/models.jinja +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/generate/templates/paths.jinja +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/logger.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/validate/__init__.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/validate/core.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/validate/schema.py +0 -0
- {robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/validate/text_response.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: robotframework-openapitools
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.4.0
|
4
4
|
Summary: A set of Robot Framework libraries to test APIs for which the OAS is available.
|
5
5
|
Home-page: https://github.com/MarketSquare/robotframework-openapitools
|
6
6
|
License: Apache-2.0
|
@@ -18,18 +18,19 @@ Classifier: Programming Language :: Python :: 3.9
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.10
|
19
19
|
Classifier: Programming Language :: Python :: 3.11
|
20
20
|
Classifier: Programming Language :: Python :: 3.12
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
21
22
|
Classifier: Topic :: Software Development :: Testing
|
22
23
|
Classifier: Topic :: Software Development :: Testing :: Acceptance
|
23
24
|
Requires-Dist: Faker (>=23.1.0)
|
24
|
-
Requires-Dist: Jinja2 (>=3.1.2
|
25
|
+
Requires-Dist: Jinja2 (>=3.1.2)
|
25
26
|
Requires-Dist: black (>=24.1.0)
|
26
|
-
Requires-Dist: openapi-core (>=0.19.0
|
27
|
-
Requires-Dist: prance[cli] (>=23
|
28
|
-
Requires-Dist: requests (>=2.31.0
|
29
|
-
Requires-Dist: rich_click (>=1.7.0
|
27
|
+
Requires-Dist: openapi-core (>=0.19.0)
|
28
|
+
Requires-Dist: prance[cli] (>=23)
|
29
|
+
Requires-Dist: requests (>=2.31.0)
|
30
|
+
Requires-Dist: rich_click (>=1.7.0)
|
30
31
|
Requires-Dist: robotframework (>=6.0.0,!=7.0.0)
|
31
32
|
Requires-Dist: robotframework-datadriver (>=1.10.0)
|
32
|
-
Requires-Dist: rstr (>=3.2.0
|
33
|
+
Requires-Dist: rstr (>=3.2.0)
|
33
34
|
Description-Content-Type: text/markdown
|
34
35
|
|
35
36
|
# OpenApiTools for Robot Framework
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name="robotframework-openapitools"
|
3
|
-
version = "0.
|
3
|
+
version = "0.4.0"
|
4
4
|
description = "A set of Robot Framework libraries to test APIs for which the OAS is available."
|
5
5
|
license = "Apache-2.0"
|
6
6
|
authors = [
|
@@ -29,16 +29,16 @@ include = ["*.libspec"]
|
|
29
29
|
|
30
30
|
[tool.poetry.dependencies]
|
31
31
|
python = "^3.8"
|
32
|
-
robotframework = ">=6.0.0, !=7.0.0"
|
32
|
+
robotframework = {version = ">=6.0.0, !=7.0.0", allow-prereleases = false }
|
33
33
|
robotframework-datadriver = ">=1.10.0"
|
34
|
-
requests = "
|
35
|
-
prance = {version = "
|
34
|
+
requests = ">=2.31.0"
|
35
|
+
prance = {version = ">=23", extras = ["CLI"]}
|
36
36
|
Faker = ">=23.1.0"
|
37
|
-
rstr = "
|
38
|
-
openapi-core = "
|
39
|
-
rich_click = "
|
37
|
+
rstr = ">=3.2.0"
|
38
|
+
openapi-core = ">=0.19.0"
|
39
|
+
rich_click = ">=1.7.0"
|
40
40
|
black = ">=24.1.0"
|
41
|
-
Jinja2 = "
|
41
|
+
Jinja2 = ">=3.1.2"
|
42
42
|
|
43
43
|
[tool.poetry.group.dev.dependencies]
|
44
44
|
invoke = ">=2.2.0"
|
@@ -69,7 +69,7 @@ build-backend = "poetry.core.masonry.api"
|
|
69
69
|
[tool.coverage.run]
|
70
70
|
branch = true
|
71
71
|
parallel = true
|
72
|
-
source = ["src"]
|
72
|
+
source = ["src/OpenApiDriver", "src/OpenApiLibCore"]
|
73
73
|
|
74
74
|
[tool.coverage.report]
|
75
75
|
exclude_lines = [
|
@@ -118,8 +118,9 @@ class OpenApiExecutors(OpenApiLibCore): # pylint: disable=too-many-instance-att
|
|
118
118
|
Perform a request for the provided 'path' and 'method' where the url for
|
119
119
|
the `path` is invalidated.
|
120
120
|
|
121
|
-
This keyword will be `SKIPPED` if the path contains no parts
|
122
|
-
can be invalidated
|
121
|
+
This keyword will be `SKIPPED` if the path contains no parts
|
122
|
+
that can be invalidated and there is no mapping for a
|
123
|
+
PathPropertiesConstraint for the `expected_status_code`.
|
123
124
|
|
124
125
|
The optional `expected_status_code` parameter (default: 404) can be set to the
|
125
126
|
expected status code for APIs that do not return a 404 on invalid urls.
|
@@ -131,7 +132,11 @@ class OpenApiExecutors(OpenApiLibCore): # pylint: disable=too-many-instance-att
|
|
131
132
|
"""
|
132
133
|
valid_url: str = run_keyword("get_valid_url", path, method)
|
133
134
|
|
134
|
-
if not (
|
135
|
+
if not (
|
136
|
+
url := run_keyword(
|
137
|
+
"get_invalidated_url", valid_url, path, method, expected_status_code
|
138
|
+
)
|
139
|
+
):
|
135
140
|
raise SkipExecution(
|
136
141
|
f"Path {path} does not contain resource references that "
|
137
142
|
f"can be invalidated."
|
@@ -194,7 +199,7 @@ class OpenApiExecutors(OpenApiLibCore): # pylint: disable=too-many-instance-att
|
|
194
199
|
}
|
195
200
|
invalidation_keywords = []
|
196
201
|
|
197
|
-
if request_data.dto.
|
202
|
+
if request_data.dto.get_body_relations_for_error_code(status_code):
|
198
203
|
invalidation_keywords.append("get_invalid_json_data")
|
199
204
|
if request_data.dto.get_parameter_relations_for_error_code(status_code):
|
200
205
|
invalidation_keywords.append("get_invalidated_parameters")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
-
<keywordspec name="OpenApiDriver" type="LIBRARY" format="HTML" scope="SUITE" generated="2024-
|
3
|
-
<version>0.
|
2
|
+
<keywordspec name="OpenApiDriver" type="LIBRARY" format="HTML" scope="SUITE" generated="2024-12-04T12:16:37+00:00" specversion="6" source="/workspaces/robotframework-openapitools/src/OpenApiDriver/openapidriver.py" lineno="352">
|
3
|
+
<version>0.4.0</version>
|
4
4
|
<doc><p>Visit the <a href="https://github.com/MarketSquare/robotframework-openapidriver">library page</a> for an introduction and examples.</p></doc>
|
5
5
|
<tags>
|
6
6
|
</tags>
|
@@ -265,7 +265,7 @@
|
|
265
265
|
</init>
|
266
266
|
</inits>
|
267
267
|
<keywords>
|
268
|
-
<kw name="Test Endpoint" source="/workspaces/robotframework-openapitools/src/OpenApiDriver/openapi_executors.py" lineno="
|
268
|
+
<kw name="Test Endpoint" source="/workspaces/robotframework-openapitools/src/OpenApiDriver/openapi_executors.py" lineno="161">
|
269
269
|
<arguments repr="path: str, method: str, status_code: int">
|
270
270
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="path: str">
|
271
271
|
<name>path</name>
|
@@ -318,7 +318,7 @@
|
|
318
318
|
</arg>
|
319
319
|
</arguments>
|
320
320
|
<doc><p>Perform a request for the provided 'path' and 'method' where the url for the <a href="#type-Path" class="name">path</a> is invalidated.</p>
|
321
|
-
<p>This keyword will be <span class="name">SKIPPED</span> if the path contains no parts that can be invalidated
|
321
|
+
<p>This keyword will be <span class="name">SKIPPED</span> if the path contains no parts that can be invalidated and there is no mapping for a PathPropertiesConstraint for the <span class="name">expected_status_code</span>.</p>
|
322
322
|
<p>The optional <span class="name">expected_status_code</span> parameter (default: 404) can be set to the expected status code for APIs that do not return a 404 on invalid urls.</p>
|
323
323
|
<p>&gt; Note: Depending on API design, the url may be validated before or after validation of headers, query parameters and / or (json) body. By default, no parameters are send with the request. The <span class="name">require_body_for_invalid_url</span> parameter can be set to <span class="name">True</span> if needed.</p></doc>
|
324
324
|
<shortdoc>Perform a request for the provided 'path' and 'method' where the url for the `path` is invalidated.</shortdoc>
|
@@ -99,6 +99,8 @@ class PathPropertiesConstraint(ResourceRelation):
|
|
99
99
|
|
100
100
|
path: str
|
101
101
|
property_name: str = "id"
|
102
|
+
invalid_value: Any = NOT_SET
|
103
|
+
invalid_value_error_code: int = 422
|
102
104
|
error_code: int = 404
|
103
105
|
|
104
106
|
|
@@ -111,6 +113,7 @@ class PropertyValueConstraint(ResourceRelation):
|
|
111
113
|
invalid_value: Any = NOT_SET
|
112
114
|
invalid_value_error_code: int = 422
|
113
115
|
error_code: int = 422
|
116
|
+
treat_as_mandatory: bool = False
|
114
117
|
|
115
118
|
|
116
119
|
@dataclass
|
@@ -190,6 +193,14 @@ class Dto(ABC):
|
|
190
193
|
]
|
191
194
|
return relations
|
192
195
|
|
196
|
+
def get_body_relations_for_error_code(self, error_code: int) -> List[Relation]:
|
197
|
+
"""
|
198
|
+
Return the list of Relations associated with the given error_code that are
|
199
|
+
applicable to the body / payload of the request.
|
200
|
+
"""
|
201
|
+
all_relations = self.get_relations_for_error_code(error_code=error_code)
|
202
|
+
return [r for r in all_relations if not isinstance(r, PathPropertiesConstraint)]
|
203
|
+
|
193
204
|
def get_invalidated_data(
|
194
205
|
self,
|
195
206
|
schema: Dict[str, Any],
|
@@ -207,18 +218,16 @@ class Dto(ABC):
|
|
207
218
|
r for r in relations if not isinstance(r, PathPropertiesConstraint)
|
208
219
|
]
|
209
220
|
property_names = [r.property_name for r in relations]
|
210
|
-
if status_code == invalid_property_default_code:
|
221
|
+
if status_code == invalid_property_default_code and schema.get("properties"):
|
211
222
|
# add all properties defined in the schema, including optional properties
|
212
223
|
property_names.extend((schema["properties"].keys()))
|
213
|
-
# remove duplicates
|
214
|
-
property_names = list(set(property_names))
|
215
224
|
if not property_names:
|
216
225
|
raise ValueError(
|
217
226
|
f"No property can be invalidated to cause status_code {status_code}"
|
218
227
|
)
|
219
|
-
# shuffle the property_names so different properties on
|
220
|
-
# when rerunning the test
|
221
|
-
shuffle(property_names)
|
228
|
+
# Remove duplicates, then shuffle the property_names so different properties on
|
229
|
+
# the Dto are invalidated when rerunning the test.
|
230
|
+
shuffle(list(set(property_names)))
|
222
231
|
for property_name in property_names:
|
223
232
|
# if possible, invalidate a constraint but send otherwise valid data
|
224
233
|
id_dependencies = [
|
@@ -1,12 +1,12 @@
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
-
<keywordspec name="OpenApiLibCore" type="LIBRARY" format="HTML" scope="SUITE" generated="2024-
|
3
|
-
<version>0.
|
2
|
+
<keywordspec name="OpenApiLibCore" type="LIBRARY" format="HTML" scope="SUITE" generated="2024-12-04T12:16:36+00:00" specversion="6" source="/workspaces/robotframework-openapitools/src/OpenApiLibCore/openapi_libcore.py" lineno="457">
|
3
|
+
<version>0.4.0</version>
|
4
4
|
<doc><p>Main class providing the keywords and core logic to interact with an OpenAPI server.</p>
|
5
5
|
<p>Visit the <a href="https://github.com/MarketSquare/robotframework-openapi-libcore">library page</a> for an introduction.</p></doc>
|
6
6
|
<tags>
|
7
7
|
</tags>
|
8
8
|
<inits>
|
9
|
-
<init name="__init__" lineno="
|
9
|
+
<init name="__init__" lineno="465">
|
10
10
|
<arguments repr="source: str, origin: str = , base_path: str = , response_validation: ValidationLevel = WARN, disable_server_validation: bool = True, mappings_path: str | Path = , invalid_property_default_response: int = 422, default_id_property_name: str = id, faker_locale: str | List[str] | None = None, require_body_for_invalid_url: bool = False, recursion_limit: int = 1, recursion_default: Any = {}, username: str = , password: str = , security_token: str = , auth: AuthBase | None = None, cert: str | Tuple[str, str] | None = None, verify_tls: bool | str | None = True, extra_headers: Dict[str, str] | None = None, cookies: Dict[str, str] | RequestsCookieJar | None = None, proxies: Dict[str, str] | None = None">
|
11
11
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="source: str">
|
12
12
|
<name>source</name>
|
@@ -214,7 +214,7 @@
|
|
214
214
|
</init>
|
215
215
|
</inits>
|
216
216
|
<keywords>
|
217
|
-
<kw name="Authorized Request" lineno="
|
217
|
+
<kw name="Authorized Request" lineno="1731">
|
218
218
|
<arguments repr="url: str, method: str, params: Dict[str, Any] | None = None, headers: Dict[str, str] | None = None, json_data: Dict[str, Dict[str, JSON] | List[JSON] | str | int | float | bool | None] | List[Dict[str, JSON] | List[JSON] | str | int | float | bool | None] | str | int | float | bool | None = None, data: Any = None, files: Any = None">
|
219
219
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="url: str">
|
220
220
|
<name>url</name>
|
@@ -307,7 +307,7 @@
|
|
307
307
|
<p>&gt; Note: provided username / password or auth objects take precedence over token based security</p></doc>
|
308
308
|
<shortdoc>Perform a request using the security token or authentication set in the library.</shortdoc>
|
309
309
|
</kw>
|
310
|
-
<kw name="Ensure In Use" lineno="
|
310
|
+
<kw name="Ensure In Use" lineno="1635">
|
311
311
|
<arguments repr="url: str, resource_relation: IdReference">
|
312
312
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="url: str">
|
313
313
|
<name>url</name>
|
@@ -321,7 +321,7 @@
|
|
321
321
|
<doc><p>Ensure that the (right-most) <span class="name">id</span> of the resource referenced by the <span class="name">url</span> is used by the resource defined by the <span class="name">resource_relation</span>.</p></doc>
|
322
322
|
<shortdoc>Ensure that the (right-most) `id` of the resource referenced by the `url` is used by the resource defined by the `resource_relation`.</shortdoc>
|
323
323
|
</kw>
|
324
|
-
<kw name="Get Ids From Url" lineno="
|
324
|
+
<kw name="Get Ids From Url" lineno="984">
|
325
325
|
<arguments repr="url: str">
|
326
326
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="url: str">
|
327
327
|
<name>url</name>
|
@@ -334,7 +334,7 @@
|
|
334
334
|
<doc><p>Perform a GET request on the <span class="name">url</span> and return the list of resource <span class="name">ids</span> from the response.</p></doc>
|
335
335
|
<shortdoc>Perform a GET request on the `url` and return the list of resource `ids` from the response.</shortdoc>
|
336
336
|
</kw>
|
337
|
-
<kw name="Get Invalid Json Data" lineno="
|
337
|
+
<kw name="Get Invalid Json Data" lineno="1409">
|
338
338
|
<arguments repr="url: str, method: str, status_code: int, request_data: RequestData">
|
339
339
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="url: str">
|
340
340
|
<name>url</name>
|
@@ -361,7 +361,7 @@
|
|
361
361
|
<p>&gt; Note: applicable UniquePropertyValueConstraint and IdReference Relations are considered before changes to <span class="name">json_data</span> are made.</p></doc>
|
362
362
|
<shortdoc>Return `json_data` based on the `dto` on the `request_data` that will cause the provided `status_code` for the `method` operation on the `url`.</shortdoc>
|
363
363
|
</kw>
|
364
|
-
<kw name="Get Invalidated Parameters" lineno="
|
364
|
+
<kw name="Get Invalidated Parameters" lineno="1460">
|
365
365
|
<arguments repr="status_code: int, request_data: RequestData">
|
366
366
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="status_code: int">
|
367
367
|
<name>status_code</name>
|
@@ -385,22 +385,37 @@
|
|
385
385
|
<doc><p>Returns a version of <span class="name">params, headers</span> as present on <span class="name">request_data</span> that has been modified to cause the provided <span class="name">status_code</span>.</p></doc>
|
386
386
|
<shortdoc>Returns a version of `params, headers` as present on `request_data` that has been modified to cause the provided `status_code`.</shortdoc>
|
387
387
|
</kw>
|
388
|
-
<kw name="Get Invalidated Url" lineno="
|
389
|
-
<arguments repr="valid_url: str">
|
388
|
+
<kw name="Get Invalidated Url" lineno="1356">
|
389
|
+
<arguments repr="valid_url: str, path: str = , method: str = , expected_status_code: int = 404">
|
390
390
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="valid_url: str">
|
391
391
|
<name>valid_url</name>
|
392
392
|
<type name="str" typedoc="string"/>
|
393
393
|
</arg>
|
394
|
+
<arg kind="POSITIONAL_OR_NAMED" required="false" repr="path: str = ">
|
395
|
+
<name>path</name>
|
396
|
+
<type name="str" typedoc="string"/>
|
397
|
+
<default/>
|
398
|
+
</arg>
|
399
|
+
<arg kind="POSITIONAL_OR_NAMED" required="false" repr="method: str = ">
|
400
|
+
<name>method</name>
|
401
|
+
<type name="str" typedoc="string"/>
|
402
|
+
<default/>
|
403
|
+
</arg>
|
404
|
+
<arg kind="POSITIONAL_OR_NAMED" required="false" repr="expected_status_code: int = 404">
|
405
|
+
<name>expected_status_code</name>
|
406
|
+
<type name="int" typedoc="integer"/>
|
407
|
+
<default>404</default>
|
408
|
+
</arg>
|
394
409
|
</arguments>
|
395
410
|
<returntype name="Union" union="true">
|
396
411
|
<type name="str" typedoc="string"/>
|
397
412
|
<type name="None" typedoc="None"/>
|
398
413
|
</returntype>
|
399
|
-
<doc><p>Return an url with all the path parameters in the <span class="name">valid_url</span> replaced by a random UUID.</p>
|
414
|
+
<doc><p>Return an url with all the path parameters in the <span class="name">valid_url</span> replaced by a random UUID if no PathPropertiesConstraint is mapped for the <a href="#type-Path" class="name">path</a>, <span class="name">method</span> and <span class="name">expected_status_code</span>. If a PathPropertiesConstraint is mapped, the <span class="name">invalid_value</span> is returned.</p>
|
400
415
|
<p>Raises ValueError if the valid_url cannot be invalidated.</p></doc>
|
401
|
-
<shortdoc>Return an url with all the path parameters in the `valid_url` replaced by a random UUID.</shortdoc>
|
416
|
+
<shortdoc>Return an url with all the path parameters in the `valid_url` replaced by a random UUID if no PathPropertiesConstraint is mapped for the `path`, `method` and `expected_status_code`. If a PathPropertiesConstraint is mapped, the `invalid_value` is returned.</shortdoc>
|
402
417
|
</kw>
|
403
|
-
<kw name="Get Json Data For Dto Class" lineno="
|
418
|
+
<kw name="Get Json Data For Dto Class" lineno="1232">
|
404
419
|
<arguments repr="schema: Dict[str, Any], dto_class: Dto | Type[Dto], operation_id: str = ">
|
405
420
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="schema: Dict[str, Any]">
|
406
421
|
<name>schema</name>
|
@@ -434,7 +449,7 @@
|
|
434
449
|
<doc><p>Generate a valid (json-compatible) dict for all the <span class="name">dto_class</span> properties.</p></doc>
|
435
450
|
<shortdoc>Generate a valid (json-compatible) dict for all the `dto_class` properties.</shortdoc>
|
436
451
|
</kw>
|
437
|
-
<kw name="Get Json Data With Conflict" lineno="
|
452
|
+
<kw name="Get Json Data With Conflict" lineno="1679">
|
438
453
|
<arguments repr="url: str, method: str, dto: Dto, conflict_status_code: int">
|
439
454
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="url: str">
|
440
455
|
<name>url</name>
|
@@ -460,7 +475,7 @@
|
|
460
475
|
<doc><p>Return <span class="name">json_data</span> based on the <span class="name">UniquePropertyValueConstraint</span> that must be returned by the <span class="name">get_relations</span> implementation on the <span class="name">dto</span> for the given <span class="name">conflict_status_code</span>.</p></doc>
|
461
476
|
<shortdoc>Return `json_data` based on the `UniquePropertyValueConstraint` that must be returned by the `get_relations` implementation on the `dto` for the given `conflict_status_code`.</shortdoc>
|
462
477
|
</kw>
|
463
|
-
<kw name="Get Parameterized Endpoint From Url" lineno="
|
478
|
+
<kw name="Get Parameterized Endpoint From Url" lineno="1397">
|
464
479
|
<arguments repr="url: str">
|
465
480
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="url: str">
|
466
481
|
<name>url</name>
|
@@ -471,7 +486,7 @@
|
|
471
486
|
<doc><p>Return the endpoint as found in the <span class="name">paths</span> section based on the given <span class="name">url</span>.</p></doc>
|
472
487
|
<shortdoc>Return the endpoint as found in the `paths` section based on the given `url`.</shortdoc>
|
473
488
|
</kw>
|
474
|
-
<kw name="Get Request Data" lineno="
|
489
|
+
<kw name="Get Request Data" lineno="1024">
|
475
490
|
<arguments repr="endpoint: str, method: str">
|
476
491
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="endpoint: str">
|
477
492
|
<name>endpoint</name>
|
@@ -486,7 +501,7 @@
|
|
486
501
|
<doc><p>Return an object with valid request data for body, headers and query params.</p></doc>
|
487
502
|
<shortdoc>Return an object with valid request data for body, headers and query params.</shortdoc>
|
488
503
|
</kw>
|
489
|
-
<kw name="Get Valid Id For Endpoint" lineno="
|
504
|
+
<kw name="Get Valid Id For Endpoint" lineno="888">
|
490
505
|
<arguments repr="endpoint: str, method: str">
|
491
506
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="endpoint: str">
|
492
507
|
<name>endpoint</name>
|
@@ -506,7 +521,7 @@
|
|
506
521
|
<p>To prevent resource conflicts with other test cases, a new resource is created (POST) if possible.</p></doc>
|
507
522
|
<shortdoc>Support keyword that returns the `id` for an existing resource at `endpoint`.</shortdoc>
|
508
523
|
</kw>
|
509
|
-
<kw name="Get Valid Url" lineno="
|
524
|
+
<kw name="Get Valid Url" lineno="848">
|
510
525
|
<arguments repr="endpoint: str, method: str">
|
511
526
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="endpoint: str">
|
512
527
|
<name>endpoint</name>
|
@@ -523,7 +538,7 @@
|
|
523
538
|
<p>&gt; Note: if valid ids cannot be retrieved within the scope of the API, the <span class="name">PathPropertiesConstraint</span> Relation can be used. More information can be found <a href="https://marketsquare.github.io/robotframework-openapi-libcore/advanced_use.html">here</a>.</p></doc>
|
524
539
|
<shortdoc>This keyword returns a valid url for the given `endpoint` and `method`.</shortdoc>
|
525
540
|
</kw>
|
526
|
-
<kw name="Perform Validated Request" lineno="
|
541
|
+
<kw name="Perform Validated Request" lineno="1778">
|
527
542
|
<arguments repr="path: str, status_code: int, request_values: RequestValues, original_data: Dict[str, Any] | None = None">
|
528
543
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="path: str">
|
529
544
|
<name>path</name>
|
@@ -552,7 +567,7 @@
|
|
552
567
|
<doc><p>This keyword first calls the Authorized Request keyword, then the Validate Response keyword and finally validates, for <span class="name">DELETE</span> operations, whether the target resource was indeed deleted (OK response) or not (error responses).</p></doc>
|
553
568
|
<shortdoc>This keyword first calls the Authorized Request keyword, then the Validate Response keyword and finally validates, for `DELETE` operations, whether the target resource was indeed deleted (OK response) or not (error responses).</shortdoc>
|
554
569
|
</kw>
|
555
|
-
<kw name="Set Auth" lineno="
|
570
|
+
<kw name="Set Auth" lineno="703">
|
556
571
|
<arguments repr="auth: AuthBase">
|
557
572
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="auth: AuthBase">
|
558
573
|
<name>auth</name>
|
@@ -563,7 +578,7 @@
|
|
563
578
|
<p>After calling this keyword, subsequent requests will use the provided <span class="name">auth</span> instance.</p></doc>
|
564
579
|
<shortdoc>Set the `auth` used for authentication after the library is imported.</shortdoc>
|
565
580
|
</kw>
|
566
|
-
<kw name="Set Basic Auth" lineno="
|
581
|
+
<kw name="Set Basic Auth" lineno="691">
|
567
582
|
<arguments repr="username: str, password: str">
|
568
583
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="username: str">
|
569
584
|
<name>username</name>
|
@@ -578,7 +593,7 @@
|
|
578
593
|
<p>After calling this keyword, subsequent requests will use the provided credentials.</p></doc>
|
579
594
|
<shortdoc>Set the `username` and `password` used for basic authentication after the library is imported.</shortdoc>
|
580
595
|
</kw>
|
581
|
-
<kw name="Set Extra Headers" lineno="
|
596
|
+
<kw name="Set Extra Headers" lineno="713">
|
582
597
|
<arguments repr="extra_headers: Dict[str, str]">
|
583
598
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="extra_headers: Dict[str, str]">
|
584
599
|
<name>extra_headers</name>
|
@@ -592,7 +607,7 @@
|
|
592
607
|
<p>After calling this keyword, subsequent requests will use the provided <span class="name">extra_headers</span>.</p></doc>
|
593
608
|
<shortdoc>Set the `extra_headers` used in requests after the library is imported.</shortdoc>
|
594
609
|
</kw>
|
595
|
-
<kw name="Set Origin" lineno="
|
610
|
+
<kw name="Set Origin" lineno="668">
|
596
611
|
<arguments repr="origin: str">
|
597
612
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="origin: str">
|
598
613
|
<name>origin</name>
|
@@ -604,7 +619,7 @@
|
|
604
619
|
<p>In combination with OpenApiLibCore, the <span class="name">origin</span> can be used at any point to target another server that hosts an API that complies to the same OAS.</p></doc>
|
605
620
|
<shortdoc>Set the `origin` after the library is imported.</shortdoc>
|
606
621
|
</kw>
|
607
|
-
<kw name="Set Security Token" lineno="
|
622
|
+
<kw name="Set Security Token" lineno="682">
|
608
623
|
<arguments repr="security_token: str">
|
609
624
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="security_token: str">
|
610
625
|
<name>security_token</name>
|
@@ -615,7 +630,7 @@
|
|
615
630
|
<p>After calling this keyword, subsequent requests will use the provided token.</p></doc>
|
616
631
|
<shortdoc>Set the `security_token` after the library is imported.</shortdoc>
|
617
632
|
</kw>
|
618
|
-
<kw name="Validate Resource Properties" lineno="
|
633
|
+
<kw name="Validate Resource Properties" lineno="2019">
|
619
634
|
<arguments repr="resource: Dict[str, Any], schema: Dict[str, Any]">
|
620
635
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="resource: Dict[str, Any]">
|
621
636
|
<name>resource</name>
|
@@ -635,7 +650,7 @@
|
|
635
650
|
<doc><p>Validate that the <span class="name">resource</span> does not contain any properties that are not defined in the <span class="name">schema_properties</span>.</p></doc>
|
636
651
|
<shortdoc>Validate that the `resource` does not contain any properties that are not defined in the `schema_properties`.</shortdoc>
|
637
652
|
</kw>
|
638
|
-
<kw name="Validate Response" lineno="
|
653
|
+
<kw name="Validate Response" lineno="1852">
|
639
654
|
<arguments repr="path: str, response: Response, original_data: Dict[str, Any] | None = None">
|
640
655
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="path: str">
|
641
656
|
<name>path</name>
|
@@ -668,7 +683,7 @@
|
|
668
683
|
</ul></doc>
|
669
684
|
<shortdoc>Validate the `response` by performing the following validations: - validate the `response` against the openapi schema for the `endpoint` - validate that the response does not contain extra properties - validate that a href, if present, refers to the correct resource - validate that the value for a property that is in the response is equal to the property value that was send - validate that no `original_data` is preserved when performing a PUT operation - validate that a PATCH operation only updates the provided properties</shortdoc>
|
670
685
|
</kw>
|
671
|
-
<kw name="Validate Send Response" lineno="
|
686
|
+
<kw name="Validate Send Response" lineno="2137">
|
672
687
|
<arguments repr="response: Response, original_data: Dict[str, Any] | None = None">
|
673
688
|
<arg kind="POSITIONAL_OR_NAMED" required="true" repr="response: Response">
|
674
689
|
<name>response</name>
|
@@ -772,6 +787,7 @@
|
|
772
787
|
<usage>Authorized Request</usage>
|
773
788
|
<usage>Get Invalid Json Data</usage>
|
774
789
|
<usage>Get Invalidated Parameters</usage>
|
790
|
+
<usage>Get Invalidated Url</usage>
|
775
791
|
<usage>Get Json Data With Conflict</usage>
|
776
792
|
<usage>Get Valid Id For Endpoint</usage>
|
777
793
|
<usage>Perform Validated Request</usage>
|
@@ -378,7 +378,15 @@ class RequestData:
|
|
378
378
|
|
379
379
|
def get_required_properties_dict(self) -> Dict[str, Any]:
|
380
380
|
"""Get the json-compatible dto data containing only the required properties."""
|
381
|
-
|
381
|
+
relations = self.dto.get_relations()
|
382
|
+
mandatory_properties = [
|
383
|
+
relation.property_name
|
384
|
+
for relation in relations
|
385
|
+
if getattr(relation, "treat_as_mandatory", False)
|
386
|
+
]
|
387
|
+
required_properties: List[str] = self.dto_schema.get("required", [])
|
388
|
+
required_properties.extend(mandatory_properties)
|
389
|
+
|
382
390
|
required_properties_dict: Dict[str, Any] = {}
|
383
391
|
for key, value in (self.dto.as_dict()).items():
|
384
392
|
if key in required_properties:
|
@@ -414,16 +422,34 @@ class RequestData:
|
|
414
422
|
|
415
423
|
def get_required_params(self) -> Dict[str, str]:
|
416
424
|
"""Get the params dict containing only the required query parameters."""
|
425
|
+
relations = self.dto.get_parameter_relations()
|
426
|
+
mandatory_properties = [
|
427
|
+
relation.property_name
|
428
|
+
for relation in relations
|
429
|
+
if getattr(relation, "treat_as_mandatory", False)
|
430
|
+
]
|
431
|
+
mandatory_parameters = [p for p in mandatory_properties if p in self.parameters]
|
432
|
+
|
417
433
|
required_parameters = [
|
418
434
|
p.get("name") for p in self.parameters if p.get("required")
|
419
435
|
]
|
436
|
+
required_parameters.extend(mandatory_parameters)
|
420
437
|
return {k: v for k, v in self.params.items() if k in required_parameters}
|
421
438
|
|
422
439
|
def get_required_headers(self) -> Dict[str, str]:
|
423
440
|
"""Get the headers dict containing only the required headers."""
|
441
|
+
relations = self.dto.get_parameter_relations()
|
442
|
+
mandatory_properties = [
|
443
|
+
relation.property_name
|
444
|
+
for relation in relations
|
445
|
+
if getattr(relation, "treat_as_mandatory", False)
|
446
|
+
]
|
447
|
+
mandatory_parameters = [p for p in mandatory_properties if p in self.parameters]
|
448
|
+
|
424
449
|
required_parameters = [
|
425
450
|
p.get("name") for p in self.parameters if p.get("required")
|
426
451
|
]
|
452
|
+
required_parameters.extend(mandatory_parameters)
|
427
453
|
return {k: v for k, v in self.headers.items() if k in required_parameters}
|
428
454
|
|
429
455
|
|
@@ -1327,13 +1353,32 @@ class OpenApiLibCore: # pylint: disable=too-many-instance-attributes
|
|
1327
1353
|
return json_data
|
1328
1354
|
|
1329
1355
|
@keyword
|
1330
|
-
def get_invalidated_url(
|
1356
|
+
def get_invalidated_url(
|
1357
|
+
self,
|
1358
|
+
valid_url: str,
|
1359
|
+
path: str = "",
|
1360
|
+
method: str = "",
|
1361
|
+
expected_status_code: int = 404,
|
1362
|
+
) -> Optional[str]:
|
1331
1363
|
"""
|
1332
1364
|
Return an url with all the path parameters in the `valid_url` replaced by a
|
1333
|
-
random UUID
|
1365
|
+
random UUID if no PathPropertiesConstraint is mapped for the `path`, `method`
|
1366
|
+
and `expected_status_code`.
|
1367
|
+
If a PathPropertiesConstraint is mapped, the `invalid_value` is returned.
|
1334
1368
|
|
1335
1369
|
Raises ValueError if the valid_url cannot be invalidated.
|
1336
1370
|
"""
|
1371
|
+
dto_class = self.get_dto_class(endpoint=path, method=method)
|
1372
|
+
relations = dto_class.get_relations()
|
1373
|
+
paths = [
|
1374
|
+
p.invalid_value
|
1375
|
+
for p in relations
|
1376
|
+
if isinstance(p, PathPropertiesConstraint)
|
1377
|
+
and p.invalid_value_error_code == expected_status_code
|
1378
|
+
]
|
1379
|
+
if paths:
|
1380
|
+
url = f"{self.base_url}{choice(paths)}"
|
1381
|
+
return url
|
1337
1382
|
parameterized_endpoint = self.get_parameterized_endpoint_from_url(valid_url)
|
1338
1383
|
parameterized_url = self.base_url + parameterized_endpoint
|
1339
1384
|
valid_url_parts = list(reversed(valid_url.split("/")))
|
@@ -1377,6 +1422,9 @@ class OpenApiLibCore: # pylint: disable=too-many-instance-attributes
|
|
1377
1422
|
"""
|
1378
1423
|
method = method.lower()
|
1379
1424
|
data_relations = request_data.dto.get_relations_for_error_code(status_code)
|
1425
|
+
data_relations = [
|
1426
|
+
r for r in data_relations if not isinstance(r, PathPropertiesConstraint)
|
1427
|
+
]
|
1380
1428
|
if not data_relations:
|
1381
1429
|
if not request_data.dto_schema:
|
1382
1430
|
raise ValueError(
|
@@ -1873,6 +1921,11 @@ class OpenApiLibCore: # pylint: disable=too-many-instance-attributes
|
|
1873
1921
|
response_spec["content"][content_type]["schema"]
|
1874
1922
|
)
|
1875
1923
|
|
1924
|
+
response_types = response_schema.get("types")
|
1925
|
+
if response_types:
|
1926
|
+
# In case of oneOf / anyOf there can be multiple possible response types
|
1927
|
+
# which makes generic validation too complex
|
1928
|
+
return None
|
1876
1929
|
response_type = response_schema.get("type", "undefined")
|
1877
1930
|
if response_type not in ["object", "array"]:
|
1878
1931
|
self._validate_value_type(value=json_response, expected_type=response_type)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/OpenApiDriver/py.typed
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/OpenApiLibCore/py.typed
RENAMED
File without changes
|
File without changes
|
{robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/__init__.py
RENAMED
File without changes
|
{robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/__main__.py
RENAMED
File without changes
|
{robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/auth.py
RENAMED
File without changes
|
File without changes
|
{robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/core.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{robotframework_openapitools-0.3.0 → robotframework_openapitools-0.4.0}/src/roboswag/logger.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|