Skip to content

Commit

Permalink
Merge pull request #9 from groveco/fixed-pagination
Browse files Browse the repository at this point in the history
Fixed pagination
  • Loading branch information
Anton-Shutik authored Nov 8, 2024
2 parents 2cff38f + 761ebcc commit e59fb7d
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 11 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ response = client.query(query_name="listProducts")
response = client.query(query, variables={"page_size": 20})

# Use pagination.
# Note that "pageIngo" block with at least "hasNextPage" & "startCursor" is required
# Note that "pageIngo" block with at least "hasNextPage" & "endCursor" is required
# $cursor value should be passed as "after" parameter
query = '''
query products($page_size: Int = 100, $cursor: String) {
Expand All @@ -106,7 +106,7 @@ query products($page_size: Int = 100, $cursor: String) {
}
pageInfo {
hasNextPage
startCursor
endCursor
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.0.4
0.0.5
6 changes: 4 additions & 2 deletions shopify_client/graphql.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,15 @@ def __query(self, query=None, query_name=None, variables=None, operation_name=No
return self.client.parse_response(response)
except requests.exceptions.HTTPError as e:
logger.warning(f"Failed to execute GraphQL query: {repr(e)}")
return {}
raise e
except json.JSONDecodeError as e:
logger.warning(f"Failed to parse JSON response: {repr(e)}")
return {}
raise e

def __paginate(self, query, variables=None, operation_name=None, page_size=100):
assert "pageInfo" in query, "Query must contain a 'pageInfo' object to be paginated"
assert "hasNextPage" in query[query.find("pageInfo"):], "Query must contain a 'hasNextPage' field in 'pageInfo' object"
assert "endCursor" in query[query.find("pageInfo"):], "Query must contain a 'endCursor' field in 'pageInfo' object"

variables = variables or {}
variables["page_size"] = page_size
Expand Down
24 changes: 18 additions & 6 deletions tests/test_graphql.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,15 @@ def test_query_paginated(graphql, mock_client):
assert results[0] == {"data": {"pageInfo": {"hasNextPage": True, "endCursor": "cursor1"}}}
assert results[1] == {"data": {"pageInfo": {"hasNextPage": False}}}

def test_query_handles_http_error(graphql, mock_client, mocker):
def test_query_reraises_http_error(graphql, mock_client):
mock_client.post.side_effect = requests.exceptions.HTTPError("HTTP Error")
response = graphql(query="query { key }")
assert response == {}
with pytest.raises(requests.exceptions.HTTPError):
graphql(query="query { key }")

def test_query_handles_json_error(graphql, mock_client):
def test_query_reraises_json_error(graphql, mock_client):
mock_client.post.side_effect = json.JSONDecodeError("JSON Decode Error", "", 0)
response = graphql(query="query { key }")
assert response == {}
with pytest.raises(json.JSONDecodeError):
graphql(query="query { key }")

def test_graphql_call(graphql, mock_client):
mock_query_response = {"data": {"exampleField": "exampleValue"}}
Expand Down Expand Up @@ -98,3 +98,15 @@ def test_graphql_query_paginated(graphql, mock_client, mocker):
call("graphql.json", json={"query": "query { items { id } pageInfo { hasNextPage, endCursor } }", "variables": {"cursor": None, "page_size": 100}, "operationName": None}),
call("graphql.json", json={"query": "query { items { id } pageInfo { hasNextPage, endCursor } }", "variables": {"cursor": "cursor-1", "page_size": 100}, "operationName": None}),
])

def test_paginated_query_requires_page_info(graphql, mock_client):
with pytest.raises(AssertionError):
list(graphql(query="query { items { id } }", paginate=True))

def test_paginated_query_requires_has_next_page(graphql, mock_client):
with pytest.raises(AssertionError):
list(graphql(query="query { pageInfo { endCursor } }", paginate=True))

def test_paginated_query_requires_end_cursor(graphql, mock_client):
with pytest.raises(AssertionError):
list(graphql(query="query { pageInfo { hasNextPage } }", paginate=True))

0 comments on commit e59fb7d

Please sign in to comment.