Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/utilities/__tests__/coerceInputValue-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,7 @@ describe('coerceInputLiteral', () => {
test('{ a: null }', testOneOfInputObj, undefined);
test('{ a: 1 }', testOneOfInputObj, undefined);
test('{ a: "abc", b: "def" }', testOneOfInputObj, undefined);
test('{ a: "abc", c: "def" }', testOneOfInputObj, undefined);
test('{}', testOneOfInputObj, undefined);
test('{ c: "abc" }', testOneOfInputObj, undefined);
});
Expand Down
30 changes: 10 additions & 20 deletions src/utilities/__tests__/validateInputValue-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -443,34 +443,31 @@ describe('validateInputValue', () => {
});

it('returns error for an unknown field', () => {
// TODO: not technically a OneOf error, as the OneOf validation assumes known fields
test({ foo: 123, unknownField: 123 }, TestInputObject, [
{
error:
'Expected value of type "TestInputObject" not to include unknown field "unknownField", found: { foo: 123, unknownField: 123 }.',
path: [],
},
{
error:
'Within OneOf Input Object type "TestInputObject", exactly one field must be specified, and the value for that field must be non-null.',
path: [],
},
]);
});

it('returns error for a misspelled field', () => {
// TODO: technically also a OneOf error, as the OneOf validation assumes known fields, so there are no errors here
test({ bart: 123 }, TestInputObject, [
{
error:
'Expected value of type "TestInputObject" not to include unknown field "bart". Did you mean "bar"? Found: { bart: 123 }.',
path: [],
},
{
error:
'Within OneOf Input Object type "TestInputObject", exactly one field must be specified, and the value for that field must be non-null.',
path: [],
},
]);
});

it('returns error for a misspelled field (no suggestions)', () => {
// TODO: technically also a OneOf error, as the OneOf validation assumes known fields, so there are no errors here
test(
{ bart: 123 },
TestInputObject,
Expand All @@ -480,6 +477,11 @@ describe('validateInputValue', () => {
'Expected value of type "TestInputObject" not to include unknown field "bart", found: { bart: 123 }.',
path: [],
},
{
error:
'Within OneOf Input Object type "TestInputObject", exactly one field must be specified, and the value for that field must be non-null.',
path: [],
},
],
true,
);
Expand Down Expand Up @@ -1016,34 +1018,22 @@ describe('validateInputLiteral', () => {
});

it('returns error for an unknown field', () => {
// TODO: not technically a OneOf error, as the OneOf validation assumes known fields
test('{ foo: 123, unknownField: 123 }', TestInputObject, [
{
error:
'Expected value of type "TestInputObject" not to include unknown field "unknownField", found: { foo: 123, unknownField: 123 }.',
path: [],
},
{
error:
'Within OneOf Input Object type "TestInputObject", exactly one field must be specified, and the value for that field must be non-null.',
path: [],
},
]);
});

it('returns error for a misspelled field', () => {
// TODO: not technically a OneOf error, as the OneOf validation assumes known fields
test('{ foo: 123, bart: 123 }', TestInputObject, [
{
error:
'Expected value of type "TestInputObject" not to include unknown field "bart". Did you mean "bar"? Found: { foo: 123, bart: 123 }.',
path: [],
},
{
error:
'Within OneOf Input Object type "TestInputObject", exactly one field must be specified, and the value for that field must be non-null.',
path: [],
},
]);
});

Expand Down
12 changes: 8 additions & 4 deletions src/utilities/validateInputValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ function validateInputValueImpl(
if (inputValue[fieldName] === undefined) {
continue;
}
fields.push(fieldName);
if (!Object.hasOwn(fieldDefs, fieldName)) {
const suggestion = hideSuggestions
? ''
Expand All @@ -162,7 +161,9 @@ function validateInputValueImpl(
}: ${inspect(inputValue)}.`,
path,
);
continue;
}
fields.push(fieldName);
}

if (type.isOneOf) {
Expand Down Expand Up @@ -414,6 +415,7 @@ function validateInputLiteralImpl(
}

const fields = valueNode.fields;
const knownFields: Array<(typeof fields)[number]> = [];
// Ensure every provided field is defined.
for (const fieldNode of fields) {
const fieldName = fieldNode.name.value;
Expand All @@ -429,11 +431,13 @@ function validateInputLiteralImpl(
fieldNode,
path,
);
} else {
knownFields.push(fieldNode);
}
}

if (type.isOneOf) {
const isNotExactlyOneField = fields.length !== 1;
const isNotExactlyOneField = knownFields.length !== 1;
if (isNotExactlyOneField) {
reportInvalidLiteral(
context.onError,
Expand All @@ -444,9 +448,9 @@ function validateInputLiteralImpl(
return;
}

const fieldValueNode = fields[0].value;
const fieldValueNode = knownFields[0].value;
if (fieldValueNode.kind === Kind.NULL) {
const fieldName = fields[0].name.value;
const fieldName = knownFields[0].name.value;
reportInvalidLiteral(
context.onError,
getOneOfInputObjectErrorMessage(type),
Expand Down
19 changes: 19 additions & 0 deletions src/validation/__tests__/ValuesOfCorrectTypeRule-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1168,6 +1168,25 @@ describe('Validate: Values of correct type', () => {
},
]);
});

it('Unknown field does not add a oneOf error', () => {
expectErrors(`
{
complicatedArgs {
oneOfArgField(oneOfArg: {
stringField: "abc",
invalidField: 123
})
}
}
`).toDeepEqual([
{
message:
'Expected value of type "OneOfInput" not to include unknown field "invalidField". Did you mean "intField"? Found: { stringField: "abc", invalidField: 123 }.',
locations: [{ line: 6, column: 17 }],
},
]);
});
});

describe('Directive arguments', () => {
Expand Down
Loading