Skip to content

Commit 727618e

Browse files
committed
Add regression test for DeleteAnalysisMutation return value
Address PR #1369 review (Claude bot): the missing-return fix in config/graphql/analysis_mutations.py — restoring `return DeleteAnalysisMutation(ok=True, message="SUCCESS")` — was the most impactful behavioral fix bundled into the type-annotation pass, but no regression test pinned the success shape. The new test grants DELETE permission on an Analysis to its creator, runs the GraphQL mutation, and asserts the response contains `ok=True`/`message="SUCCESS"` rather than the `null` payload that was previously returned. Without the restored `return`, the assertion on `data.deleteAnalysis` being non-null fails immediately.
1 parent 5183621 commit 727618e

1 file changed

Lines changed: 97 additions & 0 deletions

File tree

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
"""Regression coverage for the DeleteAnalysisMutation return value.
2+
3+
PR #1369 restored the missing ``return DeleteAnalysisMutation(...)`` line in
4+
``config/graphql/analysis_mutations.py``. Before the fix the mutation kicked
5+
off the async deletion task correctly but returned ``None`` to the GraphQL
6+
client, so the frontend never observed ``ok=True`` / a success message.
7+
"""
8+
9+
from __future__ import annotations
10+
11+
import logging
12+
13+
import factory
14+
from django.contrib.auth import get_user_model
15+
from django.db import transaction
16+
from django.db.models.signals import post_save
17+
from django.test import TestCase
18+
from graphql_relay import to_global_id
19+
20+
from config.graphql.schema import schema
21+
from opencontractserver.analyzer.models import Analysis, Analyzer, GremlinEngine
22+
from opencontractserver.types.enums import PermissionTypes
23+
from opencontractserver.utils.permissioning import set_permissions_for_obj_to_user
24+
25+
User = get_user_model()
26+
logger = logging.getLogger(__name__)
27+
28+
29+
class _Context:
30+
def __init__(self, user):
31+
self.user = user
32+
33+
34+
class DeleteAnalysisMutationReturnValueTestCase(TestCase):
35+
"""Pin the success-shape returned by ``DeleteAnalysisMutation.mutate``."""
36+
37+
DELETE_ANALYSIS = """
38+
mutation ($id: String!) {
39+
deleteAnalysis(id: $id) {
40+
ok
41+
message
42+
}
43+
}
44+
"""
45+
46+
@factory.django.mute_signals(post_save)
47+
def setUp(self) -> None:
48+
with transaction.atomic():
49+
self.user = User.objects.create_user(
50+
username="alice",
51+
password="abcd1234",
52+
)
53+
54+
self.gremlin = GremlinEngine.objects.create(
55+
url="http://example.invalid/gremlin",
56+
creator=self.user,
57+
)
58+
self.analyzer = Analyzer.objects.create(
59+
id="test-analyzer",
60+
description="Test analyzer for delete mutation",
61+
creator=self.user,
62+
host_gremlin=self.gremlin,
63+
)
64+
self.analysis = Analysis.objects.create(
65+
analyzer=self.analyzer,
66+
creator=self.user,
67+
)
68+
69+
# The owner has CRUD via the post-creation signal in production, but
70+
# signals are muted in setUp so we grant DELETE explicitly here.
71+
set_permissions_for_obj_to_user(
72+
user_val=self.user,
73+
instance=self.analysis,
74+
permissions=[PermissionTypes.DELETE],
75+
)
76+
77+
def test_mutation_returns_ok_and_success_message(self) -> None:
78+
from graphene.test import Client
79+
80+
client = Client(schema, context_value=_Context(self.user))
81+
82+
response = client.execute(
83+
self.DELETE_ANALYSIS,
84+
variable_values={
85+
"id": to_global_id("AnalysisType", self.analysis.id),
86+
},
87+
)
88+
89+
# Without the restored return statement, ``response["data"]`` would
90+
# contain ``{"deleteAnalysis": null}`` and this assertion fails.
91+
self.assertIsNone(response.get("errors"))
92+
self.assertIsNotNone(response["data"]["deleteAnalysis"])
93+
self.assertTrue(response["data"]["deleteAnalysis"]["ok"])
94+
self.assertEqual(
95+
response["data"]["deleteAnalysis"]["message"],
96+
"SUCCESS",
97+
)

0 commit comments

Comments
 (0)