Skip to content

Commit 21b3cd2

Browse files
committed
test(testing): cover snake_case alias identity and behaviour
Add ``TestAssertionAliases`` covering the new ``assert_response_no_errors`` / ``assert_response_has_errors`` aliases: * Identity check: each alias must be the **same callable** as its camelCase counterpart, so the two spellings cannot drift apart. * End-to-end behaviour for both spellings on a clean response and on an errors response, asserting both the silent-pass and ``AssertionError`` branches. Uses a tiny ``_FakeHttpResponse`` stand-in so the alias tests stay free of any dependency on routing, schemas, or the test client. Each test follows the team docstring template. Made-with: Cursor
1 parent 212ba99 commit 21b3cd2

1 file changed

Lines changed: 147 additions & 0 deletions

File tree

graphene_django/utils/tests/test_testing.py

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
import json
2+
13
import pytest
24
from django.test import Client
35

46
from ...settings import graphene_settings
57
from ...tests.test_types import with_local_registry
68
from .. import GraphQLTestCase
9+
from ..testing import GraphQLTestMixin
710

811

912
@with_local_registry
@@ -52,3 +55,147 @@ def test_graphql_test_case_imports_endpoint():
5255
"""
5356

5457
assert GraphQLTestCase.GRAPHQL_URL == graphene_settings.TESTING_ENDPOINT
58+
59+
60+
class _FakeHttpResponse:
61+
"""Minimal stand-in for ``django.http.HttpResponse``.
62+
63+
The ``assertResponse*`` helpers only touch ``.status_code`` and
64+
``.content``, so we don't need the full Django response machinery to
65+
exercise them. Building this stand-in keeps the alias tests free of
66+
any dependency on routing, schemas, or the test client.
67+
"""
68+
69+
def __init__(self, content_dict, status_code=200):
70+
self.content = json.dumps(content_dict).encode("utf-8")
71+
self.status_code = status_code
72+
73+
74+
class TestAssertionAliases:
75+
"""Coverage for the snake_case aliases in :mod:`graphene_django.utils.testing`.
76+
77+
The PR adds ``assert_response_no_errors`` /
78+
``assert_response_has_errors`` as additive aliases for the existing
79+
camelCase ``assertResponseNoErrors`` / ``assertResponseHasErrors``.
80+
These tests pin three properties of that contract:
81+
82+
1. The aliases must point at the **same callable** as the
83+
camelCase originals (no copy-paste re-implementation that could
84+
drift out of sync over time).
85+
2. The aliases must work end-to-end on a "no errors" response.
86+
3. The aliases must work end-to-end on a "with errors" response.
87+
88+
The end-to-end checks build a tiny ``GraphQLTestCase`` subclass and
89+
invoke each alias against a synthesised :class:`_FakeHttpResponse`,
90+
so neither GraphiQL routing nor a real schema needs to be involved.
91+
"""
92+
93+
def test_alias_is_identical_to_camel_case_original(self):
94+
"""
95+
Name: alias identity check
96+
Description: ``assert_response_no_errors`` and
97+
``assert_response_has_errors`` must be the **same** function
98+
objects as their camelCase counterparts so behaviour cannot
99+
drift between spellings.
100+
Assumptions: Both spellings are defined on
101+
:class:`GraphQLTestMixin`.
102+
Expectations: ``is`` identity holds for both pairs.
103+
"""
104+
assert (
105+
GraphQLTestMixin.assert_response_no_errors
106+
is GraphQLTestMixin.assertResponseNoErrors
107+
)
108+
assert (
109+
GraphQLTestMixin.assert_response_has_errors
110+
is GraphQLTestMixin.assertResponseHasErrors
111+
)
112+
113+
def test_assert_response_no_errors_alias_passes_for_clean_response(self):
114+
"""
115+
Name: snake_case no-errors helper, clean response
116+
Description: ``assert_response_no_errors`` should silently accept a
117+
200 response whose JSON body has no ``errors`` key, exactly
118+
like its camelCase counterpart.
119+
Assumptions: A bare ``{"data": {...}}`` body with status 200 is the
120+
canonical "clean" GraphQL response.
121+
Expectations: The call returns without raising.
122+
"""
123+
124+
class _TC(GraphQLTestCase):
125+
GRAPHQL_SCHEMA = True
126+
127+
def runTest(self):
128+
pass
129+
130+
tc = _TC()
131+
resp = _FakeHttpResponse({"data": {"hello": "world"}}, status_code=200)
132+
tc.assert_response_no_errors(resp)
133+
134+
def test_assert_response_no_errors_alias_fails_when_errors_present(self):
135+
"""
136+
Name: snake_case no-errors helper, errors present
137+
Description: ``assert_response_no_errors`` should fail when the
138+
response contains an ``errors`` key, exactly like its
139+
camelCase counterpart.
140+
Assumptions: ``unittest`` assertion failures raise
141+
:class:`AssertionError`.
142+
Expectations: ``AssertionError`` is raised.
143+
"""
144+
145+
class _TC(GraphQLTestCase):
146+
GRAPHQL_SCHEMA = True
147+
148+
def runTest(self):
149+
pass
150+
151+
tc = _TC()
152+
resp = _FakeHttpResponse(
153+
{"errors": [{"message": "boom"}]}, status_code=200
154+
)
155+
with pytest.raises(AssertionError):
156+
tc.assert_response_no_errors(resp)
157+
158+
def test_assert_response_has_errors_alias_passes_when_errors_present(self):
159+
"""
160+
Name: snake_case has-errors helper, errors present
161+
Description: ``assert_response_has_errors`` should silently accept
162+
a response whose body has an ``errors`` key, regardless of
163+
status code (GraphQL returns 200 even on errors).
164+
Assumptions: An ``{"errors": [...]}``-shaped response represents
165+
a failing GraphQL query.
166+
Expectations: The call returns without raising.
167+
"""
168+
169+
class _TC(GraphQLTestCase):
170+
GRAPHQL_SCHEMA = True
171+
172+
def runTest(self):
173+
pass
174+
175+
tc = _TC()
176+
resp = _FakeHttpResponse(
177+
{"errors": [{"message": "boom"}]}, status_code=200
178+
)
179+
tc.assert_response_has_errors(resp)
180+
181+
def test_assert_response_has_errors_alias_fails_for_clean_response(self):
182+
"""
183+
Name: snake_case has-errors helper, clean response
184+
Description: ``assert_response_has_errors`` should fail when the
185+
response has no ``errors`` key, exactly like its camelCase
186+
counterpart.
187+
Assumptions: ``unittest`` assertion failures raise
188+
:class:`AssertionError`.
189+
Expectations: ``AssertionError`` is raised.
190+
"""
191+
192+
class _TC(GraphQLTestCase):
193+
GRAPHQL_SCHEMA = True
194+
195+
def runTest(self):
196+
pass
197+
198+
tc = _TC()
199+
resp = _FakeHttpResponse({"data": {"hello": "world"}}, status_code=200)
200+
with pytest.raises(AssertionError):
201+
tc.assert_response_has_errors(resp)

0 commit comments

Comments
 (0)