Skip to content

Commit 5ed0ac9

Browse files
Fixed mutation input type generation for enum and custom scalar list operations. The "push", "pop", and "set" operations in list mutation inputs for enums and custom scalars are now correctly marked as optional instead of required.
1 parent 38d26bd commit 5ed0ac9

File tree

4 files changed

+416
-20
lines changed

4 files changed

+416
-20
lines changed

.changeset/social-banks-greet.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@neo4j/graphql": patch
3+
---
4+
5+
Fixed mutation input type generation for enum and custom scalar list operations. The `push`, `pop`, and `set` operations in list mutation inputs for enums and custom scalars are now correctly marked as optional instead of required.

packages/graphql/src/schema/make-augmented-schema.ts

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -183,57 +183,57 @@ function makeAugmentedSchema({
183183
name: `${enumType.name.value}ListEnumScalarMutations`,
184184
description: `Mutations for a list for ${enumType.name.value}`,
185185
fields: {
186-
set: { type: `[${enumType.name.value}!]!` },
187-
push: { type: `[${enumType.name.value}!]!` },
186+
set: { type: `[${enumType.name.value}!]` },
187+
push: { type: `[${enumType.name.value}!]` },
188188
pop: { type: enumType.name.value },
189189
},
190190
});
191191
});
192192

193193
// Generates the filters for custom scalars
194-
Array.from(scalarTypes.values()).forEach((enumType) => {
194+
Array.from(scalarTypes.values()).forEach((scalarType) => {
195195
composer.createInputTC({
196-
name: `${enumType.name.value}ScalarFilters`,
197-
description: `${enumType.name.value} filters`,
196+
name: `${scalarType.name.value}ScalarFilters`,
197+
description: `${scalarType.name.value} filters`,
198198
fields: {
199199
eq: {
200-
type: enumType.name.value,
200+
type: scalarType.name.value,
201201
},
202-
in: { type: `[${enumType.name.value}!]` },
202+
in: { type: `[${scalarType.name.value}!]` },
203203
},
204204
});
205205

206206
composer.createInputTC({
207-
name: `${enumType.name.value}ListScalarFilters`,
208-
description: `${enumType.name.value} filters`,
207+
name: `${scalarType.name.value}ListScalarFilters`,
208+
description: `${scalarType.name.value} filters`,
209209
fields: {
210210
eq: {
211-
type: `[${enumType.name.value}!]`,
211+
type: `[${scalarType.name.value}!]`,
212212
},
213213
includes: {
214-
type: enumType.name.value,
214+
type: scalarType.name.value,
215215
},
216216
},
217217
});
218218
});
219219

220220
// Generates the mutations for custom scalars
221-
Array.from(scalarTypes.values()).forEach((enumType) => {
221+
Array.from(scalarTypes.values()).forEach((scalarType) => {
222222
composer.createInputTC({
223-
name: `${enumType.name.value}ScalarMutations`,
224-
description: `${enumType.name.value} filters`,
223+
name: `${scalarType.name.value}ScalarMutations`,
224+
description: `${scalarType.name.value} filters`,
225225
fields: {
226-
set: { type: enumType.name.value },
226+
set: { type: scalarType.name.value },
227227
},
228228
});
229229

230230
composer.createInputTC({
231-
name: `${enumType.name.value}ListScalarMutations`,
232-
description: `Mutations for a list for ${enumType.name.value}`,
231+
name: `${scalarType.name.value}ListScalarMutations`,
232+
description: `Mutations for a list for ${scalarType.name.value}`,
233233
fields: {
234-
set: { type: `[${enumType.name.value}!]!` },
235-
push: { type: `[${enumType.name.value}!]!` },
236-
pop: { type: enumType.name.value },
234+
set: { type: `[${scalarType.name.value}!]` },
235+
push: { type: `[${scalarType.name.value}!]` },
236+
pop: { type: scalarType.name.value },
237237
},
238238
});
239239
});
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
20+
import { GraphQLScalarType, Kind } from "graphql";
21+
import type { UniqueType } from "../../utils/graphql-types";
22+
import { TestHelper } from "../../utils/tests-helper";
23+
24+
describe("https://github.com/neo4j/graphql/issues/6422", () => {
25+
const testHelper = new TestHelper();
26+
let typeDefs: string;
27+
28+
let MutationTest: UniqueType;
29+
const GraphQLUpperCaseString = new GraphQLScalarType({
30+
name: "UpperCaseString",
31+
description: "The `UpperCaseString` scalar type returns all strings in upper case",
32+
serialize: (value) => {
33+
if (typeof value === "string") {
34+
return value.toUpperCase();
35+
}
36+
37+
throw new Error("Unknown type");
38+
},
39+
parseValue: (value) => {
40+
if (typeof value === "string") {
41+
return value.toUpperCase();
42+
}
43+
44+
throw new Error("Unknown type");
45+
},
46+
parseLiteral: (ast) => {
47+
if (ast.kind === Kind.STRING) {
48+
return ast.value.toUpperCase();
49+
}
50+
51+
return undefined;
52+
},
53+
});
54+
55+
beforeEach(async () => {
56+
MutationTest = testHelper.createUniqueType("MutationTest");
57+
58+
typeDefs = /* GraphQL */ `
59+
scalar CustomScalar
60+
type ${MutationTest} @mutation(operations: [CREATE, UPDATE, DELETE]) @node @subscription(events: []) {
61+
enumValue: [EnumMutationTestEnumValue!]!
62+
myScalar: [CustomScalar!]!
63+
intValue: [Int!]!
64+
stringValue: [String!]!
65+
}
66+
67+
"""
68+
enum test
69+
"""
70+
enum EnumMutationTestEnumValue {
71+
ONE
72+
TWO
73+
THREE
74+
}
75+
`;
76+
77+
await testHelper.executeCypher(`
78+
CREATE(:${MutationTest} { enumValue: ["ONE", "TWO"], myScalar: ["TEST", "TEST2"], intValue: [1, 2], stringValue: ["test", "test2"] })
79+
`);
80+
81+
await testHelper.initNeo4jGraphQL({
82+
typeDefs,
83+
resolvers: { CustomScalar: GraphQLUpperCaseString },
84+
});
85+
});
86+
87+
afterEach(async () => {
88+
await testHelper.close();
89+
});
90+
91+
test("It should be possible to push an enum to an enum list", async () => {
92+
const query = /* GraphQL */ `
93+
mutation {
94+
${MutationTest.operations.update}(
95+
update: {
96+
enumValue: {
97+
push: [THREE]
98+
}
99+
}
100+
) {
101+
${MutationTest.plural} {
102+
enumValue
103+
}
104+
}
105+
}
106+
`;
107+
108+
const queryResult = await testHelper.executeGraphQL(query);
109+
expect(queryResult.errors).toBeUndefined();
110+
expect(queryResult.data).toEqual({
111+
[MutationTest.operations.update]: {
112+
[MutationTest.plural]: [
113+
{
114+
enumValue: expect.toIncludeSameMembers(["ONE", "TWO", "THREE"]),
115+
},
116+
],
117+
},
118+
});
119+
});
120+
121+
test("It should be possible to push a custom scalar to an custom scalar list", async () => {
122+
const query = /* GraphQL */ `
123+
mutation {
124+
${MutationTest.operations.update}(
125+
update: {
126+
myScalar: {
127+
push: ["test3"]
128+
}
129+
}
130+
) {
131+
${MutationTest.plural} {
132+
myScalar
133+
}
134+
}
135+
}
136+
`;
137+
138+
const queryResult = await testHelper.executeGraphQL(query);
139+
expect(queryResult.errors).toBeUndefined();
140+
expect(queryResult.data).toEqual({
141+
[MutationTest.operations.update]: {
142+
[MutationTest.plural]: [
143+
{
144+
myScalar: expect.toIncludeSameMembers(["TEST", "TEST2", "TEST3"]),
145+
},
146+
],
147+
},
148+
});
149+
});
150+
});

0 commit comments

Comments
 (0)