You must register a useMutation hook via the `GraphGLHooksProvider`

Tests from redwoodblog tutorial are failing without any changes/modification.

I was getting this on 6.4.0. Upgraded to 6.5.1 and same issue.

It is only the *Page.test.tsx files that render a Cell. For example, ContactPage and ArticlePage both faile but AboutPage does not.

  ● ContactPage › renders successfully

    expect(received).not.toThrow()

    Error name:    "Error"
    Error message: "You must register a useMutation hook via the `GraphQLHooksProvider`"

          30 | const ContactPage = () => {
          31 |   const formMethods = useForm({mode: 'onBlur'})
        > 32 |   const [create, {loading, error}] = useMutation<
             |                                                 ^
          33 |     CreateContactMutation,
          34 |     CreateContactMutationVariables
          35 |   >(CREATE_CONTACT, {

          at Object.useMutation (node_modules/@redwoodjs/web/dist/components/GraphQLHooksProvider.js:19:11)
          at useMutation (node_modules/@redwoodjs/web/dist/components/GraphQLHooksProvider.js:53:57)
          at ContactPage (web/src/pages/ContactPage/ContactPage.tsx:32:49)
          at renderWithHooks (node_modules/react-dom/cjs/react-dom.development.js:16305:18)
          at mountIndeterminateComponent (node_modules/react-dom/cjs/react-dom.development.js:20074:13)
          at beginWork (node_modules/react-dom/cjs/react-dom.development.js:21587:16)
          at beginWork$1 (node_modules/react-dom/cjs/react-dom.development.js:27426:14)
          at performUnitOfWork (node_modules/react-dom/cjs/react-dom.development.js:26560:12)
          at workLoopSync (node_modules/react-dom/cjs/react-dom.development.js:26466:5)
          at renderRootSync (node_modules/react-dom/cjs/react-dom.development.js:26434:7)
          at recoverFromConcurrentError (node_modules/react-dom/cjs/react-dom.development.js:25850:20)
          at performConcurrentWorkOnRoot (node_modules/react-dom/cjs/react-dom.development.js:25750:22)
          at flushActQueue (node_modules/react/cjs/react.development.js:2667:24)
          at act (node_modules/react/cjs/react.development.js:2582:11)
          at node_modules/@redwoodjs/testing/node_modules/@testing-library/react/dist/act-compat.js:46:25
          at renderRoot (node_modules/@redwoodjs/testing/node_modules/@testing-library/react/dist/pure.js:161:26)
          at render (node_modules/@redwoodjs/testing/node_modules/@testing-library/react/dist/pure.js:247:10)
          at customRender (node_modules/@redwoodjs/testing/dist/web/customRender.js:14:29)
          at web/src/pages/ContactPage/ContactPage.test.tsx:11:13
          at Object.<anonymous> (node_modules/expect/build/toThrowMatchers.js:74:11)
          at Object.throwingMatcher [as toThrow] (node_modules/expect/build/index.js:320:21)
          at Object.toThrow (web/src/pages/ContactPage/ContactPage.test.tsx:12:12)

      10 |     expect(() => {
      11 |       render(<ContactPage />)
    > 12 |     }).not.toThrow()
         |            ^
      13 |   })
      14 | })
      15 |

      at Object.toThrow (web/src/pages/ContactPage/ContactPage.test.tsx:12:12)

An individual on my team was able to fix this using the following (Thanks Weronika!) :

import { RedwoodApolloProvider } from '@redwoodjs/web/apollo'

import ArticlePage from './ArticlePage'
import React from "react";

//   Improve this test with help from the Redwood Testing Doc:
//   https://redwoodjs.com/docs/testing#testing-pages-layouts

function componentWrappedInRedwoodProviders(children: string | number | boolean | React.JSX.Element | Iterable<React.ReactNode>) {
  return (
    <RedwoodApolloProvider>{children}</RedwoodApolloProvider>
  )
}
describe('ArticlePage', () => {
  it('renders successfully', () => {
    expect(() => {
      render(componentWrappedInRedwoodProviders(<ArticlePage />))
    }).not.toThrow()
  })
})

Is there a way to avoid this?

I’ll add that the docs do discuss mocking cells, but it doesn’t mention that you have to.

I’m imagining something like:

import { render } from '@redwoodjs/testing/web'
import {RedwoodApolloProvider} from "@redwoodjs/web/apollo";

const AllTheProviders = ({children}: {children: React.ReactNode}) => {
  return (
    <RedwoodApolloProvider>
        {children}
    </RedwoodApolloProvider>
  )
}

const customRender = (
  ui: ReactElement,
  options?: Omit<RenderOptions, 'wrapper'>,
) => render(ui, {wrapper: AllTheProviders, ...options})

export * from '@redwoodjs/testing/web'
export {customRender as render}

Based on: Setup | Testing Library

Hey @ed-snodgrass, spent quite a bit of time debugging this one and think I finally have a lead. Does your project’s @redwoodjs/testing package have other node_modules nested in it like @redwoodjs/web?

Here’s a project I have that has the same bug and I’m seeing quite a bit of nesting going on which isn’t a good sign:

% ls ./node_modules/@redwoodjs/testing/node_modules/          
@apollo			@redwoodjs		@types			pretty-format		react-hot-toast
@reach			@testing-library	ansi-styles		react-helmet-async	react-is
% ls ./node_modules/@redwoodjs/testing/node_modules/@redwoodjs 
router	web

My theory is that there’s different instances of GraphQLHooksProvider being imported which is why one is missing query, mutation, etc. and throws.

Ok I think I fixed it by updating the versions of the react types packages in the web package.json:

I can see why this would be a problem. It’s not good to pin the versions of dependencies that are widely used across the ecosystem. We should rethink what we’re doing here framework side.

This update resolved the issue for me as well

2 Likes