'Testing a Next.js app with a custom /pages/_app.js in React-Testing-Library

I'm attempting to follow this guide in Reat-Testing-Library documentation to wrap all the components I want to test. I'm doing this because I need access to the various context providers that are defined in _app.js within the components I'm testing.

This is my /pages/_app.js file:

export class MyApp extends App {
  public componentDidMount() {
    const jssStyles = document.querySelector("#jss-server-side");
    if (jssStyles && jssStyles.parentNode) {
      jssStyles.parentNode.removeChild(jssStyles);
    }
  }
  public render() {
    const { Component, pageProps, apolloClient } = this.props;
    return (
      <Container>
        <StateProvider>
          <ThemeProvider theme={theme}>
            <ApolloProvider client={apolloClient}>
              <CssBaseline />
              <Component {...pageProps} />
              <SignUp />
              <Snackbar />
            </ApolloProvider>
          </ThemeProvider>
        </StateProvider>
      </Container>
    );
  }
}

export default withApollo(MyApp);

This is my /utils/testProviders.js file:

class AllTheProvidersWrapped extends App {
  public componentDidMount() {
    const jssStyles = document.querySelector("#jss-server-side");
    if (jssStyles && jssStyles.parentNode) {
      jssStyles.parentNode.removeChild(jssStyles);
    }
  }
  public render() {
    const { pageProps, apolloClient, children } = this.props;
    return (
      <Container>
        <StateProvider>
          <ThemeProvider theme={theme}>
            <ApolloProvider client={apolloClient}>
              <CssBaseline />
              {React.cloneElement(children, { pageProps })}
              <SignUp />
              <Snackbar />
            </ApolloProvider>
          </ThemeProvider>
        </StateProvider>
      </Container>
    );
  }
}
const AllTheProviders = withApollo(AllTheProvidersWrapped);

const customRender = (ui, options) =>
  render(ui, { wrapper: AllTheProviders, ...options });

export * from "react-testing-library";
export { customRender as render };

This is my /jest.config.js file:

module.exports = {
  testPathIgnorePatterns: ["<rootDir>/.next/", "<rootDir>/node_modules/"],
  moduleDirectories: ["node_modules", "utils", __dirname]
};

And this is an example of a test I'm trying to run:

import React from "react";
import { render, cleanup } from "testProviders";

import OutlinedInput from "./OutlinedInput";

afterEach(cleanup);

const mockProps = {
  id: "name",
  label: "Name",
  fieldStateString: "signUpForm.fields"
};

describe("<OutlinedInput />", (): void => {
  it("renders as snapshot", (): void => {
    const { asFragment } = render(<OutlinedInput {...mockProps} />, {});
    expect(asFragment()).toMatchSnapshot();
  });
});

The error message outputted from the test is:

    TypeError: Cannot read property 'pathname' of undefined

      52 | 
      53 | const customRender: CustomRender = (ui, options) =>
    > 54 |   render(ui, { wrapper: AllTheProviders, ...options });
         |   ^
      55 | 
      56 | // re-export everything
      57 | export * from "react-testing-library";

If I had to guess, I'd say that the <Component {...pageProps} /> component in /pages/_app.js is what provides the pathName as part of Next.js's routing.

The examples provided by Next.js don't cover how to do this so I'm hoping someone here might be able to help.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source