def test_client_ssl_context(monkeypatch, mocker): org_url = "https://test.okta.com" token = "TOKEN" mock_ssl_context = mocker.MagicMock() config = {'orgUrl': org_url, 'token': token, 'sslContext': mock_ssl_context} client = OktaClient(config) # mock http requests, verify if custom header is present in request class MockHTTPRequest(): def __call__(self, **params): self.request_info = params self.headers = params['headers'] self.url = params['url'] self.content_type = 'application/json' self.links = '' self.text = MockHTTPRequest.mock_response_text self.status = 200 return self async def __aenter__(self): return self async def __aexit__(self, exc_type, exc, tb): pass @staticmethod async def mock_response_text(): return '[{"text": "mock response text"}]' mock_http_request = MockHTTPRequest() monkeypatch.setattr(aiohttp.ClientSession, 'request', mock_http_request) asyncio.run(client.list_users()) assert mock_http_request.request_info['ssl_context'] == mock_ssl_context
def test_client_raise_exception(): org_url = "https://test.okta.com" token = "TOKEN" config = {'orgUrl': org_url, 'token': token, 'raiseException': True} client = OktaClient(config) with pytest.raises(HTTPException): asyncio.run(client.list_users())
def test_client_log_debug(monkeypatch, caplog): org_url = "https://test.okta.com" token = "TOKEN" config = { 'orgUrl': org_url, 'token': token, 'logging': { 'enabled': True, 'logLevel': logging.DEBUG } } client = OktaClient(config) class MockHTTPRequest(): def __call__(self, **params): self.request_info = params self.headers = params['headers'] self.url = params['url'] self.content_type = 'application/json' self.links = '' self.text = MockHTTPRequest.mock_response_text self.status = 200 return self async def __aenter__(self): return self async def __aexit__(self, exc_type, exc, tb): pass @staticmethod async def mock_response_text(): return '[{"embedded": null,' \ '"links": {"self": {"href": "https://test.okta.com/v1/users/test_id"}},' \ '"activated": "2021-01-01T00:00:00.000Z",' \ '"created": "2021-01-01T00:00:00.000Z",' \ '"credentials": null,' \ '"id": "test_id",' \ '"last_login": null,' \ '"profile": {"name": "test_name"},' \ '"status": null,' \ '"status_changed": null,' \ '"transitioning_to_status": null,' \ '"type": null}]' mock_http_request = MockHTTPRequest() monkeypatch.setattr(aiohttp, 'request', mock_http_request) with caplog.at_level(logging.DEBUG): res, resp_body, error = asyncio.run(client.list_users()) assert 'okta-sdk-python' in caplog.text assert 'DEBUG' in caplog.text assert "'method': 'GET'" in caplog.text assert "'url': 'https://test.okta.com/api/v1/users'" in caplog.text
def test_client_custom_headers(monkeypatch, mocker): org_url = "https://test.okta.com" token = "TOKEN" config = {'orgUrl': org_url, 'token': token} custom_headers = { 'Header-Test-1': 'test value 1', 'Header-Test-2': 'test value 2' } client = OktaClient(config) # verify custom headers are set client.set_custom_headers(custom_headers) assert client.get_custom_headers() == custom_headers # mock http requests, verify if custom header is present in request class MockHTTPRequest(): def __call__(self, **params): self.request_info = params self.headers = params['headers'] self.url = params['url'] self.content_type = 'application/json' self.links = '' self.text = MockHTTPRequest.mock_response_text self.status = 200 return self async def __aenter__(self): return self async def __aexit__(self, exc_type, exc, tb): pass @staticmethod async def mock_response_text(): return '{"text": "mock response text"}' mock_http_request = MockHTTPRequest() monkeypatch.setattr(aiohttp, 'request', mock_http_request) asyncio.run(client.list_users()) assert 'Header-Test-1' in mock_http_request.headers assert 'Header-Test-2' in mock_http_request.headers # verify custom headers are cleared client.clear_custom_headers() assert client.get_custom_headers() == {}
def test_client_log_exception(monkeypatch, caplog): org_url = "https://test.okta.com" token = "TOKEN" config = { 'orgUrl': org_url, 'token': token, 'logging': { 'enabled': True, 'logLevel': logging.DEBUG } } client = OktaClient(config) class MockHTTPRequest(): def __call__(self, **params): raise aiohttp.ClientConnectorCertificateError( ConnectionKey(host=org_url, port=443, is_ssl=True, ssl=None, proxy=None, proxy_auth=None, proxy_headers_hash=None), SSLCertVerificationError( 1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: ' 'unable to get local issuer certificate (_ssl.c:1123)')) async def __aenter__(self): return self async def __aexit__(self, exc_type, exc, tb): pass @staticmethod async def mock_response_text(): return '[{"text": "mock response text"}]' mock_http_request = MockHTTPRequest() monkeypatch.setattr(aiohttp, 'request', mock_http_request) with caplog.at_level(logging.DEBUG): res, resp_body, error = asyncio.run(client.list_users()) assert 'Cannot connect to host https://test.okta.com' in caplog.text
def test_client_handle_aiohttp_error(monkeypatch, mocker): org_url = "https://test.okta.com" token = "TOKEN" config = {'orgUrl': org_url, 'token': token} client = OktaClient(config) class MockHTTPRequest(): def __call__(self, **params): raise aiohttp.ClientConnectorCertificateError( ConnectionKey(host=org_url, port=443, is_ssl=True, ssl=None, proxy=None, proxy_auth=None, proxy_headers_hash=None), SSLCertVerificationError( 1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: ' 'unable to get local issuer certificate (_ssl.c:1123)')) async def __aenter__(self): return self async def __aexit__(self, exc_type, exc, tb): pass @staticmethod async def mock_response_text(): return '[{"text": "mock response text"}]' mock_http_request = MockHTTPRequest() monkeypatch.setattr(aiohttp, 'request', mock_http_request) res, resp_body, error = asyncio.run(client.list_users()) assert res is None assert resp_body is None assert isinstance(error, aiohttp.ClientError)
def test_retry_count_header(monkeypatch): org_url = "https://test.okta.com" token = "TOKEN" config = { 'orgUrl': org_url, 'token': token, 'rateLimit': { 'maxRetries': 2 } } client = OktaClient(config) class MockHTTPRequest(): """ async with aiohttp.request(**params) as response: return (response.request_info, response, await response.text(), None) _, res_details, resp_body, error = \ headers = res_details.headers """ 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.url = params['url'] self.content_type = 'application/json' self.links = '' self.text = MockHTTPRequest.mock_response_text self.status = HTTPStatus.TOO_MANY_REQUESTS return self async def __aenter__(self): return self async def __aexit__(self, exc_type, exc, tb): pass @staticmethod async def mock_response_text(): return '[{"embedded": null,' \ '"links": {"self": {"href": "https://test.okta.com/v1/users/test_id"}},' \ '"activated": "2021-01-01T00:00:00.000Z",' \ '"created": "2021-01-01T00:00:00.000Z",' \ '"credentials": null,' \ '"id": "test_id",' \ '"last_login": null,' \ '"profile": {"name": "test_name"},' \ '"status": null,' \ '"status_changed": null,' \ '"transitioning_to_status": null,' \ '"type": null}]' mock_http_request = MockHTTPRequest() monkeypatch.setattr(aiohttp, 'request', mock_http_request) res, resp_body, error = asyncio.run(client.list_users()) # Check request was retried max times and header 'X-Okta-Retry-Count' was set properly assert mock_http_request.request_info['headers'].get( 'X-Okta-Retry-Count') == '2'