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

MockedLink expects optional variables with default values to be defined in mocked queries #8023

Open
dannycochran opened this issue Apr 23, 2021 · 2 comments · May be fixed by #11806
Open

Comments

@dannycochran
Copy link
Contributor

dannycochran commented Apr 23, 2021

Intended outcome:

Given this query:

query GetFoo($id: ID!, $includeFooBar: Boolean = false) {
  ...
}

Be able to provide a mock which does not include a value for $includeFooBar if my actual invocation isn't passing it, e.g:

Actual invocation in my app:

// getFoo.ts

// Never passes `includeFooBar
const response = useQuery(GetFooDocument, { variables: { id: 5 } });

Mocks setup:

// testGetFoo.spec.ts

const mocks: ApolloMockedResponse<any>[] = [{
  response: { ... }
  request: {
    query: GetFooDocument,
    variables: { id: 5 }
  }
}]

This mock should work correctly since my actual invocation is not passing includeFooBar

Actual outcome:

The mock fails because includeFooBar is expected to be explicitly passed in the mock above. The comparison of variables here flushes out the default values and does not account for them being optional:

if (equal(requestVariables, mockedResponseVariables)) {

How to reproduce the issue:

The code snippet above.

Versions

System:
OS: macOS 11.2.2
Binaries:
Node: 12.18.4 - /usr/local/bin/node
Yarn: 1.22.4 - ~/npm-global/bin/yarn
npm: 6.14.6 - /usr/local/bin/npm
Browsers:
Chrome: 90.0.4430.85
Safari: 14.0.3
npmPackages:
@apollo/client: ^3.3.15 => 3.3.15
apollo-upload-client: 14.1.3 => 14.1.3
apollo3-cache-persist: 0.9.1 => 0.9.1
npmGlobalPackages:
apollo: 2.27.0

@phryneas
Copy link
Member

phryneas commented Apr 24, 2024

There is no way to test a query hook which gql includes an optional variable, therefore breaking graphql RFC spec.

I'm sorry, but I can't seem to reproduce that.

This is what I did (modifying an existing test):

    const query: TypedDocumentNode<Data, Variables> = gql`
      query GetTodo($id: ID = 1) {
        todo(id: $id) {
          id
          name
          completed
        }
      }
    `;

    const mocks = [
      {
        request: { query, variables: { id: 1 } },
        result: {
          data: { todo: { id: 1, name: "Take out trash", completed: false } },
        },
        delay: 20,
      },
      // refetch
      {
        request: { query, variables: { id: 1 } },
        result: {
          data: { todo: { id: 1, name: "Take out trash", completed: true } },
        },
        delay: 20,
      },
    ];

// in a component:

      const { data, refetch } = useSuspenseQuery(query, {
        // intentionally use no-cache to allow us to verify each suspense
        // component is independent of each other
        fetchPolicy: "no-cache",
        variables: {},
        queryKey: [name],
      });

This works for me without problems.

Could you please create a reproduction that shows this problem?

@phryneas
Copy link
Member

That said, I think I can see the confusion here: By the time the query reaches the MockLink, the variable defaults have already been filled in, so if you send a query with variables: {} from Apollo Client, and there's a variable defined with a default value like GetTodo($id: ID = 1), then the Link will already be called with variables: { id: 1 }.
Your mocks need to contain these values to match up.

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

Successfully merging a pull request may close this issue.

3 participants