Skip to content

Commit 74fcea7

Browse files
fix: escape single quotes in descriptions and deprecation reasons (#2924)
* fix: escape single quotes in descriptions and deprecation reasons * add added/removed message instead for defaulting to 'undefined'
1 parent b3bac0e commit 74fcea7

File tree

8 files changed

+76
-25
lines changed

8 files changed

+76
-25
lines changed

.changeset/bright-pumas-dance.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@graphql-inspector/core": patch
3+
---
4+
5+
Escape single quotes in diff change messages for descriptions and deprecation reasons
6+
7+
Improve description change messages to show "was added" or "was removed" instead of "changed from 'undefined' to X"

packages/core/__tests__/diff/directive.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,11 @@ describe('directive', () => {
9090
// added
9191
expect(change.b.criticality.level).toEqual(CriticalityLevel.NonBreaking);
9292
expect(change.b.type).toEqual('DIRECTIVE_DESCRIPTION_CHANGED');
93-
expect(change.b.message).toEqual(`Directive 'b' description changed from 'undefined' to 'Bbb'`);
93+
expect(change.b.message).toEqual(`Directive 'b' description 'Bbb' was added`);
9494
// removed
9595
expect(change.c.criticality.level).toEqual(CriticalityLevel.NonBreaking);
9696
expect(change.c.type).toEqual('DIRECTIVE_DESCRIPTION_CHANGED');
97-
expect(change.c.message).toEqual(`Directive 'c' description changed from 'Ccc' to 'undefined'`);
97+
expect(change.c.message).toEqual(`Directive 'c' description 'Ccc' was removed`);
9898
});
9999

100100
describe('location', () => {

packages/core/src/diff/changes/argument.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { GraphQLArgument, GraphQLField, GraphQLInterfaceType, GraphQLObjectType } from 'graphql';
22
import { safeChangeForInputValue } from '../../utils/graphql.js';
3-
import { safeString } from '../../utils/string.js';
3+
import { fmt, safeString } from '../../utils/string.js';
44
import {
55
Change,
66
ChangeType,
@@ -13,7 +13,13 @@ import {
1313
function buildFieldArgumentDescriptionChangedMessage(
1414
args: FieldArgumentDescriptionChangedChange['meta'],
1515
): string {
16-
return `Description for argument '${args.argumentName}' on field '${args.typeName}.${args.fieldName}' changed from '${args.oldDescription}' to '${args.newDescription}'`;
16+
if (args.oldDescription === null && args.newDescription !== null) {
17+
return `Description '${fmt(args.newDescription)}' was added to argument '${args.argumentName}' on field '${args.typeName}.${args.fieldName}'`;
18+
}
19+
if (args.newDescription === null && args.oldDescription !== null) {
20+
return `Description '${fmt(args.oldDescription)}' was removed from argument '${args.argumentName}' on field '${args.typeName}.${args.fieldName}'`;
21+
}
22+
return `Description for argument '${args.argumentName}' on field '${args.typeName}.${args.fieldName}' changed from '${fmt(args.oldDescription ?? '')}' to '${fmt(args.newDescription ?? '')}'`;
1723
}
1824

1925
export function fieldArgumentDescriptionChangedFromMeta(

packages/core/src/diff/changes/directive.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { DirectiveLocationEnum, GraphQLArgument, GraphQLDirective, isNonNullType } from 'graphql';
22
import { safeChangeForInputValue } from '../../utils/graphql.js';
3-
import { safeString } from '../../utils/string.js';
3+
import { fmt, safeString } from '../../utils/string.js';
44
import {
55
Change,
66
ChangeType,
@@ -82,9 +82,13 @@ export function directiveAdded(
8282
function buildDirectiveDescriptionChangedMessage(
8383
args: DirectiveDescriptionChangedChange['meta'],
8484
): string {
85-
return `Directive '${args.directiveName}' description changed from '${
86-
args.oldDirectiveDescription ?? 'undefined'
87-
}' to '${args.newDirectiveDescription ?? 'undefined'}'`;
85+
if (args.oldDirectiveDescription === null && args.newDirectiveDescription !== null) {
86+
return `Directive '${args.directiveName}' description '${fmt(args.newDirectiveDescription)}' was added`;
87+
}
88+
if (args.newDirectiveDescription === null && args.oldDirectiveDescription !== null) {
89+
return `Directive '${args.directiveName}' description '${fmt(args.oldDirectiveDescription)}' was removed`;
90+
}
91+
return `Directive '${args.directiveName}' description changed from '${fmt(args.oldDirectiveDescription ?? '')}' to '${fmt(args.newDirectiveDescription ?? '')}'`;
8892
}
8993

9094
export function directiveDescriptionChangedFromMeta(args: DirectiveDescriptionChangedChange) {
@@ -314,7 +318,19 @@ export function directiveArgumentRemoved(
314318
function buildDirectiveArgumentDescriptionChangedMessage(
315319
args: DirectiveArgumentDescriptionChangedChange['meta'],
316320
): string {
317-
return `Description for argument '${args.directiveArgumentName}' on directive '${args.directiveName}' changed from '${args.oldDirectiveArgumentDescription}' to '${args.newDirectiveArgumentDescription}'`;
321+
if (
322+
args.oldDirectiveArgumentDescription === null &&
323+
args.newDirectiveArgumentDescription !== null
324+
) {
325+
return `Description '${fmt(args.newDirectiveArgumentDescription)}' was added to argument '${args.directiveArgumentName}' on directive '${args.directiveName}'`;
326+
}
327+
if (
328+
args.newDirectiveArgumentDescription === null &&
329+
args.oldDirectiveArgumentDescription !== null
330+
) {
331+
return `Description '${fmt(args.oldDirectiveArgumentDescription)}' was removed from argument '${args.directiveArgumentName}' on directive '${args.directiveName}'`;
332+
}
333+
return `Description for argument '${args.directiveArgumentName}' on directive '${args.directiveName}' changed from '${fmt(args.oldDirectiveArgumentDescription ?? '')}' to '${fmt(args.newDirectiveArgumentDescription ?? '')}'`;
318334
}
319335

320336
export function directiveArgumentDescriptionChangedFromMeta(

packages/core/src/diff/changes/enum.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,13 @@ export function enumValueAdded(
8686
}
8787

8888
function buildEnumValueDescriptionChangedMessage(args: EnumValueDescriptionChangedChange['meta']) {
89-
const oldDesc = fmt(args.oldEnumValueDescription ?? 'undefined');
90-
const newDesc = fmt(args.newEnumValueDescription ?? 'undefined');
91-
return args.oldEnumValueDescription === null
92-
? `Description '${newDesc}' was added to enum value '${args.enumName}.${args.enumValueName}'`
93-
: `Description for enum value '${args.enumName}.${args.enumValueName}' changed from '${oldDesc}' to '${newDesc}'`;
89+
if (args.oldEnumValueDescription === null && args.newEnumValueDescription !== null) {
90+
return `Description '${fmt(args.newEnumValueDescription)}' was added to enum value '${args.enumName}.${args.enumValueName}'`;
91+
}
92+
if (args.newEnumValueDescription === null && args.oldEnumValueDescription !== null) {
93+
return `Description '${fmt(args.oldEnumValueDescription)}' was removed from enum value '${args.enumName}.${args.enumValueName}'`;
94+
}
95+
return `Description for enum value '${args.enumName}.${args.enumValueName}' changed from '${fmt(args.oldEnumValueDescription ?? '')}' to '${fmt(args.newEnumValueDescription ?? '')}'`;
9496
}
9597

9698
export function enumValueDescriptionChangedFromMeta(

packages/core/src/diff/changes/field.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
isNonNullType,
99
} from 'graphql';
1010
import { safeChangeForField } from '../../utils/graphql.js';
11+
import { fmt } from '../../utils/string.js';
1112
import {
1213
Change,
1314
ChangeType,
@@ -97,7 +98,13 @@ export function fieldAdded(
9798
}
9899

99100
function buildFieldDescriptionChangedMessage(args: FieldDescriptionChangedChange['meta']) {
100-
return `Field '${args.typeName}.${args.fieldName}' description changed from '${args.oldDescription}' to '${args.newDescription}'`;
101+
if (!args.oldDescription && args.newDescription) {
102+
return `Field '${args.typeName}.${args.fieldName}' description '${fmt(args.newDescription)}' was added`;
103+
}
104+
if (!args.newDescription && args.oldDescription) {
105+
return `Field '${args.typeName}.${args.fieldName}' description '${fmt(args.oldDescription)}' was removed`;
106+
}
107+
return `Field '${args.typeName}.${args.fieldName}' description changed from '${fmt(args.oldDescription)}' to '${fmt(args.newDescription)}'`;
101108
}
102109

103110
export function fieldDescriptionChangedFromMeta(args: FieldDescriptionChangedChange) {
@@ -129,7 +136,8 @@ export function fieldDescriptionChanged(
129136
}
130137

131138
function buildFieldDescriptionAddedMessage(args: FieldDescriptionAddedChange['meta']) {
132-
return `Field '${args.typeName}.${args.fieldName}' has description '${args.addedDescription}'`;
139+
const desc = fmt(args.addedDescription);
140+
return `Field '${args.typeName}.${args.fieldName}' has description '${desc}'`;
133141
}
134142

135143
export function fieldDescriptionAddedFromMeta(args: FieldDescriptionAddedChange) {
@@ -249,7 +257,9 @@ export function fieldDeprecationRemoved(
249257
function buildFieldDeprecationReasonChangedMessage(
250258
args: FieldDeprecationReasonChangedChange['meta'],
251259
) {
252-
return `Deprecation reason on field '${args.typeName}.${args.fieldName}' has changed from '${args.oldDeprecationReason}' to '${args.newDeprecationReason}'`;
260+
const oldReason = fmt(args.oldDeprecationReason);
261+
const newReason = fmt(args.newDeprecationReason);
262+
return `Deprecation reason on field '${args.typeName}.${args.fieldName}' has changed from '${oldReason}' to '${newReason}'`;
253263
}
254264

255265
export function fieldDeprecationReasonChangedFromMeta(args: FieldDeprecationReasonChangedChange) {
@@ -283,7 +293,8 @@ export function fieldDeprecationReasonChanged(
283293
}
284294

285295
function buildFieldDeprecationReasonAddedMessage(args: FieldDeprecationReasonAddedChange['meta']) {
286-
return `Field '${args.typeName}.${args.fieldName}' has deprecation reason '${args.addedDeprecationReason}'`;
296+
const reason = fmt(args.addedDeprecationReason);
297+
return `Field '${args.typeName}.${args.fieldName}' has deprecation reason '${reason}'`;
287298
}
288299

289300
export function fieldDeprecationReasonAddedFromMeta(args: FieldDeprecationReasonAddedChange) {

packages/core/src/diff/changes/input.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { GraphQLInputField, GraphQLInputObjectType, isNonNullType } from 'graphql';
22
import { safeChangeForInputValue } from '../../utils/graphql.js';
33
import { isDeprecated } from '../../utils/is-deprecated.js';
4-
import { safeString } from '../../utils/string.js';
4+
import { fmt, safeString } from '../../utils/string.js';
55
import {
66
Change,
77
ChangeType,
@@ -95,7 +95,8 @@ export function inputFieldAdded(
9595
}
9696

9797
function buildInputFieldDescriptionAddedMessage(args: InputFieldDescriptionAddedChange['meta']) {
98-
return `Input field '${args.inputName}.${args.inputFieldName}' has description '${args.addedInputFieldDescription}'`;
98+
const desc = fmt(args.addedInputFieldDescription);
99+
return `Input field '${args.inputName}.${args.inputFieldName}' has description '${desc}'`;
99100
}
100101

101102
export function inputFieldDescriptionAddedFromMeta(args: InputFieldDescriptionAddedChange) {
@@ -127,7 +128,8 @@ export function inputFieldDescriptionAdded(
127128
function buildInputFieldDescriptionRemovedMessage(
128129
args: InputFieldDescriptionRemovedChange['meta'],
129130
) {
130-
return `Description '${args.removedDescription}' was removed from input field '${args.inputName}.${args.inputFieldName}'`;
131+
const desc = fmt(args.removedDescription);
132+
return `Description '${desc}' was removed from input field '${args.inputName}.${args.inputFieldName}'`;
131133
}
132134

133135
export function inputFieldDescriptionRemovedFromMeta(args: InputFieldDescriptionRemovedChange) {
@@ -159,7 +161,9 @@ export function inputFieldDescriptionRemoved(
159161
function buildInputFieldDescriptionChangedMessage(
160162
args: InputFieldDescriptionChangedChange['meta'],
161163
) {
162-
return `Input field '${args.inputName}.${args.inputFieldName}' description changed from '${args.oldInputFieldDescription}' to '${args.newInputFieldDescription}'`;
164+
const oldDesc = fmt(args.oldInputFieldDescription);
165+
const newDesc = fmt(args.newInputFieldDescription);
166+
return `Input field '${args.inputName}.${args.inputFieldName}' description changed from '${oldDesc}' to '${newDesc}'`;
163167
}
164168

165169
export function inputFieldDescriptionChangedFromMeta(args: InputFieldDescriptionChangedChange) {

packages/core/src/diff/changes/type.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
type GraphQLNamedType,
99
} from 'graphql';
1010
import { getKind } from '../../utils/graphql.js';
11+
import { fmt } from '../../utils/string.js';
1112
import {
1213
Change,
1314
ChangeType,
@@ -134,7 +135,9 @@ export function typeKindChanged(
134135
}
135136

136137
function buildTypeDescriptionChangedMessage(args: TypeDescriptionChangedChange['meta']): string {
137-
return `Description '${args.oldTypeDescription}' on type '${args.typeName}' has changed to '${args.newTypeDescription}'`;
138+
const oldDesc = fmt(args.oldTypeDescription);
139+
const newDesc = fmt(args.newTypeDescription);
140+
return `Description '${oldDesc}' on type '${args.typeName}' has changed to '${newDesc}'`;
138141
}
139142

140143
export function typeDescriptionChangedFromMeta(args: TypeDescriptionChangedChange) {
@@ -164,7 +167,8 @@ export function typeDescriptionChanged(
164167
}
165168

166169
function buildTypeDescriptionRemoved(args: TypeDescriptionRemovedChange['meta']): string {
167-
return `Description '${args.removedTypeDescription}' was removed from object type '${args.typeName}'`;
170+
const desc = fmt(args.removedTypeDescription);
171+
return `Description '${desc}' was removed from object type '${args.typeName}'`;
168172
}
169173

170174
export function typeDescriptionRemovedFromMeta(args: TypeDescriptionRemovedChange) {
@@ -192,7 +196,8 @@ export function typeDescriptionRemoved(
192196
}
193197

194198
function buildTypeDescriptionAddedMessage(args: TypeDescriptionAddedChange['meta']): string {
195-
return `Object type '${args.typeName}' has description '${args.addedTypeDescription}'`;
199+
const desc = fmt(args.addedTypeDescription);
200+
return `Object type '${args.typeName}' has description '${desc}'`;
196201
}
197202

198203
export function typeDescriptionAddedFromMeta(args: TypeDescriptionAddedChange) {

0 commit comments

Comments
 (0)