Skip to content

Commit 0ebe024

Browse files
authored
fix the case where list of nullable array containing null values (#314)
fixes #192
1 parent 0173ac7 commit 0ebe024

File tree

3 files changed

+120
-2
lines changed

3 files changed

+120
-2
lines changed

lib/query-validation-visitor.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,11 @@ function validateArrayTypeValue (context, valueTypeDef, typeDefWithDirective, va
227227
// Validate array content
228228
if (value) {
229229
value.forEach((element, index) => {
230+
// Skip null elements - GraphQL's built-in validation handles null checks for non-null types
231+
if (element === null || element === undefined) {
232+
return
233+
}
234+
230235
const iFieldNameFullIndexed = iFieldNameFull ? `${iFieldNameFull}[${index++}]` : `[${index++}]`
231236

232237
if (isInputObjectType(valueTypeDefArray)) {

package-lock.json

Lines changed: 24 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/input-object.test.js

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,5 +194,96 @@ module.exports.test = function (setup, implType) {
194194
})
195195
}
196196
})
197+
198+
describe('Arrays with null values', function () {
199+
const queryVariables = /* GraphQL */`
200+
mutation createBook($input: BookInput) {
201+
createBook(input: $input) {
202+
title
203+
}
204+
}
205+
`
206+
207+
before(async function () {
208+
this.typeDefs = /* GraphQL */`
209+
type Query {
210+
books: [Book]
211+
}
212+
type Book {
213+
title: String
214+
}
215+
type Mutation {
216+
createBook(input: BookInput): Book
217+
}
218+
input BookInput {
219+
title: Int! @constraint(min: 3)
220+
options: [OptionInput]
221+
}
222+
input OptionInput {
223+
id: ID
224+
name: String @constraint(minLength: 2)
225+
}
226+
`
227+
228+
this.request = await setup({ typeDefs: this.typeDefs })
229+
})
230+
231+
it('should handle null values in array of input objects', async function () {
232+
const { body, statusCode } = await this.request
233+
.post('/graphql')
234+
.set('Accept', 'application/json')
235+
.send({
236+
query: queryVariables,
237+
variables: {
238+
input: {
239+
title: 3,
240+
options: [null, { id: '1', name: 'test' }, null]
241+
}
242+
}
243+
})
244+
245+
strictEqual(statusCode, 200)
246+
deepStrictEqual(body, { data: { createBook: null } })
247+
})
248+
249+
it('should handle array with only null values', async function () {
250+
const { body, statusCode } = await this.request
251+
.post('/graphql')
252+
.set('Accept', 'application/json')
253+
.send({
254+
query: queryVariables,
255+
variables: {
256+
input: {
257+
title: 3,
258+
options: [null, null]
259+
}
260+
}
261+
})
262+
263+
strictEqual(statusCode, 200)
264+
deepStrictEqual(body, { data: { createBook: null } })
265+
})
266+
267+
it('should still validate non-null elements when array contains nulls', async function () {
268+
const { body, statusCode } = await this.request
269+
.post('/graphql')
270+
.set('Accept', 'application/json')
271+
.send({
272+
query: queryVariables,
273+
variables: {
274+
input: {
275+
title: 3,
276+
options: [null, { id: '1', name: 'a' }]
277+
}
278+
}
279+
})
280+
281+
isStatusCodeError(statusCode, implType)
282+
strictEqual(body.errors[0].message,
283+
'Variable "$input" got invalid value "a" at "input.options[1].name"' +
284+
valueByImplType(implType, '; Expected type "name_String_minLength_2"') +
285+
'. Must be at least 2 characters in length')
286+
})
287+
})
197288
})
198289
}

0 commit comments

Comments
 (0)