Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apollo Boost MockedProvider returns empty object when using fragment on query

I have a working test using Apollo Boost MockedProvider, Jest and React Testing Library that, when I change the returned fields to a graphQL fragment it stops working. What am I missing?

TicketGql.js

export default class TicketGql {
  static VIEW_FRAGMENT = gql`
    fragment ViewFragment on View {
      viewId
      versionId
      name
      description
      orderedColumns {
        columnId
        name
        descriptions {
          translationId
          lang
          description
        }
      }
    }
  `;

  static GET_TICKET_VIEW = gql`
    query getView($viewId: ID!) {
      view(viewId: $viewId) {
        viewId
        versionId
        name
        description
        orderedColumns {
          columnId
          name
          descriptions {
            translationId
            lang
            description
          }
        }
      }
    }
  `;
}

TicketGql.test.js

...
it('GET_TICKET_VIEW', async () => {
  const currentLang = uniqid('lang_');
  const viewMock = {
    viewId: uniqid('viewId_'),
    versionId: uniqid('versionId_'),
    name: uniqid('name_'),
    description: uniqid('description_'),
    orderedColumns: [],
  };
  _.times(_.random(1, 5), (columnIndex) => {
    viewMock.orderedColumns.push({
      columnId: uniqid('columnId_'),
      name: uniqid('columnId_'),
      descriptions: [],
    });
    _.times(
      _.random(1, 3),
      (descIndex) => viewMock.orderedColumns[columnIndex].descriptions.push({
        translationId: uniqid('translationId_'),
        lang: descIndex === 0 ? currentLang : uniqid('lang_'),
        description: uniqid('description_'),
      }),
    );
  });
  const variables = { viewId: viewMock.viewId };
  const mocks = [
    {
      request: {
        query: TicketGql.GET_TICKET_VIEW,
        variables,
      },
      result: {
        data: {
          view: viewMock,
        },
      },
    },
  ];
  const TicketViewColumns = () => {
    const { data, loading, error } = useQuery(TicketGql.GET_TICKET_VIEW, {
      variables,
    });
    return (
      <div>
        {error}
        <ul>
          {
            loading
              ? 'loading...'
              : (
                data.view.orderedColumns.map((column) => (
                  <li key={column.columnId}>
                    {column.descriptions.find((d) => d.lang === currentLang).description}
                  </li>
                ))
              )
          }
        </ul>
      </div>
    );
  };
  render(
    <MockedProvider mocks={mocks} addTypename={false}>
      <TicketViewColumns />
    </MockedProvider>,
  );
  await waitFor(() => expect(screen.queryAllByRole('listitem'))
    .toHaveLength(viewMock.orderedColumns.length));
 );
...

This test works as it is. But, when I change the GET_TICKET_VIEW to this...

static GET_TICKET_VIEW = gql`
  query getView($viewId: ID!) {
    view(viewId: $viewId) {
      ...ViewFragment
    }
  }
  ${TicketGql.VIEW_FRAGMENT}
`;

... it just stops working. The MockedProvide returns data === { view: {} } instead of the data provided in viewMock, causing error on data.view.orderedColumns.map as data.view.orderedColumns is undefined. I have another test using this fragment on a mutation and it works.

Edit:

package.json

"dependencies": {
  "@apollo/react-hooks": "^4.0.0",
  "apollo-boost": "^0.4.9",
  "graphql": "^15.0.0",
  ...
}
"devDependencies": {
  "@apollo/client": "^3.1.1",
  "@testing-library/jest-dom": "^5.8.0",
  "@testing-library/react": "^10.0.4",
...
}
like image 951
vborges Avatar asked Aug 21 '20 14:08

vborges


1 Answers

Just add __typename to your mock object, when you use a fragment. It isn't required with simple query that is free of fragments/unions, but required if you have it.

read more here

like image 92
PCGeek Avatar answered Sep 22 '22 13:09

PCGeek