robotframework-openapitools 0.2.3__py3-none-any.whl → 0.3.0__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.
@@ -20,7 +20,7 @@ run_keyword = BuiltIn().run_keyword
20
20
  logger = getLogger(__name__)
21
21
 
22
22
 
23
- @library(scope="TEST SUITE", doc_format="ROBOT")
23
+ @library(scope="SUITE", doc_format="ROBOT")
24
24
  class OpenApiExecutors(OpenApiLibCore): # pylint: disable=too-many-instance-attributes
25
25
  """Main class providing the keywords and core logic to perform endpoint validations."""
26
26
 
@@ -52,9 +52,13 @@ class OpenApiExecutors(OpenApiLibCore): # pylint: disable=too-many-instance-att
52
52
  source=source,
53
53
  origin=origin,
54
54
  base_path=base_path,
55
+ response_validation=response_validation,
56
+ disable_server_validation=disable_server_validation,
55
57
  mappings_path=mappings_path,
56
58
  default_id_property_name=default_id_property_name,
59
+ invalid_property_default_response=invalid_property_default_response,
57
60
  faker_locale=faker_locale,
61
+ require_body_for_invalid_url=require_body_for_invalid_url,
58
62
  recursion_limit=recursion_limit,
59
63
  recursion_default=recursion_default,
60
64
  username=username,
@@ -67,10 +71,6 @@ class OpenApiExecutors(OpenApiLibCore): # pylint: disable=too-many-instance-att
67
71
  cookies=cookies,
68
72
  proxies=proxies,
69
73
  )
70
- self.response_validation = response_validation
71
- self.disable_server_validation = disable_server_validation
72
- self.require_body_for_invalid_url = require_body_for_invalid_url
73
- self.invalid_property_default_response = invalid_property_default_response
74
74
 
75
75
  @keyword
76
76
  def test_unauthorized(self, path: str, method: str) -> None:
@@ -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-06-20T15:30:31+00:00" specversion="6" source="/workspaces/robotframework-openapitools/src/OpenApiDriver/openapidriver.py" lineno="352">
3
- <version>0.2.3</version>
2
+ <keywordspec name="OpenApiDriver" type="LIBRARY" format="HTML" scope="SUITE" generated="2024-08-09T12:54:30+00:00" specversion="6" source="/workspaces/robotframework-openapitools/src/OpenApiDriver/openapidriver.py" lineno="352">
3
+ <version>0.3.0</version>
4
4
  <doc>&lt;p&gt;Visit the &lt;a href="https://github.com/MarketSquare/robotframework-openapidriver"&gt;library page&lt;/a&gt; for an introduction and examples.&lt;/p&gt;</doc>
5
5
  <tags>
6
6
  </tags>
@@ -134,7 +134,7 @@ from OpenApiDriver.openapi_executors import OpenApiExecutors, ValidationLevel
134
134
  from OpenApiDriver.openapi_reader import OpenApiReader
135
135
 
136
136
 
137
- @library(scope="TEST SUITE", doc_format="ROBOT")
137
+ @library(scope="SUITE", doc_format="ROBOT")
138
138
  class OpenApiDriver(OpenApiExecutors, DataDriver):
139
139
  """
140
140
  Visit the [https://github.com/MarketSquare/robotframework-openapidriver | library page]
@@ -1,13 +1,13 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
- <keywordspec name="OpenApiLibCore" type="LIBRARY" format="HTML" scope="SUITE" generated="2024-06-20T15:30:30+00:00" specversion="6" source="/workspaces/robotframework-openapitools/src/OpenApiLibCore/openapi_libcore.py" lineno="430">
3
- <version>0.2.3</version>
2
+ <keywordspec name="OpenApiLibCore" type="LIBRARY" format="HTML" scope="SUITE" generated="2024-08-09T12:54:30+00:00" specversion="6" source="/workspaces/robotframework-openapitools/src/OpenApiLibCore/openapi_libcore.py" lineno="431">
3
+ <version>0.3.0</version>
4
4
  <doc>&lt;p&gt;Main class providing the keywords and core logic to interact with an OpenAPI server.&lt;/p&gt;
5
5
  &lt;p&gt;Visit the &lt;a href="https://github.com/MarketSquare/robotframework-openapi-libcore"&gt;library page&lt;/a&gt; for an introduction.&lt;/p&gt;</doc>
6
6
  <tags>
7
7
  </tags>
8
8
  <inits>
9
- <init name="__init__" lineno="438">
10
- <arguments repr="source: str, origin: str = , base_path: str = , mappings_path: str | Path = , invalid_property_default_response: int = 422, default_id_property_name: str = id, faker_locale: str | List[str] | None = None, 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">
9
+ <init name="__init__" lineno="439">
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>
13
13
  <type name="str" typedoc="string"/>
@@ -22,6 +22,16 @@
22
22
  <type name="str" typedoc="string"/>
23
23
  <default/>
24
24
  </arg>
25
+ <arg kind="POSITIONAL_OR_NAMED" required="false" repr="response_validation: ValidationLevel = WARN">
26
+ <name>response_validation</name>
27
+ <type name="ValidationLevel" typedoc="ValidationLevel"/>
28
+ <default>WARN</default>
29
+ </arg>
30
+ <arg kind="POSITIONAL_OR_NAMED" required="false" repr="disable_server_validation: bool = True">
31
+ <name>disable_server_validation</name>
32
+ <type name="bool" typedoc="boolean"/>
33
+ <default>True</default>
34
+ </arg>
25
35
  <arg kind="POSITIONAL_OR_NAMED" required="false" repr="mappings_path: str | Path = ">
26
36
  <name>mappings_path</name>
27
37
  <type name="Union" union="true">
@@ -51,6 +61,11 @@
51
61
  </type>
52
62
  <default>None</default>
53
63
  </arg>
64
+ <arg kind="POSITIONAL_OR_NAMED" required="false" repr="require_body_for_invalid_url: bool = False">
65
+ <name>require_body_for_invalid_url</name>
66
+ <type name="bool" typedoc="boolean"/>
67
+ <default>False</default>
68
+ </arg>
54
69
  <arg kind="POSITIONAL_OR_NAMED" required="false" repr="recursion_limit: int = 1">
55
70
  <name>recursion_limit</name>
56
71
  <type name="int" typedoc="integer"/>
@@ -147,6 +162,17 @@
147
162
  &lt;p&gt;The server (and port) of the target server. E.g. &lt;code&gt;https://localhost:8000&lt;/code&gt;&lt;/p&gt;
148
163
  &lt;h4&gt;base_path&lt;/h4&gt;
149
164
  &lt;p&gt;The routing between &lt;code&gt;origin&lt;/code&gt; and the endpoints as found in the &lt;code&gt;paths&lt;/code&gt; section in the openapi document. E.g. &lt;code&gt;/petshop/v2&lt;/code&gt;.&lt;/p&gt;
165
+ &lt;h3&gt;Test case execution&lt;/h3&gt;
166
+ &lt;h4&gt;response_validation&lt;/h4&gt;
167
+ &lt;p&gt;By default, a &lt;code&gt;WARN&lt;/code&gt; is logged when the Response received after a Request does not comply with the schema as defined in the openapi document for the given operation. The following values are supported:&lt;/p&gt;
168
+ &lt;ul&gt;
169
+ &lt;li&gt;&lt;code&gt;DISABLED&lt;/code&gt;: All Response validation errors will be ignored&lt;/li&gt;
170
+ &lt;li&gt;&lt;code&gt;INFO&lt;/code&gt;: Any Response validation erros will be logged at &lt;code&gt;INFO&lt;/code&gt; level&lt;/li&gt;
171
+ &lt;li&gt;&lt;code&gt;WARN&lt;/code&gt;: Any Response validation erros will be logged at &lt;code&gt;WARN&lt;/code&gt; level&lt;/li&gt;
172
+ &lt;li&gt;&lt;code&gt;STRICT&lt;/code&gt;: The Test Case will fail on any Response validation errors&lt;/li&gt;
173
+ &lt;/ul&gt;
174
+ &lt;h4&gt;disable_server_validation&lt;/h4&gt;
175
+ &lt;p&gt;If enabled by setting this parameter to &lt;code&gt;True&lt;/code&gt;, the Response validation will also include possible errors for Requests made to a server address that is not defined in the list of servers in the openapi document. This generally means that if there is a mismatch, every Test Case will raise this error. Note that &lt;code&gt;localhost&lt;/code&gt; and &lt;code&gt;127.0.0.1&lt;/code&gt; are not considered the same by Response validation.&lt;/p&gt;
150
176
  &lt;h3&gt;API-specific configurations&lt;/h3&gt;
151
177
  &lt;h4&gt;mappings_path&lt;/h4&gt;
152
178
  &lt;p&gt;See &lt;a href="https://marketsquare.github.io/robotframework-openapi-libcore/advanced_use.html"&gt;this page&lt;/a&gt; for an in-depth explanation.&lt;/p&gt;
@@ -157,6 +183,8 @@
157
183
  &lt;p&gt;If different property names are used for the unique identifier for different types of resources, an &lt;code&gt;ID_MAPPING&lt;/code&gt; can be implemented using the &lt;code&gt;mappings_path&lt;/code&gt;.&lt;/p&gt;
158
184
  &lt;h4&gt;faker_locale&lt;/h4&gt;
159
185
  &lt;p&gt;A locale string or list of locale strings to pass to the Faker library to be used in generation of string data for supported format types.&lt;/p&gt;
186
+ &lt;h4&gt;require_body_for_invalid_url&lt;/h4&gt;
187
+ &lt;p&gt;When a request is made against an invalid url, this usually is because of a "404" request; a request for a resource that does not exist. Depending on API implementation, when a request with a missing or invalid request body is made on a non-existent resource, either a 404 or a 422 or 400 Response is normally returned. If the API being tested processes the request body before checking if the requested resource exists, set this parameter to True.&lt;/p&gt;
160
188
  &lt;h3&gt;Parsing parameters&lt;/h3&gt;
161
189
  &lt;h4&gt;recursion_limit&lt;/h4&gt;
162
190
  &lt;p&gt;The recursion depth to which to fully parse recursive references before the &lt;span class="name"&gt;recursion_default&lt;/span&gt; is used to end the recursion.&lt;/p&gt;
@@ -186,8 +214,8 @@
186
214
  </init>
187
215
  </inits>
188
216
  <keywords>
189
- <kw name="Authorized Request" lineno="1607">
190
- <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">
217
+ <kw name="Authorized Request" lineno="1683">
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">
191
219
  <arg kind="POSITIONAL_OR_NAMED" required="true" repr="url: str">
192
220
  <name>url</name>
193
221
  <type name="str" typedoc="string"/>
@@ -262,13 +290,24 @@
262
290
  </type>
263
291
  <default>None</default>
264
292
  </arg>
293
+ <arg kind="POSITIONAL_OR_NAMED" required="false" repr="data: Any = None">
294
+ <name>data</name>
295
+ <type name="Any" typedoc="Any"/>
296
+ <default>None</default>
297
+ </arg>
298
+ <arg kind="POSITIONAL_OR_NAMED" required="false" repr="files: Any = None">
299
+ <name>files</name>
300
+ <type name="Any" typedoc="Any"/>
301
+ <default>None</default>
302
+ </arg>
265
303
  </arguments>
266
304
  <returntype name="Response"/>
267
305
  <doc>&lt;p&gt;Perform a request using the security token or authentication set in the library.&lt;/p&gt;
306
+ &lt;p&gt;&lt;span class="name"&gt;json_data&lt;/span&gt;, &lt;span class="name"&gt;data&lt;/span&gt; and &lt;span class="name"&gt;files&lt;/span&gt; are passed to &lt;span class="name"&gt;requests.request&lt;/span&gt;s &lt;span class="name"&gt;json&lt;/span&gt;, &lt;span class="name"&gt;data&lt;/span&gt; and &lt;span class="name"&gt;files&lt;/span&gt; parameters unaltered. See the requests documentation for details: &lt;a href="https://requests.readthedocs.io/en/latest/api/#requests.request"&gt;https://requests.readthedocs.io/en/latest/api/#requests.request&lt;/a&gt;&lt;/p&gt;
268
307
  &lt;p&gt;&amp;gt; Note: provided username / password or auth objects take precedence over token based security&lt;/p&gt;</doc>
269
308
  <shortdoc>Perform a request using the security token or authentication set in the library.</shortdoc>
270
309
  </kw>
271
- <kw name="Ensure In Use" lineno="1511">
310
+ <kw name="Ensure In Use" lineno="1587">
272
311
  <arguments repr="url: str, resource_relation: IdReference">
273
312
  <arg kind="POSITIONAL_OR_NAMED" required="true" repr="url: str">
274
313
  <name>url</name>
@@ -282,7 +321,7 @@
282
321
  <doc>&lt;p&gt;Ensure that the (right-most) &lt;span class="name"&gt;id&lt;/span&gt; of the resource referenced by the &lt;span class="name"&gt;url&lt;/span&gt; is used by the resource defined by the &lt;span class="name"&gt;resource_relation&lt;/span&gt;.&lt;/p&gt;</doc>
283
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>
284
323
  </kw>
285
- <kw name="Get Ids From Url" lineno="882">
324
+ <kw name="Get Ids From Url" lineno="958">
286
325
  <arguments repr="url: str">
287
326
  <arg kind="POSITIONAL_OR_NAMED" required="true" repr="url: str">
288
327
  <name>url</name>
@@ -295,7 +334,7 @@
295
334
  <doc>&lt;p&gt;Perform a GET request on the &lt;span class="name"&gt;url&lt;/span&gt; and return the list of resource &lt;span class="name"&gt;ids&lt;/span&gt; from the response.&lt;/p&gt;</doc>
296
335
  <shortdoc>Perform a GET request on the `url` and return the list of resource `ids` from the response.</shortdoc>
297
336
  </kw>
298
- <kw name="Get Invalid Json Data" lineno="1288">
337
+ <kw name="Get Invalid Json Data" lineno="1364">
299
338
  <arguments repr="url: str, method: str, status_code: int, request_data: RequestData">
300
339
  <arg kind="POSITIONAL_OR_NAMED" required="true" repr="url: str">
301
340
  <name>url</name>
@@ -322,7 +361,7 @@
322
361
  &lt;p&gt;&amp;gt; Note: applicable UniquePropertyValueConstraint and IdReference Relations are considered before changes to &lt;span class="name"&gt;json_data&lt;/span&gt; are made.&lt;/p&gt;</doc>
323
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>
324
363
  </kw>
325
- <kw name="Get Invalidated Parameters" lineno="1336">
364
+ <kw name="Get Invalidated Parameters" lineno="1412">
326
365
  <arguments repr="status_code: int, request_data: RequestData">
327
366
  <arg kind="POSITIONAL_OR_NAMED" required="true" repr="status_code: int">
328
367
  <name>status_code</name>
@@ -346,7 +385,7 @@
346
385
  <doc>&lt;p&gt;Returns a version of &lt;span class="name"&gt;params, headers&lt;/span&gt; as present on &lt;span class="name"&gt;request_data&lt;/span&gt; that has been modified to cause the provided &lt;span class="name"&gt;status_code&lt;/span&gt;.&lt;/p&gt;</doc>
347
386
  <shortdoc>Returns a version of `params, headers` as present on `request_data` that has been modified to cause the provided `status_code`.</shortdoc>
348
387
  </kw>
349
- <kw name="Get Invalidated Url" lineno="1254">
388
+ <kw name="Get Invalidated Url" lineno="1330">
350
389
  <arguments repr="valid_url: str">
351
390
  <arg kind="POSITIONAL_OR_NAMED" required="true" repr="valid_url: str">
352
391
  <name>valid_url</name>
@@ -361,7 +400,7 @@
361
400
  &lt;p&gt;Raises ValueError if the valid_url cannot be invalidated.&lt;/p&gt;</doc>
362
401
  <shortdoc>Return an url with all the path parameters in the `valid_url` replaced by a random UUID.</shortdoc>
363
402
  </kw>
364
- <kw name="Get Json Data For Dto Class" lineno="1130">
403
+ <kw name="Get Json Data For Dto Class" lineno="1206">
365
404
  <arguments repr="schema: Dict[str, Any], dto_class: Dto | Type[Dto], operation_id: str = ">
366
405
  <arg kind="POSITIONAL_OR_NAMED" required="true" repr="schema: Dict[str, Any]">
367
406
  <name>schema</name>
@@ -395,7 +434,7 @@
395
434
  <doc>&lt;p&gt;Generate a valid (json-compatible) dict for all the &lt;span class="name"&gt;dto_class&lt;/span&gt; properties.&lt;/p&gt;</doc>
396
435
  <shortdoc>Generate a valid (json-compatible) dict for all the `dto_class` properties.</shortdoc>
397
436
  </kw>
398
- <kw name="Get Json Data With Conflict" lineno="1555">
437
+ <kw name="Get Json Data With Conflict" lineno="1631">
399
438
  <arguments repr="url: str, method: str, dto: Dto, conflict_status_code: int">
400
439
  <arg kind="POSITIONAL_OR_NAMED" required="true" repr="url: str">
401
440
  <name>url</name>
@@ -421,7 +460,7 @@
421
460
  <doc>&lt;p&gt;Return &lt;span class="name"&gt;json_data&lt;/span&gt; based on the &lt;span class="name"&gt;UniquePropertyValueConstraint&lt;/span&gt; that must be returned by the &lt;span class="name"&gt;get_relations&lt;/span&gt; implementation on the &lt;span class="name"&gt;dto&lt;/span&gt; for the given &lt;span class="name"&gt;conflict_status_code&lt;/span&gt;.&lt;/p&gt;</doc>
422
461
  <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>
423
462
  </kw>
424
- <kw name="Get Parameterized Endpoint From Url" lineno="1276">
463
+ <kw name="Get Parameterized Endpoint From Url" lineno="1352">
425
464
  <arguments repr="url: str">
426
465
  <arg kind="POSITIONAL_OR_NAMED" required="true" repr="url: str">
427
466
  <name>url</name>
@@ -432,7 +471,7 @@
432
471
  <doc>&lt;p&gt;Return the endpoint as found in the &lt;span class="name"&gt;paths&lt;/span&gt; section based on the given &lt;span class="name"&gt;url&lt;/span&gt;.&lt;/p&gt;</doc>
433
472
  <shortdoc>Return the endpoint as found in the `paths` section based on the given `url`.</shortdoc>
434
473
  </kw>
435
- <kw name="Get Request Data" lineno="922">
474
+ <kw name="Get Request Data" lineno="998">
436
475
  <arguments repr="endpoint: str, method: str">
437
476
  <arg kind="POSITIONAL_OR_NAMED" required="true" repr="endpoint: str">
438
477
  <name>endpoint</name>
@@ -447,7 +486,7 @@
447
486
  <doc>&lt;p&gt;Return an object with valid request data for body, headers and query params.&lt;/p&gt;</doc>
448
487
  <shortdoc>Return an object with valid request data for body, headers and query params.</shortdoc>
449
488
  </kw>
450
- <kw name="Get Valid Id For Endpoint" lineno="786">
489
+ <kw name="Get Valid Id For Endpoint" lineno="862">
451
490
  <arguments repr="endpoint: str, method: str">
452
491
  <arg kind="POSITIONAL_OR_NAMED" required="true" repr="endpoint: str">
453
492
  <name>endpoint</name>
@@ -467,7 +506,7 @@
467
506
  &lt;p&gt;To prevent resource conflicts with other test cases, a new resource is created (POST) if possible.&lt;/p&gt;</doc>
468
507
  <shortdoc>Support keyword that returns the `id` for an existing resource at `endpoint`.</shortdoc>
469
508
  </kw>
470
- <kw name="Get Valid Url" lineno="746">
509
+ <kw name="Get Valid Url" lineno="822">
471
510
  <arguments repr="endpoint: str, method: str">
472
511
  <arg kind="POSITIONAL_OR_NAMED" required="true" repr="endpoint: str">
473
512
  <name>endpoint</name>
@@ -484,7 +523,7 @@
484
523
  &lt;p&gt;&amp;gt; Note: if valid ids cannot be retrieved within the scope of the API, the &lt;span class="name"&gt;PathPropertiesConstraint&lt;/span&gt; Relation can be used. More information can be found &lt;a href="https://marketsquare.github.io/robotframework-openapi-libcore/advanced_use.html"&gt;here&lt;/a&gt;.&lt;/p&gt;</doc>
485
524
  <shortdoc>This keyword returns a valid url for the given `endpoint` and `method`.</shortdoc>
486
525
  </kw>
487
- <kw name="Perform Validated Request" lineno="1645">
526
+ <kw name="Perform Validated Request" lineno="1730">
488
527
  <arguments repr="path: str, status_code: int, request_values: RequestValues, original_data: Dict[str, Any] | None = None">
489
528
  <arg kind="POSITIONAL_OR_NAMED" required="true" repr="path: str">
490
529
  <name>path</name>
@@ -513,19 +552,70 @@
513
552
  <doc>&lt;p&gt;This keyword first calls the Authorized Request keyword, then the Validate Response keyword and finally validates, for &lt;span class="name"&gt;DELETE&lt;/span&gt; operations, whether the target resource was indeed deleted (OK response) or not (error responses).&lt;/p&gt;</doc>
514
553
  <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>
515
554
  </kw>
516
- <kw name="Set Origin" lineno="607">
555
+ <kw name="Set Auth" lineno="677">
556
+ <arguments repr="auth: AuthBase">
557
+ <arg kind="POSITIONAL_OR_NAMED" required="true" repr="auth: AuthBase">
558
+ <name>auth</name>
559
+ <type name="AuthBase"/>
560
+ </arg>
561
+ </arguments>
562
+ <doc>&lt;p&gt;Set the &lt;span class="name"&gt;auth&lt;/span&gt; used for authentication after the library is imported.&lt;/p&gt;
563
+ &lt;p&gt;After calling this keyword, subsequent requests will use the provided &lt;span class="name"&gt;auth&lt;/span&gt; instance.&lt;/p&gt;</doc>
564
+ <shortdoc>Set the `auth` used for authentication after the library is imported.</shortdoc>
565
+ </kw>
566
+ <kw name="Set Basic Auth" lineno="665">
567
+ <arguments repr="username: str, password: str">
568
+ <arg kind="POSITIONAL_OR_NAMED" required="true" repr="username: str">
569
+ <name>username</name>
570
+ <type name="str" typedoc="string"/>
571
+ </arg>
572
+ <arg kind="POSITIONAL_OR_NAMED" required="true" repr="password: str">
573
+ <name>password</name>
574
+ <type name="str" typedoc="string"/>
575
+ </arg>
576
+ </arguments>
577
+ <doc>&lt;p&gt;Set the &lt;span class="name"&gt;username&lt;/span&gt; and &lt;span class="name"&gt;password&lt;/span&gt; used for basic authentication after the library is imported.&lt;/p&gt;
578
+ &lt;p&gt;After calling this keyword, subsequent requests will use the provided credentials.&lt;/p&gt;</doc>
579
+ <shortdoc>Set the `username` and `password` used for basic authentication after the library is imported.</shortdoc>
580
+ </kw>
581
+ <kw name="Set Extra Headers" lineno="687">
582
+ <arguments repr="extra_headers: Dict[str, str]">
583
+ <arg kind="POSITIONAL_OR_NAMED" required="true" repr="extra_headers: Dict[str, str]">
584
+ <name>extra_headers</name>
585
+ <type name="Dict" typedoc="dictionary">
586
+ <type name="str" typedoc="string"/>
587
+ <type name="str" typedoc="string"/>
588
+ </type>
589
+ </arg>
590
+ </arguments>
591
+ <doc>&lt;p&gt;Set the &lt;span class="name"&gt;extra_headers&lt;/span&gt; used in requests after the library is imported.&lt;/p&gt;
592
+ &lt;p&gt;After calling this keyword, subsequent requests will use the provided &lt;span class="name"&gt;extra_headers&lt;/span&gt;.&lt;/p&gt;</doc>
593
+ <shortdoc>Set the `extra_headers` used in requests after the library is imported.</shortdoc>
594
+ </kw>
595
+ <kw name="Set Origin" lineno="642">
517
596
  <arguments repr="origin: str">
518
597
  <arg kind="POSITIONAL_OR_NAMED" required="true" repr="origin: str">
519
598
  <name>origin</name>
520
599
  <type name="str" typedoc="string"/>
521
600
  </arg>
522
601
  </arguments>
523
- <doc>&lt;p&gt;Update the &lt;span class="name"&gt;origin&lt;/span&gt; after the library is imported.&lt;/p&gt;
602
+ <doc>&lt;p&gt;Set the &lt;span class="name"&gt;origin&lt;/span&gt; after the library is imported.&lt;/p&gt;
524
603
  &lt;p&gt;This can be done during the &lt;span class="name"&gt;Suite setup&lt;/span&gt; when using DataDriver in situations where the OpenAPI document is available on disk but the target host address is not known before the test starts.&lt;/p&gt;
525
604
  &lt;p&gt;In combination with OpenApiLibCore, the &lt;span class="name"&gt;origin&lt;/span&gt; can be used at any point to target another server that hosts an API that complies to the same OAS.&lt;/p&gt;</doc>
526
- <shortdoc>Update the `origin` after the library is imported.</shortdoc>
605
+ <shortdoc>Set the `origin` after the library is imported.</shortdoc>
527
606
  </kw>
528
- <kw name="Validate Resource Properties" lineno="1871">
607
+ <kw name="Set Security Token" lineno="656">
608
+ <arguments repr="security_token: str">
609
+ <arg kind="POSITIONAL_OR_NAMED" required="true" repr="security_token: str">
610
+ <name>security_token</name>
611
+ <type name="str" typedoc="string"/>
612
+ </arg>
613
+ </arguments>
614
+ <doc>&lt;p&gt;Set the &lt;span class="name"&gt;security_token&lt;/span&gt; after the library is imported.&lt;/p&gt;
615
+ &lt;p&gt;After calling this keyword, subsequent requests will use the provided token.&lt;/p&gt;</doc>
616
+ <shortdoc>Set the `security_token` after the library is imported.</shortdoc>
617
+ </kw>
618
+ <kw name="Validate Resource Properties" lineno="1966">
529
619
  <arguments repr="resource: Dict[str, Any], schema: Dict[str, Any]">
530
620
  <arg kind="POSITIONAL_OR_NAMED" required="true" repr="resource: Dict[str, Any]">
531
621
  <name>resource</name>
@@ -545,7 +635,7 @@
545
635
  <doc>&lt;p&gt;Validate that the &lt;span class="name"&gt;resource&lt;/span&gt; does not contain any properties that are not defined in the &lt;span class="name"&gt;schema_properties&lt;/span&gt;.&lt;/p&gt;</doc>
546
636
  <shortdoc>Validate that the `resource` does not contain any properties that are not defined in the `schema_properties`.</shortdoc>
547
637
  </kw>
548
- <kw name="Validate Response" lineno="1719">
638
+ <kw name="Validate Response" lineno="1804">
549
639
  <arguments repr="path: str, response: Response, original_data: Dict[str, Any] | None = None">
550
640
  <arg kind="POSITIONAL_OR_NAMED" required="true" repr="path: str">
551
641
  <name>path</name>
@@ -578,7 +668,7 @@
578
668
  &lt;/ul&gt;</doc>
579
669
  <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>
580
670
  </kw>
581
- <kw name="Validate Send Response" lineno="1989">
671
+ <kw name="Validate Send Response" lineno="2084">
582
672
  <arguments repr="response: Response, original_data: Dict[str, Any] | None = None">
583
673
  <arg kind="POSITIONAL_OR_NAMED" required="true" repr="response: Response">
584
674
  <name>response</name>
@@ -649,6 +739,7 @@
649
739
  <usage>Get Json Data For Dto Class</usage>
650
740
  <usage>Get Json Data With Conflict</usage>
651
741
  <usage>Perform Validated Request</usage>
742
+ <usage>Set Extra Headers</usage>
652
743
  <usage>Validate Resource Properties</usage>
653
744
  <usage>Validate Response</usage>
654
745
  <usage>Validate Send Response</usage>
@@ -746,7 +837,10 @@
746
837
  <usage>Get Valid Id For Endpoint</usage>
747
838
  <usage>Get Valid Url</usage>
748
839
  <usage>Perform Validated Request</usage>
840
+ <usage>Set Basic Auth</usage>
841
+ <usage>Set Extra Headers</usage>
749
842
  <usage>Set Origin</usage>
843
+ <usage>Set Security Token</usage>
750
844
  <usage>Validate Resource Properties</usage>
751
845
  <usage>Validate Response</usage>
752
846
  <usage>Validate Send Response</usage>
@@ -765,5 +859,20 @@
765
859
  <usage>Get Invalidated Parameters</usage>
766
860
  </usages>
767
861
  </type>
862
+ <type name="ValidationLevel" type="Enum">
863
+ <doc>&lt;p&gt;The available levels for the response_validation parameter.&lt;/p&gt;</doc>
864
+ <accepts>
865
+ <type>string</type>
866
+ </accepts>
867
+ <usages>
868
+ <usage>__init__</usage>
869
+ </usages>
870
+ <members>
871
+ <member name="DISABLED" value="DISABLED"/>
872
+ <member name="INFO" value="INFO"/>
873
+ <member name="WARN" value="WARN"/>
874
+ <member name="STRICT" value="STRICT"/>
875
+ </members>
876
+ </type>
768
877
  </typedocs>
769
878
  </keywordspec>
@@ -149,6 +149,7 @@ from openapi_core.contrib.requests import (
149
149
  RequestsOpenAPIResponse,
150
150
  )
151
151
  from openapi_core.exceptions import OpenAPIError
152
+ from openapi_core.templating.paths.exceptions import ServerNotFound
152
153
  from openapi_core.validation.exceptions import ValidationError
153
154
  from openapi_core.validation.response.exceptions import ResponseValidationError
154
155
  from openapi_core.validation.schemas.exceptions import InvalidSchemaValue
@@ -157,8 +158,8 @@ from prance.util.url import ResolutionError
157
158
  from requests import Response, Session
158
159
  from requests.auth import AuthBase, HTTPBasicAuth
159
160
  from requests.cookies import RequestsCookieJar as CookieJar
160
- from robot.api import Failure
161
161
  from robot.api.deco import keyword, library
162
+ from robot.api.exceptions import Failure
162
163
  from robot.libraries.BuiltIn import BuiltIn
163
164
 
164
165
  from OpenApiLibCore import value_utils
@@ -426,7 +427,7 @@ class RequestData:
426
427
  return {k: v for k, v in self.headers.items() if k in required_parameters}
427
428
 
428
429
 
429
- @library(scope="TEST SUITE", doc_format="ROBOT")
430
+ @library(scope="SUITE", doc_format="ROBOT")
430
431
  class OpenApiLibCore: # pylint: disable=too-many-instance-attributes
431
432
  """
432
433
  Main class providing the keywords and core logic to interact with an OpenAPI server.
@@ -440,10 +441,13 @@ class OpenApiLibCore: # pylint: disable=too-many-instance-attributes
440
441
  source: str,
441
442
  origin: str = "",
442
443
  base_path: str = "",
444
+ response_validation: ValidationLevel = ValidationLevel.WARN,
445
+ disable_server_validation: bool = True,
443
446
  mappings_path: Union[str, Path] = "",
444
447
  invalid_property_default_response: int = 422,
445
448
  default_id_property_name: str = "id",
446
449
  faker_locale: Optional[Union[str, List[str]]] = None,
450
+ require_body_for_invalid_url: bool = False,
447
451
  recursion_limit: int = 1,
448
452
  recursion_default: Any = {},
449
453
  username: str = "",
@@ -470,6 +474,25 @@ class OpenApiLibCore: # pylint: disable=too-many-instance-attributes
470
474
  section in the openapi document.
471
475
  E.g. ``/petshop/v2``.
472
476
 
477
+ == Test case execution ==
478
+
479
+ === response_validation ===
480
+ By default, a ``WARN`` is logged when the Response received after a Request does not
481
+ comply with the schema as defined in the openapi document for the given operation. The
482
+ following values are supported:
483
+
484
+ - ``DISABLED``: All Response validation errors will be ignored
485
+ - ``INFO``: Any Response validation erros will be logged at ``INFO`` level
486
+ - ``WARN``: Any Response validation erros will be logged at ``WARN`` level
487
+ - ``STRICT``: The Test Case will fail on any Response validation errors
488
+
489
+ === disable_server_validation ===
490
+ If enabled by setting this parameter to ``True``, the Response validation will also
491
+ include possible errors for Requests made to a server address that is not defined in
492
+ the list of servers in the openapi document. This generally means that if there is a
493
+ mismatch, every Test Case will raise this error. Note that ``localhost`` and
494
+ ``127.0.0.1`` are not considered the same by Response validation.
495
+
473
496
  == API-specific configurations ==
474
497
 
475
498
  === mappings_path ===
@@ -496,6 +519,14 @@ class OpenApiLibCore: # pylint: disable=too-many-instance-attributes
496
519
  A locale string or list of locale strings to pass to the Faker library to be
497
520
  used in generation of string data for supported format types.
498
521
 
522
+ === require_body_for_invalid_url ===
523
+ When a request is made against an invalid url, this usually is because of a "404" request;
524
+ a request for a resource that does not exist. Depending on API implementation, when a
525
+ request with a missing or invalid request body is made on a non-existent resource,
526
+ either a 404 or a 422 or 400 Response is normally returned. If the API being tested
527
+ processes the request body before checking if the requested resource exists, set
528
+ this parameter to True.
529
+
499
530
  == Parsing parameters ==
500
531
 
501
532
  === recursion_limit ===
@@ -552,6 +583,8 @@ class OpenApiLibCore: # pylint: disable=too-many-instance-attributes
552
583
  self._source = source
553
584
  self._origin = origin
554
585
  self._base_path = base_path
586
+ self.response_validation = response_validation
587
+ self.disable_server_validation = disable_server_validation
555
588
  self._recursion_limit = recursion_limit
556
589
  self._recursion_default = recursion_default
557
590
  self.session = Session()
@@ -559,7 +592,7 @@ class OpenApiLibCore: # pylint: disable=too-many-instance-attributes
559
592
  # if multiple are provided, username and password take precedence
560
593
  self.security_token = security_token
561
594
  self.auth = auth
562
- if username and password:
595
+ if username:
563
596
  self.auth = HTTPBasicAuth(username, password)
564
597
  # Robot Framework does not allow users to create tuples and requests
565
598
  # does not accept lists, so perform the conversion here
@@ -596,8 +629,10 @@ class OpenApiLibCore: # pylint: disable=too-many-instance-attributes
596
629
  )
597
630
  if faker_locale:
598
631
  FAKE.set_locale(locale=faker_locale)
632
+ self.require_body_for_invalid_url = require_body_for_invalid_url
599
633
  # update the globally available DEFAULT_ID_PROPERTY_NAME to the provided value
600
634
  DEFAULT_ID_PROPERTY_NAME.id_property_name = default_id_property_name
635
+ self._server_validation_warning_logged = False
601
636
 
602
637
  @property
603
638
  def origin(self) -> str:
@@ -606,7 +641,7 @@ class OpenApiLibCore: # pylint: disable=too-many-instance-attributes
606
641
  @keyword
607
642
  def set_origin(self, origin: str) -> None:
608
643
  """
609
- Update the `origin` after the library is imported.
644
+ Set the `origin` after the library is imported.
610
645
 
611
646
  This can be done during the `Suite setup` when using DataDriver in situations
612
647
  where the OpenAPI document is available on disk but the target host address is
@@ -617,6 +652,47 @@ class OpenApiLibCore: # pylint: disable=too-many-instance-attributes
617
652
  """
618
653
  self._origin = origin
619
654
 
655
+ @keyword
656
+ def set_security_token(self, security_token: str) -> None:
657
+ """
658
+ Set the `security_token` after the library is imported.
659
+
660
+ After calling this keyword, subsequent requests will use the provided token.
661
+ """
662
+ self.security_token = security_token
663
+
664
+ @keyword
665
+ def set_basic_auth(self, username: str, password: str) -> None:
666
+ """
667
+ Set the `username` and `password` used for basic
668
+ authentication after the library is imported.
669
+
670
+ After calling this keyword, subsequent requests
671
+ will use the provided credentials.
672
+ """
673
+ if username:
674
+ self.auth = HTTPBasicAuth(username, password)
675
+
676
+ @keyword
677
+ def set_auth(self, auth: AuthBase) -> None:
678
+ """
679
+ Set the `auth` used for authentication after the library is imported.
680
+
681
+ After calling this keyword, subsequent requests
682
+ will use the provided `auth` instance.
683
+ """
684
+ self.auth = auth
685
+
686
+ @keyword
687
+ def set_extra_headers(self, extra_headers: Dict[str, str]) -> None:
688
+ """
689
+ Set the `extra_headers` used in requests after the library is imported.
690
+
691
+ After calling this keyword, subsequent requests
692
+ will use the provided `extra_headers`.
693
+ """
694
+ self.extra_headers = extra_headers
695
+
620
696
  @property
621
697
  def base_url(self) -> str:
622
698
  return f"{self.origin}{self._base_path}"
@@ -1611,10 +1687,17 @@ class OpenApiLibCore: # pylint: disable=too-many-instance-attributes
1611
1687
  params: Optional[Dict[str, Any]] = None,
1612
1688
  headers: Optional[Dict[str, str]] = None,
1613
1689
  json_data: Optional[JSON] = None,
1690
+ data: Any = None,
1691
+ files: Any = None,
1614
1692
  ) -> Response:
1615
1693
  """
1616
1694
  Perform a request using the security token or authentication set in the library.
1617
1695
 
1696
+ `json_data`, `data` and `files` are passed to `requests.request`s `json`,
1697
+ `data` and `files` parameters unaltered.
1698
+ See the requests documentation for details:
1699
+ https://requests.readthedocs.io/en/latest/api/#requests.request
1700
+
1618
1701
  > Note: provided username / password or auth objects take precedence over token
1619
1702
  based security
1620
1703
  """
@@ -1632,6 +1715,8 @@ class OpenApiLibCore: # pylint: disable=too-many-instance-attributes
1632
1715
  params=params,
1633
1716
  headers=headers,
1634
1717
  json=json_data,
1718
+ data=data,
1719
+ files=files,
1635
1720
  cookies=self.cookies,
1636
1721
  auth=self.auth,
1637
1722
  proxies=self.proxies,
@@ -1841,7 +1926,7 @@ class OpenApiLibCore: # pylint: disable=too-many-instance-attributes
1841
1926
  request=RequestsOpenAPIRequest(response.request),
1842
1927
  response=RequestsOpenAPIResponse(response),
1843
1928
  )
1844
- except ResponseValidationError as exception:
1929
+ except (ResponseValidationError, ServerNotFound) as exception:
1845
1930
  errors: List[InvalidSchemaValue] = exception.__cause__
1846
1931
  validation_errors: Optional[List[ValidationError]] = getattr(
1847
1932
  errors, "schema_errors", None
@@ -1856,6 +1941,16 @@ class OpenApiLibCore: # pylint: disable=too-many-instance-attributes
1856
1941
  else:
1857
1942
  error_message = str(exception)
1858
1943
 
1944
+ if isinstance(exception, ServerNotFound):
1945
+ if not self._server_validation_warning_logged:
1946
+ logger.warning(
1947
+ f"ServerNotFound was raised during response validation. "
1948
+ f"Due to this, no full response validation will be performed."
1949
+ f"\nThe original error was: {error_message}"
1950
+ )
1951
+ self._server_validation_warning_logged = True
1952
+ if self.disable_server_validation:
1953
+ return
1859
1954
  if response.status_code == self.invalid_property_default_response:
1860
1955
  logger.debug(error_message)
1861
1956
  return
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: robotframework-openapitools
3
- Version: 0.2.3
3
+ Version: 0.3.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
@@ -1,15 +1,15 @@
1
1
  OpenApiDriver/__init__.py,sha256=34h5RkB8nBNRKPId4r_B_xzcgXJYD3m2QYwIaPfpv80,1331
2
- OpenApiDriver/openapi_executors.py,sha256=7zjvMzkKY-IknTWZABZZoMNguMqXVn3gNiiljDQ9VyQ,12260
2
+ OpenApiDriver/openapi_executors.py,sha256=g7DsTRYC37LQm816U8Y3jy4_VjKighdAGqwgjcm_HnY,12247
3
3
  OpenApiDriver/openapi_reader.py,sha256=4kSM-hFd54ws-jq88inbienkaoC5sSDwfRuxLrHP7aA,4652
4
- OpenApiDriver/openapidriver.libspec,sha256=olRvV7rb60qyB9LFbcVUc0Sn0mBTS8ja3bcfuf8soYI,27059
5
- OpenApiDriver/openapidriver.py,sha256=QRFcF1q9x88rqsD7XzBN25wPYqTbZldK4rSvpEdhQHo,15214
4
+ OpenApiDriver/openapidriver.libspec,sha256=4GkssGoKEPcBK1ORo3O2QNPpqpkuOrz_Oki0r1WsPio,27059
5
+ OpenApiDriver/openapidriver.py,sha256=HD2t32pU0RokKbf2VopjxlArIVoh_-fLcwiJmfQ2MJM,15209
6
6
  OpenApiDriver/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  OpenApiLibCore/__init__.py,sha256=CGZRj3Vh4TZ76LOLWJOrBFr27QYWVXsO1imLqH-aP9E,1604
8
8
  OpenApiLibCore/dto_base.py,sha256=qAPSLnrs1n_sbfe1z-3EPV31Q7dMe0Nno2XRFmrYl9A,11792
9
9
  OpenApiLibCore/dto_utils.py,sha256=maYX9QqPaJtiEo8vIFQLsT2FOT-LUGVnNcVaca4zCDk,2903
10
10
  OpenApiLibCore/oas_cache.py,sha256=Qg_Is5pAJZjZu5VmwEEarQs8teKrh3Y2psCcpDLU5Y4,379
11
- OpenApiLibCore/openapi_libcore.libspec,sha256=NuArV1fyBCQCbRdoHyFv81Ah1BppVCE2nS6L05cobqo,39195
12
- OpenApiLibCore/openapi_libcore.py,sha256=BVBaeqv_ZgPw5332BmNeTjONdpL73dXPcf8w1bWtvBA,86685
11
+ OpenApiLibCore/openapi_libcore.libspec,sha256=L-Mcs6bUn4db2jXkwg9DPFco06KkVksYz0u7jMpfTJw,45934
12
+ OpenApiLibCore/openapi_libcore.py,sha256=YkuznUzlfxPu0hoW_EDhdjQC37sttGBnWee04NBwTHk,91076
13
13
  OpenApiLibCore/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
14
  OpenApiLibCore/value_utils.py,sha256=wO5ssYTuk4YWWMJb0kl5n20X2r0NG55FXvgLqQd8qvw,18145
15
15
  roboswag/__init__.py,sha256=-8ql4wuY_ftOZRdCxSmBCMW3WpDk7Ir__st9xcb9qCI,223
@@ -35,7 +35,7 @@ roboswag/validate/__init__.py,sha256=stpgQmvZvqlqPBjZ3Vxhd3wbX_Nb85jyIbj44_EhK_w
35
35
  roboswag/validate/core.py,sha256=CfUEhkXPFAzIppRSiGyh62j4BYW4vkjIXWEzRcJFD6o,84
36
36
  roboswag/validate/schema.py,sha256=jyD44GcYU_JQLw5hb1wK-DwxOsbJ-FstoNHwIVVMqoo,711
37
37
  roboswag/validate/text_response.py,sha256=P7WEC6ot1OG3YDEXRtmOwIFwki8jgq8fMb-L77X4vIo,527
38
- robotframework_openapitools-0.2.3.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
39
- robotframework_openapitools-0.2.3.dist-info/METADATA,sha256=3IFT878_SbvVMz0mQ0hV8ETJOlOKg9Qxxrfg-dBDALo,1610
40
- robotframework_openapitools-0.2.3.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
41
- robotframework_openapitools-0.2.3.dist-info/RECORD,,
38
+ robotframework_openapitools-0.3.0.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
39
+ robotframework_openapitools-0.3.0.dist-info/METADATA,sha256=XZJh7znjyzNIkKGG0k4Q4YGADOaZhAgrEWPaTMS63CI,1610
40
+ robotframework_openapitools-0.3.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
41
+ robotframework_openapitools-0.3.0.dist-info/RECORD,,