3

I'm trying to test component that should be updated with new data after running a mutation. I posted example code below. You can find it on GitHub as runnable repository as well.

Unfortunately, I didn't find a way to actually update the store data for the MockedProvider after the mutation. When you run the test you can see that the mutation is being executed and the component gets rendered after that. But since the mutation is not doing anything the new todo item is not added.

Can anyone tell me how to change data with a mutation when using MockedProvider?

The test query and mutation:

const TODOS_QUERY = gql`
  query todos {
    todos {
      title
    }
  }
`

const ADD_TODO_MUTATION = gql`
  mutation addTodo($title: String!) {
    addTodo(title: $title)
  }
`;

The test component:

const Component = () => (
  <Query query={TODOS_QUERY}>
    {
      ({ data }) => {
        console.log('render'); return (
        <Mutation mutation={ADD_TODO_MUTATION}>
          {
            addTodo => (
              <div>
                <button onClick={() => { console.log('addTodo'); addTodo({ variables: { title: 'My new todo' } }) }}>
                  Click me to add a todo!
                </button>

                {
                  (data.todos || []).map(({ title }, index) => (
                    <div key={index} className="todo-item">
                      {title}
                    </div>
                  ))
                }
              </div>
            )
          }
        </Mutation>
      )}
    }
  </Query>
);

The test implementation. This mounts the component using Enzyme, simulates a click on the button to execute the mutation and waits until the component is rendered again.

it('renders without crashing', async () => {
  const mocks = [
    {
      request: {
        query: TODOS_QUERY,
      },
      result: {
        data: {
          todos: [
            {
              title: 'An old todo',
            },
          ],
        },
      },
    },
    {
      request: {
        query: ADD_TODO_MUTATION,
        variables: {
          title: 'My new todo',
        },
      },
      result: {
        data: {
          addTodo: null,
        },
      },
    },
  ];

  const wrapper = mount(
    <MockedProvider mocks={mocks} addTypename={false}>
      <Component />
    </MockedProvider>
  );

  await wait(100);
  wrapper.update();

  console.log(wrapper.debug())

  expect(wrapper.contains('An old todo')).toBe(true);
  expect(wrapper.contains('My new todo')).toBe(false);
  wrapper.find('button').simulate('click');

  await wait(100);
  wrapper.update();

  console.log(wrapper.debug())

  expect(wrapper.contains('An old todo')).toBe(true);
  expect(wrapper.contains('My new todo')).toBe(true);
});

Thanks a lot for your help!

1 Answer 1

1

MockedProvider accepts a cache prop which you can pass your own cache to (same one you’re using when initialising ApolloClient). That should give you automatic cache updates in tests.

You might need to remove the addTypeName=false for it to work, and provide mocks including __typenames.

https://www.apollographql.com/docs/react/api/react-testing/

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.