2019-03-29 13:51:40 +03:00
|
|
|
import json
|
2020-12-31 08:12:24 +03:00
|
|
|
import warnings
|
2019-03-29 13:51:40 +03:00
|
|
|
|
2021-02-23 07:24:02 +03:00
|
|
|
from django.test import Client, TestCase, TransactionTestCase
|
2019-03-29 13:51:40 +03:00
|
|
|
|
2022-09-26 01:56:22 +03:00
|
|
|
from graphene_django.settings import graphene_settings
|
2023-09-18 18:23:53 +03:00
|
|
|
from graphene_django.utils.utils import _DJANGO_VERSION_AT_LEAST_4_2
|
2022-09-26 01:56:22 +03:00
|
|
|
|
2022-01-07 23:26:07 +03:00
|
|
|
DEFAULT_GRAPHQL_URL = "/graphql"
|
2020-08-05 22:24:16 +03:00
|
|
|
|
|
|
|
|
|
|
|
def graphql_query(
|
|
|
|
query,
|
2020-08-06 22:35:08 +03:00
|
|
|
operation_name=None,
|
2020-08-05 22:24:16 +03:00
|
|
|
input_data=None,
|
|
|
|
variables=None,
|
|
|
|
headers=None,
|
|
|
|
client=None,
|
|
|
|
graphql_url=None,
|
|
|
|
):
|
|
|
|
"""
|
|
|
|
Args:
|
|
|
|
query (string) - GraphQL query to run
|
2020-08-06 22:35:08 +03:00
|
|
|
operation_name (string) - If the query is a mutation or named query, you must
|
2022-03-03 16:58:48 +03:00
|
|
|
supply the operation_name. For annon queries ("{ ... }"),
|
2020-08-05 22:24:16 +03:00
|
|
|
should be None (default).
|
|
|
|
input_data (dict) - 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.
|
|
|
|
variables (dict) - If provided, the "variables" field in GraphQL will be
|
|
|
|
set to this value.
|
|
|
|
headers (dict) - If provided, the headers in POST request to GRAPHQL_URL
|
2021-02-23 07:13:49 +03:00
|
|
|
will be set to this value. Keys should be prepended with
|
|
|
|
"HTTP_" (e.g. to specify the "Authorization" HTTP header,
|
|
|
|
use "HTTP_AUTHORIZATION" as the key).
|
2020-08-05 22:24:16 +03:00
|
|
|
client (django.test.Client) - Test client. Defaults to django.test.Client.
|
|
|
|
graphql_url (string) - URL to graphql endpoint. Defaults to "/graphql".
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Response object from client
|
|
|
|
"""
|
|
|
|
if client is None:
|
|
|
|
client = Client()
|
|
|
|
if not graphql_url:
|
2022-09-26 01:56:22 +03:00
|
|
|
graphql_url = graphene_settings.TESTING_ENDPOINT
|
2020-08-05 22:24:16 +03:00
|
|
|
|
|
|
|
body = {"query": query}
|
2020-08-06 22:35:08 +03:00
|
|
|
if operation_name:
|
|
|
|
body["operationName"] = operation_name
|
2020-08-05 22:24:16 +03:00
|
|
|
if variables:
|
|
|
|
body["variables"] = variables
|
|
|
|
if input_data:
|
2020-12-31 02:37:57 +03:00
|
|
|
if "variables" in body:
|
2020-08-05 22:24:16 +03:00
|
|
|
body["variables"]["input"] = input_data
|
|
|
|
else:
|
|
|
|
body["variables"] = {"input": input_data}
|
|
|
|
if headers:
|
2023-09-18 18:23:53 +03:00
|
|
|
header_params = (
|
|
|
|
{"headers": headers} if _DJANGO_VERSION_AT_LEAST_4_2 else headers
|
|
|
|
)
|
2020-08-05 22:24:16 +03:00
|
|
|
resp = client.post(
|
2023-09-18 18:23:53 +03:00
|
|
|
graphql_url,
|
|
|
|
json.dumps(body),
|
|
|
|
content_type="application/json",
|
|
|
|
**header_params
|
2020-08-05 22:24:16 +03:00
|
|
|
)
|
|
|
|
else:
|
|
|
|
resp = client.post(
|
|
|
|
graphql_url, json.dumps(body), content_type="application/json"
|
|
|
|
)
|
|
|
|
return resp
|
|
|
|
|
2019-03-29 13:51:40 +03:00
|
|
|
|
2022-10-19 17:10:30 +03:00
|
|
|
class GraphQLTestMixin:
|
2019-03-29 13:51:40 +03:00
|
|
|
"""
|
|
|
|
Based on: https://www.sam.today/blog/testing-graphql-with-graphene-django/
|
|
|
|
"""
|
|
|
|
|
|
|
|
# URL to graphql endpoint
|
2022-09-26 01:56:22 +03:00
|
|
|
GRAPHQL_URL = graphene_settings.TESTING_ENDPOINT
|
2019-03-29 13:51:40 +03:00
|
|
|
|
2020-05-09 14:25:24 +03:00
|
|
|
def query(
|
|
|
|
self, query, operation_name=None, input_data=None, variables=None, headers=None
|
|
|
|
):
|
2019-03-29 13:51:40 +03:00
|
|
|
"""
|
|
|
|
Args:
|
|
|
|
query (string) - GraphQL query to run
|
2020-05-09 14:25:24 +03:00
|
|
|
operation_name (string) - If the query is a mutation or named query, you must
|
2022-03-03 16:58:48 +03:00
|
|
|
supply the operation_name. For annon queries ("{ ... }"),
|
2019-03-29 13:51:40 +03:00
|
|
|
should be None (default).
|
|
|
|
input_data (dict) - If provided, the $input variable in GraphQL will be set
|
2020-04-19 23:11:33 +03:00
|
|
|
to this value. If both ``input_data`` and ``variables``,
|
2019-09-07 21:49:29 +03:00
|
|
|
are provided, the ``input`` field in the ``variables``
|
|
|
|
dict will be overwritten with this value.
|
|
|
|
variables (dict) - If provided, the "variables" field in GraphQL will be
|
2019-12-26 14:45:18 +03:00
|
|
|
set to this value.
|
|
|
|
headers (dict) - If provided, the headers in POST request to GRAPHQL_URL
|
2021-02-23 07:13:49 +03:00
|
|
|
will be set to this value. Keys should be prepended with
|
|
|
|
"HTTP_" (e.g. to specify the "Authorization" HTTP header,
|
2022-03-03 16:58:48 +03:00
|
|
|
use "HTTP_AUTHORIZATION" as the key).
|
2019-03-29 13:51:40 +03:00
|
|
|
|
|
|
|
Returns:
|
|
|
|
Response object from client
|
|
|
|
"""
|
2020-08-05 22:24:16 +03:00
|
|
|
return graphql_query(
|
|
|
|
query,
|
2020-08-06 22:35:08 +03:00
|
|
|
operation_name=operation_name,
|
2020-08-05 22:24:16 +03:00
|
|
|
input_data=input_data,
|
|
|
|
variables=variables,
|
|
|
|
headers=headers,
|
2020-12-31 08:12:24 +03:00
|
|
|
client=self.client,
|
2020-08-05 22:24:16 +03:00
|
|
|
graphql_url=self.GRAPHQL_URL,
|
|
|
|
)
|
2019-03-29 13:51:40 +03:00
|
|
|
|
2020-12-31 08:12:24 +03:00
|
|
|
@property
|
2021-01-10 06:14:54 +03:00
|
|
|
def _client(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
@_client.getter
|
2020-12-31 08:12:24 +03:00
|
|
|
def _client(self):
|
|
|
|
warnings.warn(
|
|
|
|
"Using `_client` is deprecated in favour of `client`.",
|
|
|
|
PendingDeprecationWarning,
|
|
|
|
stacklevel=2,
|
|
|
|
)
|
|
|
|
return self.client
|
|
|
|
|
2021-01-10 06:14:54 +03:00
|
|
|
@_client.setter
|
|
|
|
def _client(self, client):
|
|
|
|
warnings.warn(
|
|
|
|
"Using `_client` is deprecated in favour of `client`.",
|
|
|
|
PendingDeprecationWarning,
|
|
|
|
stacklevel=2,
|
|
|
|
)
|
|
|
|
self.client = client
|
|
|
|
|
2020-12-31 02:37:57 +03:00
|
|
|
def assertResponseNoErrors(self, resp, msg=None):
|
2019-03-29 13:51:40 +03:00
|
|
|
"""
|
|
|
|
Assert that the call went through correctly. 200 means the syntax is ok, if there are no `errors`,
|
|
|
|
the call was fine.
|
2019-03-29 14:53:18 +03:00
|
|
|
:resp HttpResponse: Response
|
2019-03-29 13:51:40 +03:00
|
|
|
"""
|
2019-07-11 22:32:07 +03:00
|
|
|
content = json.loads(resp.content)
|
2020-12-31 02:37:57 +03:00
|
|
|
self.assertEqual(resp.status_code, 200, msg or content)
|
|
|
|
self.assertNotIn("errors", list(content.keys()), msg or content)
|
2019-03-29 13:51:40 +03:00
|
|
|
|
2020-12-31 02:37:57 +03:00
|
|
|
def assertResponseHasErrors(self, resp, msg=None):
|
2019-03-29 13:51:40 +03:00
|
|
|
"""
|
|
|
|
Assert that the call was failing. Take care: Even with errors, GraphQL returns status 200!
|
2019-03-29 14:53:18 +03:00
|
|
|
:resp HttpResponse: Response
|
2019-03-29 13:51:40 +03:00
|
|
|
"""
|
|
|
|
content = json.loads(resp.content)
|
2020-12-31 02:37:57 +03:00
|
|
|
self.assertIn("errors", list(content.keys()), msg or content)
|
2021-02-23 07:24:02 +03:00
|
|
|
|
|
|
|
|
|
|
|
class GraphQLTestCase(GraphQLTestMixin, TestCase):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
class GraphQLTransactionTestCase(GraphQLTestMixin, TransactionTestCase):
|
|
|
|
pass
|