Skip to content

Commit d5ec1c5

Browse files
committed
Add safe schema change for descriptions changing
Replicates graphql/graphql-js@cc007a9
1 parent d213449 commit d5ec1c5

2 files changed

Lines changed: 266 additions & 2 deletions

File tree

‎src/graphql/utilities/find_schema_changes.py‎

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ class SafeChangeType(Enum):
9797
FIELD_CHANGED_KIND_SAFE = 78
9898
ARG_CHANGED_KIND_SAFE = 79
9999
ARG_DEFAULT_VALUE_ADDED = 80
100+
DESCRIPTION_CHANGED = 81
100101

101102

102103
class BreakingChange(NamedTuple):
@@ -222,6 +223,17 @@ def find_directive_changes(
222223
for arg_name in args_diff.removed
223224
)
224225

226+
for old_arg, new_arg in args_diff.persisted.values():
227+
if old_arg.description != new_arg.description:
228+
schema_changes.append(
229+
SafeChange(
230+
SafeChangeType.DESCRIPTION_CHANGED,
231+
f"Description of @{old_directive.name}"
232+
f"({old_directive.name}) has changed to"
233+
f' "{new_arg.description}".',
234+
)
235+
)
236+
225237
if old_directive.is_repeatable and not new_directive.is_repeatable:
226238
schema_changes.append(
227239
BreakingChange(
@@ -237,6 +249,15 @@ def find_directive_changes(
237249
)
238250
)
239251

252+
if old_directive.description != new_directive.description:
253+
schema_changes.append(
254+
SafeChange(
255+
SafeChangeType.DESCRIPTION_CHANGED,
256+
f"Description of @{old_directive.name} has changed to"
257+
f' "{new_directive.description}".',
258+
)
259+
)
260+
240261
schema_changes.extend(
241262
BreakingChange(
242263
BreakingChangeType.DIRECTIVE_LOCATION_REMOVED,
@@ -284,6 +305,15 @@ def find_type_changes(
284305
)
285306

286307
for type_name, (old_type, new_type) in types_diff.persisted.items():
308+
if old_type.description != new_type.description:
309+
schema_changes.append(
310+
SafeChange(
311+
SafeChangeType.DESCRIPTION_CHANGED,
312+
f"Description of {old_type.name} has changed to"
313+
f' "{new_type.description}".',
314+
)
315+
)
316+
287317
if is_enum_type(old_type) and is_enum_type(new_type):
288318
schema_changes.extend(find_enum_type_changes(old_type, new_type))
289319
elif is_union_type(old_type) and is_union_type(new_type):
@@ -352,7 +382,7 @@ def find_input_object_type_changes(
352382
f" from {old_field.type} to {new_field.type}.",
353383
)
354384
)
355-
else:
385+
elif str(old_field.type) != str(new_field.type):
356386
schema_changes.append(
357387
SafeChange(
358388
SafeChangeType.FIELD_CHANGED_KIND_SAFE,
@@ -361,6 +391,15 @@ def find_input_object_type_changes(
361391
)
362392
)
363393

394+
if old_field.description != new_field.description:
395+
schema_changes.append(
396+
SafeChange(
397+
SafeChangeType.DESCRIPTION_CHANGED,
398+
f"Description of input-field {new_type}.{field_name}"
399+
f' has changed to "{new_field.description}".',
400+
)
401+
)
402+
364403
return schema_changes
365404

366405

@@ -411,6 +450,16 @@ def find_enum_type_changes(
411450
for value_name in values_diff.removed
412451
)
413452

453+
for value_name, (old_value, new_value) in values_diff.persisted.items():
454+
if old_value.description != new_value.description:
455+
schema_changes.append(
456+
SafeChange(
457+
SafeChangeType.DESCRIPTION_CHANGED,
458+
f"Description of enum value {old_type}.{value_name}"
459+
f' has changed to "{new_value.description}".',
460+
)
461+
)
462+
414463
return schema_changes
415464

416465

@@ -487,6 +536,15 @@ def find_field_changes(
487536
)
488537
)
489538

539+
if old_field.description != new_field.description:
540+
schema_changes.append(
541+
SafeChange(
542+
SafeChangeType.DESCRIPTION_CHANGED,
543+
f"Description of field {old_type}.{field_name}"
544+
f' has changed to "{new_field.description}".',
545+
)
546+
)
547+
490548
return schema_changes
491549

492550

@@ -557,7 +615,7 @@ def find_arg_changes(
557615
f" added a defaultValue {new_value_str}.",
558616
)
559617
)
560-
else:
618+
elif str(old_arg.type) != str(new_arg.type):
561619
schema_changes.append(
562620
SafeChange(
563621
SafeChangeType.ARG_CHANGED_KIND_SAFE,
@@ -567,6 +625,15 @@ def find_arg_changes(
567625
)
568626
)
569627

628+
if old_arg.description != new_arg.description:
629+
schema_changes.append(
630+
SafeChange(
631+
SafeChangeType.DESCRIPTION_CHANGED,
632+
f"Description of argument {old_type}.{field_name}"
633+
f'({arg_name}) has changed to "{new_arg.description}".',
634+
)
635+
)
636+
570637
for arg_name, new_arg in args_diff.added.items():
571638
if is_required_argument(new_arg):
572639
schema_changes.append(

‎tests/utilities/test_find_schema_changes.py‎

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,26 @@ def should_detect_if_a_type_was_added():
2323
(SafeChangeType.TYPE_ADDED, "Type2 was added."),
2424
]
2525

26+
def should_detect_a_type_changing_description():
27+
new_schema = build_schema(
28+
"""
29+
"New Description"
30+
type Type1
31+
"""
32+
)
33+
34+
old_schema = build_schema(
35+
"""
36+
type Type1
37+
"""
38+
)
39+
assert find_schema_changes(old_schema, new_schema) == [
40+
(
41+
SafeChangeType.DESCRIPTION_CHANGED,
42+
'Description of Type1 has changed to "New Description".',
43+
),
44+
]
45+
2646
def should_detect_if_a_field_was_added():
2747
old_schema = build_schema(
2848
"""
@@ -44,6 +64,32 @@ def should_detect_if_a_field_was_added():
4464
(SafeChangeType.FIELD_ADDED, "Field Query.bar was added."),
4565
]
4666

67+
def should_detect_a_field_changing_description():
68+
old_schema = build_schema(
69+
"""
70+
type Query {
71+
foo: String
72+
bar: String
73+
}
74+
"""
75+
)
76+
77+
new_schema = build_schema(
78+
"""
79+
type Query {
80+
foo: String
81+
"New Description"
82+
bar: String
83+
}
84+
"""
85+
)
86+
assert find_schema_changes(old_schema, new_schema) == [
87+
(
88+
SafeChangeType.DESCRIPTION_CHANGED,
89+
'Description of field Query.bar has changed to "New Description".',
90+
),
91+
]
92+
4793
def should_detect_if_a_default_value_was_added():
4894
old_schema = build_schema(
4995
"""
@@ -67,6 +113,33 @@ def should_detect_if_a_default_value_was_added():
67113
),
68114
]
69115

116+
def should_detect_if_an_arg_value_changes_description():
117+
old_schema = build_schema(
118+
"""
119+
type Query {
120+
foo(x: String!): String
121+
}
122+
"""
123+
)
124+
125+
new_schema = build_schema(
126+
"""
127+
type Query {
128+
foo(
129+
"New Description"
130+
x: String!
131+
): String
132+
}
133+
"""
134+
)
135+
assert find_schema_changes(old_schema, new_schema) == [
136+
(
137+
SafeChangeType.DESCRIPTION_CHANGED,
138+
"Description of argument Query.foo(x)"
139+
' has changed to "New Description".',
140+
),
141+
]
142+
70143
def should_detect_if_an_arg_value_changes_safely():
71144
old_schema = build_schema(
72145
"""
@@ -112,6 +185,34 @@ def should_detect_if_a_directive_was_added():
112185
(SafeChangeType.DIRECTIVE_ADDED, "Directive @Foo was added."),
113186
]
114187

188+
def should_detect_if_a_directive_changes_description():
189+
old_schema = build_schema(
190+
"""
191+
directive @Foo on FIELD_DEFINITION
192+
193+
type Query {
194+
foo: String
195+
}
196+
"""
197+
)
198+
199+
new_schema = build_schema(
200+
"""
201+
"New Description"
202+
directive @Foo on FIELD_DEFINITION
203+
204+
type Query {
205+
foo: String
206+
}
207+
"""
208+
)
209+
assert find_schema_changes(old_schema, new_schema) == [
210+
(
211+
SafeChangeType.DESCRIPTION_CHANGED,
212+
'Description of @Foo has changed to "New Description".',
213+
),
214+
]
215+
115216
def should_detect_if_a_directive_becomes_repeatable():
116217
old_schema = build_schema(
117218
"""
@@ -189,3 +290,99 @@ def should_detect_if_a_directive_arg_gets_added():
189290
"An optional argument @Foo(arg1:) was added.",
190291
),
191292
]
293+
294+
def should_detect_if_a_directive_arg_changes_description():
295+
old_schema = build_schema(
296+
"""
297+
directive @Foo(
298+
arg1: String
299+
) on FIELD_DEFINITION
300+
301+
type Query {
302+
foo: String
303+
}
304+
"""
305+
)
306+
307+
new_schema = build_schema(
308+
"""
309+
directive @Foo(
310+
"New Description"
311+
arg1: String
312+
) on FIELD_DEFINITION
313+
314+
type Query {
315+
foo: String
316+
}
317+
"""
318+
)
319+
assert find_schema_changes(old_schema, new_schema) == [
320+
(
321+
SafeChangeType.DESCRIPTION_CHANGED,
322+
'Description of @Foo(Foo) has changed to "New Description".',
323+
),
324+
]
325+
326+
def should_detect_if_an_enum_member_changes_description():
327+
old_schema = build_schema(
328+
"""
329+
enum Foo {
330+
TEST
331+
}
332+
333+
type Query {
334+
foo: String
335+
}
336+
"""
337+
)
338+
339+
new_schema = build_schema(
340+
"""
341+
enum Foo {
342+
"New Description"
343+
TEST
344+
}
345+
346+
type Query {
347+
foo: String
348+
}
349+
"""
350+
)
351+
assert find_schema_changes(old_schema, new_schema) == [
352+
(
353+
SafeChangeType.DESCRIPTION_CHANGED,
354+
'Description of enum value Foo.TEST has changed to "New Description".',
355+
),
356+
]
357+
358+
def should_detect_if_an_input_field_changes_description():
359+
old_schema = build_schema(
360+
"""
361+
input Foo {
362+
x: String
363+
}
364+
365+
type Query {
366+
foo: String
367+
}
368+
"""
369+
)
370+
371+
new_schema = build_schema(
372+
"""
373+
input Foo {
374+
"New Description"
375+
x: String
376+
}
377+
378+
type Query {
379+
foo: String
380+
}
381+
"""
382+
)
383+
assert find_schema_changes(old_schema, new_schema) == [
384+
(
385+
SafeChangeType.DESCRIPTION_CHANGED,
386+
'Description of input-field Foo.x has changed to "New Description".',
387+
),
388+
]

0 commit comments

Comments
 (0)