Skip to content
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

Cannot mock a field being undefined or null #4792

Open
4 tasks
jmtimko5 opened this issue Oct 28, 2022 · 1 comment
Open
4 tasks

Cannot mock a field being undefined or null #4792

jmtimko5 opened this issue Oct 28, 2022 · 1 comment

Comments

@jmtimko5
Copy link

jmtimko5 commented Oct 28, 2022

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 generate in the terminal.

    Please make sure the GraphQL Tools package versions under package.json matches 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:

throw new Error(`Value returned by the mock for ${typeName} is not an object`);

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/delegate@7.0.1
    │ └─ @graphql-tools/schema@7.0.0
    ├─ @graphql-tools/merge@6.2.5
    │ └─ @graphql-tools/schema@7.0.0
    ├─ @graphql-tools/mock@8.7.6
    │ └─ @graphql-tools/schema@9.0.4
    ├─ @graphql-tools/schema@8.3.2
    └─ graphql-config@3.0.3
    └─ @graphql-tools/schema@7.0.0

  • NodeJS: 14.18.1

@Grohden
Copy link

Grohden commented Jan 18, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants