def __init__( self, authentication_method: Optional[BaseAuthenticationMethod] = None, response_handler: Type[BaseResponseHandler] = RequestsResponseHandler, request_formatter: Type[BaseRequestFormatter] = NoOpRequestFormatter, error_handler: Type[BaseErrorHandler] = ErrorHandler, request_strategy: Optional[BaseRequestStrategy] = None, ): # Set default values self._default_headers = {} self._default_query_params = {} self._default_username_password_authentication = None # A session needs to live at this client level so that all # request strategies have access to the same session. self._session = None # Set client strategies self.set_authentication_method(authentication_method or NoAuthentication()) self.set_response_handler(response_handler) self.set_error_handler(error_handler) self.set_request_formatter(request_formatter) self.set_request_strategy(request_strategy or RequestStrategy()) # Perform any one time authentication required by api self._authentication_method.perform_initial_auth(self)
def test_no_authentication_method_does_not_alter_client(): client = BaseClient( authentication_method=NoAuthentication(), response_handler=BaseResponseHandler, request_formatter=BaseRequestFormatter, ) assert client.get_default_query_params() == {} assert client.get_default_headers() == {} assert client.get_default_username_password_authentication() is None
def test_client_initialization_with_invalid_requests_handler(): with pytest.raises(RuntimeError) as exc_info: Client( authentication_method=NoAuthentication(), response_handler=MockResponseHandler, request_formatter=None, ) assert str( exc_info.value ) == "provided request_formatter must be a subclass of BaseRequestFormatter."
def test_set_and_get_default_headers(): client = Client( authentication_method=NoAuthentication(), response_handler=MockResponseHandler, request_formatter=MockRequestFormatter, ) assert client.get_default_headers() == {} client.set_default_headers({"first": "header"}) assert client.get_default_headers() == {"first": "header"} # Setting the default headers should overwrite the original client.set_default_headers({"second": "header"}) assert client.get_default_headers() == {"second": "header"}
def test_read_real_world_api(json_placeholder_cassette): client = JSONPlaceholderClient( authentication_method=NoAuthentication(), response_handler=JsonResponseHandler, request_formatter=JsonRequestFormatter, ) assert len(client.get_all_todos()) == 200 expected_todo = { "completed": False, "id": 45, "title": "velit soluta adipisci molestias reiciendis harum", "userId": 3, } assert client.get_todo(45) == expected_todo
def test_set_and_get_default_username_password_authentication(): client = Client( authentication_method=NoAuthentication(), response_handler=MockResponseHandler, request_formatter=MockRequestFormatter, ) assert client.get_default_username_password_authentication() is None client.set_default_username_password_authentication( ("username", "password")) assert client.get_default_username_password_authentication() == ( "username", "password") # Setting the default username password should overwrite the original client.set_default_username_password_authentication( ("username", "morecomplicatedpassword")) assert client.get_default_username_password_authentication() == ( "username", "morecomplicatedpassword")
def test_url_parameter_pagination(mock_requests): # Given the response is over two pages mock_requests.get( "mock://testserver.com", json={ "page1": "data", "next": "mock://testserver.com/page2" }, status_code=200, ) mock_requests.get("mock://testserver.com/page2", json={ "page2": "data", "next": None }, status_code=200) response_data = [ { "page1": "data", "next": "mock://testserver.com/page2" }, { "page2": "data", "next": None }, ] client = UrlPaginatedClient( base_url="mock://testserver.com", authentication_method=NoAuthentication(), response_handler=JsonResponseHandler, request_formatter=JsonRequestFormatter, ) # And the client has been set up with the SinglePagePaginator original_strategy = client.get_request_strategy() assert isinstance(original_strategy, RequestStrategy) # When I call the client method response = list(client.make_read_request()) # Then two requests are made to get both pages assert mock_requests.call_count == 2 assert response == response_data # And the clients paginator is reset back to the original. assert client.get_request_strategy() == original_strategy
def test_query_parameter_pagination(mock_requests): # Given the response is over three pages response_data = [ { "page1": "data", "next": "page2" }, { "page2": "data", "next": "page3" }, { "page3": "data", "next": None }, ] mock_requests.get( "mock://testserver.com", [ { "json": { "page1": "data", "next": "page2" }, "status_code": 200 }, { "json": { "page2": "data", "next": "page3" }, "status_code": 200 }, { "json": { "page3": "data", "next": None }, "status_code": 200 }, ], ) # mock_requests.get.side_effect = [build_response(json=page_data) for page_data in response_data] client = QueryPaginatedClient( base_url="mock://testserver.com", authentication_method=NoAuthentication(), response_handler=JsonResponseHandler, request_formatter=JsonRequestFormatter, ) # And the client has been set up with the SinglePagePaginator original_strategy = client.get_request_strategy() assert isinstance(original_strategy, RequestStrategy) # When I call the client method response = list(client.make_read_request()) # Then two requests are made to get both pages assert mock_requests.call_count == 3 assert len(response) == 3 assert response == response_data # And the clients paginator is reset back to the original. assert client.get_request_strategy() == original_strategy
@staticmethod def get_request_data(response): mock_response_handler_call(response) return response class MockRequestFormatter(BaseRequestFormatter): """Mock class for testing.""" @classmethod def format(cls, data: dict): mock_request_formatter_call(data) return data client = Client( authentication_method=NoAuthentication(), response_handler=MockResponseHandler, request_formatter=MockRequestFormatter, ) def test_client_initialization_with_invalid_authentication_method(): with pytest.raises(RuntimeError) as exc_info: Client( authentication_method=None, response_handler=MockResponseHandler, request_formatter=MockRequestFormatter, ) expected_message = "provided authentication_method must be an instance of BaseAuthenticationMethod." assert str(exc_info.value) == expected_message