-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generalize testing.file_graphql_query #68
Closed
Closed
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
"""Use flask's Test client to run file based graphql test.""" | ||
from .. import testingbase | ||
|
||
DEFAULT_GRAPHQL_URL = "/graphql/" | ||
|
||
|
||
def create_client_post(client): | ||
""" | ||
Create client_post function for testingbase.file_graphql_query from django.test.Client | ||
""" | ||
def client_post(graphql_url, data, files, headers=None): | ||
data.update(files) | ||
if headers: | ||
response = client.post(graphql_url, data=data, headers=headers) | ||
else: | ||
response = client.post(graphql_url, data=data) | ||
return response | ||
return client_post | ||
|
||
|
||
def file_graphql_query( | ||
query, op_name=None, input_data=None, variables=None, | ||
headers=None, files=None, client=None, graphql_url=None, | ||
): | ||
""" | ||
Perform file based mutation, using django.test.Client | ||
|
||
:param str query: GraphQL query to run | ||
:param str op_name: If the query is a mutation or named query, you must | ||
supply the op_name. For annon queries ("{ ... }"), should be None (default). | ||
:param dict input_data: If provided, the $input variable in GraphQL will be set | ||
to this value. If both ``input_data`` and ``variables``, | ||
are provided, the ``input`` field in the ``variables`` | ||
dict will be overwritten with this value. Defaults to None. | ||
:param dict variables: If provided, the "variables" field in GraphQL will be | ||
set to this value. Defaults to None. | ||
:param dict headers: If provided, the headers in POST request to GRAPHQL_URL | ||
will be set to this value. Defaults to None | ||
:param dict files: Files to be sent via request.FILES. Defaults to None. | ||
:param flask.testing.FlaskClient: Test client. Defaults to None. | ||
:param str graphql_url: URL to graphql endpoint. Defaults to "/graphql" | ||
:return: Response object from client | ||
""" | ||
client_post = create_client_post(client) | ||
return testingbase.file_graphql_query( | ||
query, op_name, input_data, variables, headers, files, client_post, graphql_url) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
"""Base of using Test client to run file based graphql test.""" | ||
import json | ||
DEFAULT_GRAPHQL_URL = "/graphql/" | ||
|
||
|
||
def file_graphql_query( | ||
query, op_name=None, input_data=None, variables=None, | ||
headers=None, files=None, client_post=None, graphql_url=None, | ||
): | ||
""" | ||
Based on: https://www.sam.today/blog/testing-graphql-with-graphene-django/ | ||
|
||
Perform file based mutation. | ||
|
||
:param str query: GraphQL query to run | ||
:param str op_name: If the query is a mutation or named query, you must | ||
supply the op_name. For annon queries ("{ ... }"), should be None (default). | ||
:param dict input_data: If provided, the $input variable in GraphQL will be set | ||
to this value. If both ``input_data`` and ``variables``, | ||
are provided, the ``input`` field in the ``variables`` | ||
dict will be overwritten with this value. Defaults to None. | ||
:param dict variables: If provided, the "variables" field in GraphQL will be | ||
set to this value. Defaults to None. | ||
:param dict headers: If provided, the headers in POST request to GRAPHQL_URL | ||
will be set to this value. Defaults to None | ||
:param dict files: Files to be sent via request.FILES. Defaults to None. | ||
:param callable client_post: Test client wrapper function. | ||
It receives graphql endpoint(str), data(dict), files(dict), headers(dict). | ||
When called, it sends POST request using framework specific test client. | ||
Defaults to None. | ||
:param str graphql_url: URL to graphql endpoint. Defaults to "/graphql" | ||
:return: Response object from client | ||
""" | ||
|
||
if not files: | ||
raise ValueError('Missing required argument "files".') | ||
|
||
if not client_post: | ||
raise ValueError('Missing required argument "client_post".') | ||
|
||
headers = headers or {} | ||
variables = variables or {} | ||
graphql_url = graphql_url or DEFAULT_GRAPHQL_URL | ||
map_ = {} | ||
|
||
for key in files.keys(): | ||
map_[key] = [f'variables.{key}'] | ||
if key not in variables: | ||
variables[key] = None | ||
|
||
body = {'query': query} | ||
if op_name: | ||
body['operationName'] = op_name | ||
if variables: | ||
body['variables'] = variables | ||
if input_data: | ||
if 'variables' in body: | ||
body['variables']['input'] = input_data | ||
else: | ||
body['variables'] = {'input': input_data} | ||
|
||
data = { | ||
'operations': json.dumps(body), | ||
'map': json.dumps(map_), | ||
} | ||
|
||
# data.update(files) | ||
if headers: | ||
resp = client_post(graphql_url, data, files ** headers) | ||
else: | ||
resp = client_post(graphql_url, data, files) | ||
|
||
return resp | ||
|
||
|
||
class GraphQLFileUploadTestMixin: | ||
"""GraphQL file upload test mixin.""" | ||
|
||
# URL to graphql endpoint | ||
GRAPHQL_URL = DEFAULT_GRAPHQL_URL | ||
|
||
def file_query( | ||
self, query, op_name=None, input_data=None, files=None, | ||
variables=None, headers=None, | ||
): | ||
""" | ||
Perform file based mutation. | ||
:param str query: GraphQL query to run | ||
:param str op_name: If the query is a mutation or named query, you must | ||
supply the op_name. For annon queries ("{ ... }"), should be None (default). | ||
:param dict input_data: If provided, the $input variable in GraphQL will be set | ||
to this value. If both ``input_data`` and ``variables``, | ||
are provided, the ``input`` field in the ``variables`` | ||
dict will be overwritten with this value. Defaults to None. | ||
:param dict variables: If provided, the "variables" field in GraphQL will be | ||
set to this value. Defaults to None. | ||
:param dict headers: If provided, the headers in POST request to GRAPHQL_URL | ||
will be set to this value. Defaults to None | ||
:param dict files: Files to be sent via request.FILES. Defaults to None. | ||
:param django.test.Client client: Test client. Defaults to django.test.Client. | ||
:param str graphql_url: URL to graphql endpoint. Defaults to "/graphql" | ||
:return: Response object from client | ||
""" | ||
return file_graphql_query( | ||
query, | ||
op_name=op_name, | ||
input_data=input_data, | ||
variables=variables, | ||
headers=headers, | ||
files=files, | ||
client_post=self.client_post, | ||
graphql_url=self.GRAPHQL_URL, | ||
) | ||
|
||
def assertResponseNoErrors(self, resp, msg=None): # pylint: disable=C0103 | ||
""" | ||
Assert that the call went through correctly. 200 means the syntax is ok, | ||
if there are no `errors`, the call was fine. | ||
:param Response resp: HttpResponse | ||
:param str msg: Error message. | ||
""" | ||
content = json.loads(resp.content) | ||
self.assertEqual(resp.status_code, 200, msg or content) | ||
self.assertNotIn("errors", list(content.keys()), msg or content) | ||
|
||
def assertResponseHasErrors(self, resp, msg=None): # pylint: disable=C0103 | ||
""" | ||
Assert that the call was failing. Take care: Even with errors, | ||
GraphQL returns status 200! | ||
:param Response resp: HttpResponse | ||
:param str msg: Error message. | ||
""" | ||
content = json.loads(resp.content) | ||
self.assertIn("errors", list(content.keys()), msg or content) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll argue that a base class shouldn't implement a
setUp
method.