graphql-tools
graphql-tools copied to clipboard
Cannot mock a field being undefined or null
Issue workflow progress
Progress of the issue based on the Contributor Workflow
- [ ] 1. The issue provides a reproduction available on Github, Stackblitz or CodeSandbox
Make sure to fork this template and run
yarn generatein the terminal.Please make sure the GraphQL Tools package versions under
package.jsonmatches yours. - [ ] 2. A failing test has been provided
- [ ] 3. A local solution has been provided
- [ ] 4. A pull request is pending review
Describe the bug
It seems impossible to simulate a situation where you are returned a partial set of the fields you have requested in a query. This is a very common scenario I want to test. Your UI needs to be able to handle that situation. Seemingly no matter what I try, graphql-mock returns an error when I attempt to do this. I would really appreciate help.
To Reproduce Steps to reproduce the behavior:
const typeDefs = `#graphql
type AuthConfig {
twoFactorEnabled: Boolean
}
type OrgConfig {
auth: AuthConfig
defaultSecurityPolicy: String
}
type Query {
getOrgConfig: OrgConfig
}
`;
const query = /* GraphQL */ `
query getOrgConfig {
getOrgConfig {
auth {
twoFactorEnabled
}
defaultSecurityPolicy
}
}
`;
const mockSchema = addMocksToSchema({
schema: makeExecutableSchema({
typeDefs,
}),
mocks: {
AuthConfig: () => undefined,
},
});
graphql(mockSchema, query).then((result) => console.log("Got result", result));
Expected behavior
I expect a partial return value to be acceptable, as it is in real, not mocked, GQL.
If I try to mock AuthConfig as undefined or null I get the following
Got result {
errors: [
Error: Value returned by the mock for AuthConfig is not an object.......
This make sense given the following code: https://github.com/ardatan/graphql-tools/blob/0f149dc3ac1195c4c4457f703f303e381e4fb44f/packages/mock/src/MockStore.ts#L433
My main question is how are you supposed to simulate a partial result situation if the Mocking library mandates a value for every field.
Environment:
-
OS: Mac
-
├─ @graphql-tools/[email protected] │ └─ @graphql-tools/[email protected] ├─ @graphql-tools/[email protected] │ └─ @graphql-tools/[email protected] ├─ @graphql-tools/[email protected] │ └─ @graphql-tools/[email protected] ├─ @graphql-tools/[email protected] └─ [email protected] └─ @graphql-tools/[email protected]
-
NodeJS: 14.18.1
Nice, since 2018 without null mocks.. it's like graphql doesn't have support for null returns! (current mocks are amazing tbh, its just missing this)
I made a custom solution which I'm yet to try on a real test codebase:
const schema = buildSchema(typeDefs)
const store = createMockStore({schema})
const nullStore = {
_nulls: {} as Record<string, Set<string | undefined>>,
has(key: string, id: string): boolean {
return !!this._nulls[key]?.has(id)
},
add(key: string, id: string) {
if (!this._nulls[key]) {
this._nulls[key] = new Set()
}
this._nulls[key].add(id)
},
delete(key: string, id: string) {
if (!this._nulls[key]) {
return
}
this._nulls[key].delete(id)
},
nullOrGet: (key: string, id: string) => {
return nullStore.has(key, id) ? null : store.get(key, id);
}
}
const schemaWithMocks = addMocksToSchema({
schema,
store,
resolvers: () => ({
Query: {
fooById(_, {id}) { return nullStore.nullOrGet('Foo', id) }
}
})
})
const query = /* GraphQL */ `
query Foo {
foo(id: 1) {
id
}
}
`
nullStore.add('Foo', '1')
const isNull = await graphql({ schema: schemaWithMocks, source: query })
console.log('Got result', isNull);
nullStore.delete('Foo', '1')
const isNotNull = await graphql({ schema: schemaWithMocks, source: query })
console.log('Got result', isNotNull);
Essentially, an if should be null ? then null in each Query/Mutation field resolver that I can control almost like the mock store