diff --git a/shopify_client/exceptions.py b/shopify_client/exceptions.py new file mode 100644 index 0000000..5a81969 --- /dev/null +++ b/shopify_client/exceptions.py @@ -0,0 +1,2 @@ +class GraphQLError(Exception): + pass diff --git a/shopify_client/graphql.py b/shopify_client/graphql.py index 4359425..a1625ba 100644 --- a/shopify_client/graphql.py +++ b/shopify_client/graphql.py @@ -4,6 +4,8 @@ import requests +from .exceptions import GraphQLError + logger = logging.getLogger(__name__) @@ -56,7 +58,12 @@ def __query( "operationName": operation_name, }, ) - return self.client.parse_response(response) + parsed_response = self.client.parse_response(response) + if "errors" in parsed_response: + logger.warning(f"GraphQL errors: {parsed_response['errors']}") + if "data" not in parsed_response: + raise GraphQLError(f"GraphQL errors: {parsed_response['errors']}") + return parsed_response except requests.exceptions.HTTPError as e: logger.warning(f"Failed to execute GraphQL query: {repr(e)}") raise e diff --git a/tests/test_graphql.py b/tests/test_graphql.py index 7d7efb9..02c1a55 100644 --- a/tests/test_graphql.py +++ b/tests/test_graphql.py @@ -2,6 +2,7 @@ from unittest.mock import call, mock_open, patch import requests import pytest +from shopify_client.exceptions import GraphQLError from shopify_client.graphql import GraphQL from tests.conftest import CopyingMock @@ -159,3 +160,43 @@ def test_paginated_query_requires_has_next_page(graphql, mock_client): def test_paginated_query_requires_end_cursor(graphql, mock_client): with pytest.raises(AssertionError): list(graphql(query="query { pageInfo { hasNextPage } }", paginate=True)) + + +def test_graphql_query_handles_empty_data_with_errors_only(graphql, mock_client): + mock_client.post.return_value = {"errors": [{"message": "Another error occurred"}]} + with pytest.raises(GraphQLError, match='[{"message": "Another error occurred"}]'): + graphql(query="query { key }") + + +def test_graphql_query_reraises_http_error(graphql, mock_client): + mock_client.post.side_effect = requests.exceptions.HTTPError("HTTP Error") + with pytest.raises(requests.exceptions.HTTPError): + graphql(query="query { key }") + + +def test_graphql_query_reraises_json_error(graphql, mock_client): + mock_client.post.side_effect = json.JSONDecodeError("JSON Decode Error", "", 0) + with pytest.raises(json.JSONDecodeError): + graphql(query="query { key }") + + +def test_graphql_query_handles_data_with_errors(graphql, mock_client): + mock_client.post.return_value = { + "data": {"key": "value"}, + "errors": [{"message": "Some error occurred"}], + } + + # Mock the logger from the client + with patch("shopify_client.graphql.logger") as mock_logger: + response = graphql(query="query { key }") + + # Check that the response contains the data + assert response == { + "data": {"key": "value"}, + "errors": [{"message": "Some error occurred"}], + } + + # Verify that the logger was called with the expected message + mock_logger.warning.assert_called_once_with( + "GraphQL errors: [{'message': 'Some error occurred'}]" + )