from unittest.mock import Mock, patch import pytest from requests.exceptions import Timeout from ...conf.test import override_dynamic_settings from .. import exceptions from ..client import REQUESTS_TIMEOUT, get_access_token ACCESS_TOKEN = "acc3ss-t0k3n" CODE_GRANT = "valid-code" @pytest.fixture def mock_request(dynamic_settings): return Mock( settings=dynamic_settings, build_absolute_uri=lambda url: f"http://mysite.com{url or ''}", ) @override_dynamic_settings( oauth2_client_id="clientid123", oauth2_client_secret="secr3t", oauth2_token_url="https://example.com/oauth2/token", ) def test_access_token_is_retrieved_using_post_request(mock_request): post_mock = Mock( return_value=Mock( status_code=200, json=Mock( return_value={ "access_token": ACCESS_TOKEN, }, ), ), ) with patch("requests.post", post_mock): assert get_access_token(mock_request, CODE_GRANT) == ACCESS_TOKEN post_mock.assert_called_once_with( "https://example.com/oauth2/token", data={ "grant_type": "authorization_code", "client_id": "clientid123", "client_secret": "secr3t", "redirect_uri": "http://mysite.com/oauth2/complete/", "code": CODE_GRANT, }, headers={}, timeout=REQUESTS_TIMEOUT, ) @override_dynamic_settings( oauth2_client_id="clientid123", oauth2_client_secret="secr3t", oauth2_token_url="https://example.com/oauth2/token", oauth2_token_extra_headers="Accept: application/json\nApi-Ver:1234", ) def test_access_token_is_retrieved_using_extra_headers(mock_request): post_mock = Mock( return_value=Mock( status_code=200, json=Mock( return_value={ "access_token": ACCESS_TOKEN, }, ), ), ) with patch("requests.post", post_mock): assert get_access_token(mock_request, CODE_GRANT) == ACCESS_TOKEN post_mock.assert_called_once_with( "https://example.com/oauth2/token", data={ "grant_type": "authorization_code", "client_id": "clientid123", "client_secret": "secr3t", "redirect_uri": "http://mysite.com/oauth2/complete/", "code": CODE_GRANT, }, headers={ "Accept": "application/json", "Api-Ver": "1234", }, timeout=REQUESTS_TIMEOUT, ) @override_dynamic_settings( oauth2_client_id="clientid123", oauth2_client_secret="secr3t", oauth2_token_url="https://example.com/oauth2/token", oauth2_json_token_path="data.auth.token", ) def test_access_token_is_extracted_from_json(mock_request): post_mock = Mock( return_value=Mock( status_code=200, json=Mock( return_value={ "data": { "auth": { "token": ACCESS_TOKEN, }, }, }, ), ), ) with patch("requests.post", post_mock): assert get_access_token(mock_request, CODE_GRANT) == ACCESS_TOKEN post_mock.assert_called_once() @override_dynamic_settings( oauth2_client_id="clientid123", oauth2_client_secret="secr3t", oauth2_token_url="https://example.com/oauth2/token", ) def test_exception_is_raised_if_access_token_request_times_out(mock_request): post_mock = Mock(side_effect=Timeout()) with patch("requests.post", post_mock): with pytest.raises(exceptions.OAuth2AccessTokenRequestError): get_access_token(mock_request, CODE_GRANT) post_mock.assert_called_once() @override_dynamic_settings( oauth2_client_id="clientid123", oauth2_client_secret="secr3t", oauth2_token_url="https://example.com/oauth2/token", ) def test_exception_is_raised_if_access_token_request_response_is_not_200(mock_request): post_mock = Mock( return_value=Mock( status_code=400, ), ) with patch("requests.post", post_mock): with pytest.raises(exceptions.OAuth2AccessTokenResponseError): get_access_token(mock_request, CODE_GRANT) post_mock.assert_called_once() @override_dynamic_settings( oauth2_client_id="clientid123", oauth2_client_secret="secr3t", oauth2_token_url="https://example.com/oauth2/token", ) def test_exception_is_raised_if_access_token_request_response_is_not_json(mock_request): post_mock = Mock( return_value=Mock( status_code=200, json=Mock( side_effect=ValueError(), ), ), ) with patch("requests.post", post_mock): with pytest.raises(exceptions.OAuth2AccessTokenJSONError): get_access_token(mock_request, CODE_GRANT) post_mock.assert_called_once() @override_dynamic_settings( oauth2_client_id="clientid123", oauth2_client_secret="secr3t", oauth2_token_url="https://example.com/oauth2/token", ) def test_exception_is_raised_if_access_token_request_response_json_is_not_object( mock_request, ): post_mock = Mock( return_value=Mock( status_code=200, json=Mock( return_value=["json", "list"], ), ), ) with patch("requests.post", post_mock): with pytest.raises(exceptions.OAuth2AccessTokenJSONError): get_access_token(mock_request, CODE_GRANT) post_mock.assert_called_once() @override_dynamic_settings( oauth2_client_id="clientid123", oauth2_client_secret="secr3t", oauth2_token_url="https://example.com/oauth2/token", ) def test_exception_is_raised_if_access_token_request_response_json_misses_token( mock_request, ): post_mock = Mock( return_value=Mock( status_code=200, json=Mock( return_value={ "no_token": "nope", }, ), ), ) with patch("requests.post", post_mock): with pytest.raises(exceptions.OAuth2AccessTokenNotProvidedError): get_access_token(mock_request, CODE_GRANT) post_mock.assert_called_once()