apollographql / apollo-client-nextjs

Apollo Client support for the Next.js App Router
https://www.npmjs.com/package/@apollo/experimental-nextjs-app-support
MIT License
436 stars 32 forks source link

Jest registerApolloClient is not a function #353

Open levchenkod opened 3 weeks ago

levchenkod commented 3 weeks ago

I've followed the recommendations from the README, but I get this error during tests:

 TypeError: (0 , _experimentalnextjsappsupport.registerApolloClient) is not a function

       9 |
      10 |
    > 11 | const { getClient: graphClient } = registerApolloClient(() => {

Apart from jest the code works fine.

Repo to reproduce: https://github.com/levchenkod/next-apolo-jest-basic-setup

phryneas commented 3 weeks ago

Jest simulates a browser environment, so it uses the wrong version of Apollo Client for this - registerApolloClient is only available in React Server Components, not in the browser.

You can do

/** @type {import('jest').Config} */
const config = {
  testEnvironment: 'jsdom',
  testEnvironmentOptions: {
    customExportConditions: ['react-server'],
  },
};

in your jest config, which will instead load the "server component" code of @apollo/experimental-nextjs-app-support, but keep in mind that this will change resolution for all your dependencies to "server component" - you'll also get a different build of react, react-dom etc. If you want to test server components, this is probably a good thing, but I don't know for sure if jest actually works nicely with that.

marjorg commented 2 weeks ago

Jest simulates a browser environment, so it uses the wrong version of Apollo Client for this - registerApolloClient is only available in React Server Components, not in the browser.

You can do

/** @type {import('jest').Config} */
const config = {
  testEnvironment: 'jsdom',
  testEnvironmentOptions: {
    customExportConditions: ['react-server'],
  },
};

in your jest config, which will instead load the "server component" code of @apollo/experimental-nextjs-app-support, but keep in mind that this will change resolution for all your dependencies to "server component" - you'll also get a different build of react, react-dom etc. If you want to test server components, this is probably a good thing, but I don't know for sure if jest actually works nicely with that.

@phryneas I'm getting the same error using Vitest, and I've been trying to replicate the provided Jest config without luck. Any pointers?

phryneas commented 2 weeks ago

Vitest also doesn't simulate a react-server environment by default. This is really a specific runtime environment where libraries load differently than they would in the RSC run or in the browser.

For vitest, you would have to specify

export default defineConfig({
  plugins: [react()],
  resolve: {
    conditions: ["react-server"],
  },
});
marjorg commented 2 weeks ago

Vitest also doesn't simulate a react-server environment by default. This is really a specific runtime environment where libraries load differently than they would in the RSC run or in the browser.

For vitest, you would have to specify

export default defineConfig({
  plugins: [react()],
  resolve: {
    conditions: ["react-server"],
  },
});

Thanks for helping, but adding that line to the config seems to break all tests with the following error:

Error: This entry point is not yet supported outside of experimental channels
 ❯ ../../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.shared-subset.development.js:18:7
 ❯ Object.<anonymous> ../../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.shared-subset.development.js:19:5
 ❯ Object.<anonymous> ../../node_modules/.pnpm/react@18.3.1/node_modules/react/react.shared-subset.js:6:2
phryneas commented 2 weeks ago

Yes, you are running your tests with React 18.3.1, while Next.js is using a Canary build of React. You will have to find out which React build your Next.js installation uses and use that same build for your tests.

Next.js ignores your node_modules and brings it's own dependencies. I know it's insane but that's what we all have to deal with 😢

Look in node_modules/next/dist/compiled/react/cjs/react.development.js for the string ReactVersion, you'll find something like '18.3.0-canary-14898b6a9-20240318'

marjorg commented 2 weeks ago

That is quite insane indeed, I gave the last suggestion a shot but no luck. I think I'll wait with adding tests for the few pages I've migrated to app router until Next 15 to see if they make this more manageable.

Thanks for your help!