question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Fragment fields do not work in tests with MockedProvider

See original GitHub issue

Intended outcome: Queries with fragments should pass through all fragment fields in tests.

Actual outcome: Queries with fragments in tests do not pass through the fields from the fragment.

How to reproduce the issue: I have the following fragment + query.

const FRAG= gql`
  fragment FooFields on Foo {
    id
    foobar {
      id
    }
  }
`

const QUERY = gql`
  ${FRAG}
  query fetchFoo (id: ID!) {
     fetchFoo(id: $id) {
       ...FooFields
     }
  }
`

where the query’s schema looks like:

  type Foobar {
     id: ID!
  }
  type Foo {
     id: ID!
     foobar: Foobar!
  }
  extend type Query {
    fetchFoo(id: ID!): Foo!
  }

Performing the query in a jest test with the following:


const fragmentDefaultOptions: DefaultOptions = {
  watchQuery: { fetchPolicy: "no-cache" },
  query: { fetchPolicy: "no-cache" },
};

const mocks = [
  {
    request: {
      query: FETCH_FOO,
      variables: {
        id: "some-foo",
      },
    },
    result: {
      data: {
       fetchFoo: {
         id: "some-foo",
        foobar: {
          id: "some-foobar",
        }
      },
    },
  },
];

...  = render(
      <MockedProvider
        mocks={mocks}
        addTypename={false}
        defaultOptions={fragmentDefaultOptions}
      >
          <SomeComponent />
      </MockedProvider>
)

where SomeComponent performs the call:

  const {
    data,
    error,
    refetch,
    loading,
  } = useQuery(FETCH_FOO, {
    variables: {
      id: fooId,
    },
    fetchPolicy: "cache-and-network",
  });

It seems like if I use ...FooFields, then data.fetchFoo is an empty object in the test only. If I inline the fields:

const QUERY = gql`
  query fetchFoo (id: ID!) {
     fetchFoo(id: $id) {
       id
       foobar {
         id
       }
     }
  }
`

then it works fine both in tests and in the actual app.

Versions

  System:
    OS: Linux 4.19 Ubuntu 20.04.1 LTS (Focal Fossa)
  Binaries:
    Node: 15.0.1 - ~/.nvm/versions/node/v15.0.1/bin/node
    Yarn: 1.22.5 - /usr/bin/yarn
    npm: 7.0.3 - ~/.nvm/versions/node/v15.0.1/bin/npm
  Browsers:
    Firefox: 84.0
  npmPackages:
    @apollo/client: ^3.2.5 => 3.2.5

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:5
  • Comments:11 (1 by maintainers)

github_iconTop GitHub Comments

18reactions
benjamncommented, May 24, 2021

@richardwu Your mocked result objects need __typename fields, so the fragment constraint on BudgetLineItem can match against those objects. Unless you’re using interfaces or unions (which bring possibleTypes into play), that type will most likely have the same name as the fragment constraint: __typename: "BudgetLineItem". When in doubt, just ask what your server would return, and try to approximate that with your mock data.

Since Apollo Client requests the __typename field automatically, and every GraphQL server knows how to provide a __typename for any object type, it’s easy to forget how important that information is when you’re mocking data, but object type information has wide-reaching consequences, not just for fragment matching but many other type-driven client/cache behaviors. If __typename is missing from your mock data, you’re not really testing the same behavior that happens outside of your tests, even if the tests are passing.

7reactions
pimmeecommented, Aug 3, 2021

I’ve spent countless hours struggling with this, and if anyone is running into the same issue: For some reason including the fragment before the query fails when using MockedProvider.

This DOES NOT work:

export const GET_PRESCRIPTIONS = gql`
  ${PrescriptionFragment}
  query GetPrescriptions($patientId: ID!) {
    prescriptions(patientId: $patientId) {
      ...PrescriptionInfo
    }
  }
`;

This DOES work:

export const GET_PRESCRIPTIONS = gql`
  query GetPrescriptions($patientId: ID!) {`
    prescriptions(patientId: $patientId) {
      ...PrescriptionInfo
    }
  }
  ${PrescriptionFragment}
`;
Read more comments on GitHub >

github_iconTop Results From Across the Web

Apollo Boost MockedProvider returns empty object when ...
I have another test using this fragment on a mutation and it works. Edit: package.json "dependencies": { "@apollo/react-hooks": "^4.0.0", ...
Read more >
Testing React components - Apollo GraphQL Docs
The MockedProvider component enables you to define mock responses for individual queries that are executed in your test. This means your test doesn't...
Read more >
How to fix Apollo's MockedProvider returning empty objects for ...
When your query asks for optional fields, but the response does not provide them, it fails silently, and you get an empty response....
Read more >
Testing React components - Apollo GraphQL Docs
Components utilizing React with Apollo Client are no exception. ... However, this will cause the tests to run against an actual backend which...
Read more >
Testing – Angular - GraphQL Code Generator
This guide will explain step-by-step how to test apollo-angular code. ... Make sure the query is also exported -- not just the component ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found