diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000..a33b2097 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,23 @@ +# This workflow will install Python dependencies, run tests and lint with a variety of Python versions +version: 2.1 + +orbs: + python: circleci/python@2.1.1 + +jobs: + build_and_test: + executor: python/default + steps: + - checkout + - python/install-packages: + pkg-manager: pip + - run: + name: Build + command: python setup.py build + - run: + name: Run Tests + command: pytest +workflows: + main: + jobs: + - build_and_test \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9d3540de..029d1d25 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,7 @@ __pycache__/ # JS files */node_modules/ -*package-lock.json \ No newline at end of file +*package-lock.json + +# Build files +build/ diff --git a/okta/request_executor.py b/okta/request_executor.py index b21475a4..8d1cca2c 100644 --- a/okta/request_executor.py +++ b/okta/request_executor.py @@ -118,8 +118,8 @@ async def create_request(self, method: str, url: str, body: dict = None, # Build request # Get predetermined headers and build URL - headers.update(self._custom_headers) - headers.update(self._default_headers) + headers = {**self._custom_headers, **headers} + headers = {**self._default_headers, **headers} if self._config["client"]["orgUrl"] not in url: url = self._config["client"]["orgUrl"] + url diff --git a/tests/unit/test_request_executor.py b/tests/unit/test_request_executor.py index 6759ca99..fcba3dd7 100644 --- a/tests/unit/test_request_executor.py +++ b/tests/unit/test_request_executor.py @@ -1,6 +1,7 @@ import aiohttp import asyncio import datetime +import pytest import time from http import HTTPStatus @@ -29,11 +30,13 @@ class MockHTTPRequest(): def __call__(self, **params): self.request_info = params - self.headers = MultiDict({'Date': datetime.datetime.now(tz=datetime.timezone.utc).strftime('%a, %d %b %Y %H:%M:%S %Z'), - 'Content-Type': 'application/json', - 'X-Rate-Limit-Limit': 600, - 'X-Rate-Limit-Remaining': 599, - 'X-Rate-Limit-Reset': str(time.time())}) + self.headers = MultiDict( + {'Date': datetime.datetime.now(tz=datetime.timezone.utc).strftime('%a, %d %b %Y %H:%M:%S %Z'), + 'Content-Type': 'application/json', + 'X-Rate-Limit-Limit': 600, + 'X-Rate-Limit-Remaining': 599, + 'X-Rate-Limit-Reset': str(time.time())} + ) self.url = params['url'] self.content_type = 'application/json' self.links = '' @@ -95,17 +98,46 @@ def test_clear_empty_params(): body = {'int_value': 0, 'str_value': '0', 'empty_str_value': '', - 'list_value': [1,2,3], + 'list_value': [1, 2, 3], 'empty_list_value': [], 'dict_value': {'int_value': 0}, 'empty_dict_value': {}, - 'nested_empty_dict_value': {'list_value': [1,2,3], 'empty_list_value': []}, + 'nested_empty_dict_value': {'list_value': [1, 2, 3], 'empty_list_value': []}, 'nested_empty_list_value': {'empty_list_value': []}} cleared_body = {'int_value': 0, 'str_value': '0', - 'list_value': [1,2,3], + 'list_value': [1, 2, 3], 'dict_value': {'int_value': 0}, - 'nested_empty_dict_value': {'list_value': [1,2,3]}} + 'nested_empty_dict_value': {'list_value': [1, 2, 3]}} assert req_exec.clear_empty_params(body) == cleared_body + + +@pytest.mark.parametrize( + "accept_header", + ["", "application/xml", "application/json", + "text/html", "application/xhtml+xml", "image/jpeg"] +) +@pytest.mark.asyncio +async def test_overwrite_default_request_executor_headers(accept_header): + org_url = "https://test.okta.com" + token = "TOKEN" + config = {'client': {'orgUrl': org_url, + 'token': token, + 'rateLimit': {}, + 'authorizationMode': None}} + req_exec = RequestExecutor(config=config, cache=None) + + # overwrite headers if parameter present + header_overwrite = {'Accept': accept_header} if accept_header else {} + request, error = await req_exec.create_request( + 'GET', + f'{org_url}/api/v1/users', + {}, + header_overwrite, + {} + ) + assert request is not None + assert request["headers"]["Accept"] ==\ + accept_header if accept_header else "application/json"