-
Notifications
You must be signed in to change notification settings - Fork 2k
Implement OneOf Input Objects via @oneOf
directive
#3513
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
IvanGoncharov
merged 19 commits into
graphql:main
from
erikkessler1:oneof-implementation-objects
Jun 27, 2023
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
99189d9
Add `oneOf` directive
erikkessler1 534b243
Add `__Type.oneOf`
erikkessler1 25928e3
Validate oneOf types
erikkessler1 24f0d95
Enforce oneOf rules during the validation phase
erikkessler1 15e39f5
Validate oneOf input objects at execution time
erikkessler1 50bb968
Validate oneOf objects at execution time
erikkessler1 36f44d3
Remove oneOf objects
erikkessler1 6f7f8d5
Add test coverage
erikkessler1 ac4bb46
Add another test to increase coverage
benjie a5b4a47
Merge branch 'main' into oneof-implementation-objects
benjie a081f85
Upgrade GraphQLError calls
benjie dc58476
Rename __Type.oneOf to __Type.isOneOf
benjie ec88066
Remove unnecessary return
benjie 77fb4b9
Oops
benjie 5966a1a
Merge branch 'main' into oneof-implementation-objects
benjie e9302ae
Lint
benjie 903555d
Merge branch 'main' into oneof-implementation-objects
erikkessler1 84a87ee
Fix lint violations
erikkessler1 cfc68cd
Address PR feedback
erikkessler1 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
IvanGoncharov marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
import { describe, it } from 'mocha'; | ||
|
||
import { expectJSON } from '../../__testUtils__/expectJSON.js'; | ||
|
||
import { parse } from '../../language/parser.js'; | ||
|
||
import { buildSchema } from '../../utilities/buildASTSchema.js'; | ||
|
||
import type { ExecutionResult } from '../execute.js'; | ||
import { execute } from '../execute.js'; | ||
|
||
const schema = buildSchema(` | ||
type Query { | ||
test(input: TestInputObject!): TestObject | ||
} | ||
|
||
input TestInputObject @oneOf { | ||
a: String | ||
b: Int | ||
} | ||
|
||
type TestObject { | ||
a: String | ||
b: Int | ||
} | ||
`); | ||
|
||
function executeQuery( | ||
query: string, | ||
rootValue: unknown, | ||
variableValues?: { [variable: string]: unknown }, | ||
): ExecutionResult | Promise<ExecutionResult> { | ||
return execute({ schema, document: parse(query), rootValue, variableValues }); | ||
IvanGoncharov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
describe('Execute: Handles OneOf Input Objects', () => { | ||
describe('OneOf Input Objects', () => { | ||
const rootValue = { | ||
test({ input }: { input: { a?: string; b?: number } }) { | ||
return input; | ||
IvanGoncharov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}, | ||
}; | ||
|
||
it('accepts a good default value', () => { | ||
const query = ` | ||
query ($input: TestInputObject! = {a: "abc"}) { | ||
test(input: $input) { | ||
a | ||
b | ||
} | ||
} | ||
`; | ||
const result = executeQuery(query, rootValue); | ||
|
||
expectJSON(result).toDeepEqual({ | ||
data: { | ||
test: { | ||
a: 'abc', | ||
b: null, | ||
IvanGoncharov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}, | ||
}, | ||
}); | ||
benjie marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}); | ||
|
||
it('rejects a bad default value', () => { | ||
const query = ` | ||
query ($input: TestInputObject! = {a: "abc", b: 123}) { | ||
benjie marked this conversation as resolved.
Show resolved
Hide resolved
|
||
test(input: $input) { | ||
a | ||
b | ||
} | ||
} | ||
`; | ||
const result = executeQuery(query, rootValue); | ||
|
||
expectJSON(result).toDeepEqual({ | ||
data: { | ||
test: null, | ||
}, | ||
errors: [ | ||
{ | ||
locations: [{ column: 23, line: 3 }], | ||
message: | ||
// This type of error would be caught at validation-time | ||
// hence the vague error message here. | ||
'Argument "input" of non-null type "TestInputObject!" must not be null.', | ||
benjie marked this conversation as resolved.
Show resolved
Hide resolved
IvanGoncharov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
path: ['test'], | ||
}, | ||
], | ||
}); | ||
}); | ||
|
||
it('accepts a good variable', () => { | ||
const query = ` | ||
query ($input: TestInputObject!) { | ||
test(input: $input) { | ||
a | ||
b | ||
} | ||
} | ||
`; | ||
const result = executeQuery(query, rootValue, { input: { a: 'abc' } }); | ||
|
||
expectJSON(result).toDeepEqual({ | ||
data: { | ||
test: { | ||
a: 'abc', | ||
b: null, | ||
}, | ||
}, | ||
}); | ||
}); | ||
|
||
it('accepts a good variable with an undefined key', () => { | ||
const query = ` | ||
query ($input: TestInputObject!) { | ||
test(input: $input) { | ||
a | ||
b | ||
} | ||
} | ||
`; | ||
const result = executeQuery(query, rootValue, { | ||
input: { a: 'abc', b: undefined }, | ||
}); | ||
|
||
expectJSON(result).toDeepEqual({ | ||
data: { | ||
test: { | ||
a: 'abc', | ||
b: null, | ||
}, | ||
}, | ||
}); | ||
}); | ||
|
||
it('rejects a variable with multiple non-null keys', () => { | ||
const query = ` | ||
query ($input: TestInputObject!) { | ||
test(input: $input) { | ||
a | ||
b | ||
} | ||
} | ||
`; | ||
const result = executeQuery(query, rootValue, { | ||
input: { a: 'abc', b: 123 }, | ||
}); | ||
|
||
expectJSON(result).toDeepEqual({ | ||
errors: [ | ||
{ | ||
locations: [{ column: 16, line: 2 }], | ||
message: | ||
'Variable "$input" got invalid value { a: "abc", b: 123 }; Exactly one key must be specified for OneOf type "TestInputObject".', | ||
}, | ||
], | ||
}); | ||
}); | ||
|
||
it('rejects a variable with multiple nullable keys', () => { | ||
const query = ` | ||
query ($input: TestInputObject!) { | ||
test(input: $input) { | ||
a | ||
b | ||
} | ||
} | ||
`; | ||
const result = executeQuery(query, rootValue, { | ||
input: { a: 'abc', b: null }, | ||
}); | ||
|
||
expectJSON(result).toDeepEqual({ | ||
errors: [ | ||
{ | ||
locations: [{ column: 16, line: 2 }], | ||
message: | ||
'Variable "$input" got invalid value { a: "abc", b: null }; Exactly one key must be specified for OneOf type "TestInputObject".', | ||
}, | ||
], | ||
}); | ||
}); | ||
benjie marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}); | ||
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.