8

According to the docs, I should be able to to mock graphql errors in order to test.

To simulate GraphQL errors, simply define errors along with any data in your result.

const dogMock = {
  // ...
  result: {
    errors: [{ message: "Error!" }],
  },
};

However the error is causing my test to fail outright. It's working as expected for a Query but the docs say it works the same for a Mutation as well.

For the sake of simplicity, the error case for mutations hasn’t been shown here, but testing Mutation errors is exactly the same as testing Query errors: just add an error to the mock, fire the mutation, and check the UI for error messages.

Here is my code...

Component

class Example extends Component {
  state = {email: ''};

  render() {
    return (
      <div>
        <Mutation mutation={EXAMPLE_MUTATION} variables={this.state}>
          {(signin, {error, loading}) => {
            if(error)
              return <p data-test="graphql-error">{error.message}</p>;

            return (
              <form method="post" onSubmit={async e => {
                e.preventDefault();
                await signin();
                this.setState({email: ''});
              }}>
                <fieldset disabled={loading} aria-busy={loading}>
                  <label htmlFor="email">
                    Email
                    <input type="email" name="email" placeholder="email" value={this.state.email} onChange={this.saveToState} />
                  </label>
                  <div>
                    <input type="submit" value="Example"/>
                  </div>
                </fieldset>
              </form>
            )
          }}
        </Mutation>
      </div>
    );
  }

  saveToState = e => this.setState({[e.target.name]: e.target.value});
}

Mutation

const EXAMPLE_MUTATION = gql`
  mutation EXAMPLE_MUTATION($email: String!){
    example(email: $email){
      email
      name
    }
  }
`;

Test


describe('<Example />', () => {
  it('handles errors properly', async () => {
    const wrapper = mount(
      <MockedProvider mocks={[{
        request: {query: EXAMPLE_MUTATION, variables: {email: '[email protected]'}},
        result: {errors: [{message: "There was an error"}]}}]}>
        <Example />
      </MockedProvider>
    );

    type(wrapper, 'email', '[email protected]');
    wrapper.update();
    wrapper.find(`form`).simulate('submit');

    // form is busy + contains inputs
    expect(toJSON(wrapper.find('form'))).toMatchSnapshot();

    await wait();
    wrapper.update();

    // test fails before ever getting here

    const err = wrapper.find('[data-test="graphql-error"]');
    expect(err.text()).toEqual('There was an error');

    console.log(err.debug())
    console.log(err.text())
  });

The test fails with my error instead of rendering it to the page like I would have expected.

    GraphQL error: There was an error

      at new ApolloError (node_modules/src/errors/ApolloError.ts:56:5)
      at Object.next (node_modules/src/core/QueryManager.ts:258:21)
      at notifySubscription (node_modules/zen-observable/lib/Observable.js:130:18)
      at onNotify (node_modules/zen-observable/lib/Observable.js:165:3)
      at SubscriptionObserver.next (node_modules/zen-observable/lib/Observable.js:219:7)
      at node_modules/react-apollo/test-utils.js:937:38
      at Timeout.callback (node_modules/jsdom/lib/jsdom/browser/Window.js:678:19)

Where did I go wrong? Any help would be much appreciated!

2 Answers 2

3

Create ApolloError object and pass it as error field in the mock variable

   const apolloError = new ApolloError({
      graphQLErrors: [new GraphQLError('SLOT_ALREADY_BOOKED')],
      networkError: null,
    });
    
    <MockedProvider
      mocks={[
        {
          error: apolloError,
          request: { query: EXAMPLE_MUTATION, variables: { email: '[email protected]' } },
        },
      ]}
    >
      <Example />
    </MockedProvider>;
Sign up to request clarification or add additional context in comments.

Comments

0

When mutation fails, react-apollo throws an error if no onError prop is provided to Mutation component (source code here). If you leave the error uncaught, test runner interprets it as a failed test.

This can be worked around by either preventing the error from throwing by providing a dummy onError prop:

<Mutation mutation={EXAMPLE_MUTATION} variables={this.state} onError={() => {}}>

or by wrapping mutation call in a try...catch (await is important since the error is asynchronous):

try {
  await signin();
} catch (error) {
  // do smth with the error here
}

There's a relevant GitHub issue.

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.