robotframework-openapitools 0.2.2__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.
@@ -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.2
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=JuR4-Feq6xy3WQZn0xe8U9jA0rVnnvfvLN-3X6YwDjY,28322
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=qgCF2aJGNWUgSX6-xjHQ2-DvknFGcA-1CnvU3VHCRzA,39801
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.2.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
39
- robotframework_openapitools-0.2.2.dist-info/METADATA,sha256=9b-sj3qOnu_xXjxDj5Ad-9Vp5RIIBvd-fav5IVCqk6I,1610
40
- robotframework_openapitools-0.2.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
41
- robotframework_openapitools-0.2.2.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,,