Apollo-client: TypeError: graphql.visit is not a function

Created on 20 Nov 2020  ·  7Comments  ·  Source: apollographql/apollo-client

Intended outcome:

We are trying to mock the graphql for teting with jest on NextJS

Actual outcome:

We are getting the following error:

    TypeError: graphql.visit is not a function

      29 |   // });
      30 |   it('test', async () => {
    > 31 |     TestRenderer.create(
         |                  ^
      32 |       <MockedProvider mocks={mocks}>
      33 |         <Test />
      34 |       </MockedProvider>

      at removeDirectivesFromDocument (node_modules/@apollo/client/utilities/graphql/transform.js:39:40)
      at Object.removeConnectionDirectiveFromDocument (node_modules/@apollo/client/utilities/graphql/transform.js:147:12)
      at MockLink.Object.<anonymous>.MockLink.normalizeMockedResponse (node_modules/@apollo/client/utilities/testing/mocking/mockLink.js:86:38)
      at MockLink.Object.<anonymous>.MockLink.addMockedResponse (node_modules/@apollo/client/utilities/testing/mocking/mockLink.js:29:45)
      at node_modules/@apollo/client/utilities/testing/mocking/mockLink.js:23:23
          at Array.forEach (<anonymous>)
      at new MockLink (node_modules/@apollo/client/utilities/testing/mocking/mockLink.js:22:29)
      at new MockedProvider (node_modules/@apollo/client/utilities/testing/mocking/MockedProvider.js:15:27)
      at constructClassInstance (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:3629:18)
      at updateClassComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7558:5)
      at beginWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:9043:16)
      at performUnitOfWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:12649:12)
      at workLoopSync (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:12622:22)
      at performSyncWorkOnRoot (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:12333:9)
      at node_modules/react-test-renderer/cjs/react-test-renderer.development.js:1825:24
      at unstable_runWithPriority (node_modules/scheduler/cjs/scheduler.development.js:653:12)
      at runWithPriority (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:1775:10)
      at flushSyncCallbackQueueImpl (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:1820:7)
      at flushSyncCallbackQueue (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:1808:3)
      at scheduleUpdateOnFiber (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11776:9)
      at updateContainer (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14747:3)
      at Object.create (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:15455:5)
      at src/features/Task/components/Task/__tests__/Task.test.tsx:31:18
      at step (node_modules/tslib/tslib.js:141:27)
      at Object.next (node_modules/tslib/tslib.js:122:57)
      at node_modules/tslib/tslib.js:115:75
      at Object.__awaiter (node_modules/tslib/tslib.js:111:16)
      at Object.<anonymous> (src/features/Task/components/Task/__tests__/Task.test.tsx:30:14)

How to reproduce the issue:

Our files:

Task.test.tsx

import * as React from 'react';
import Test from '@features/Task/components/Task/Test';
import { MockedProvider } from '@apollo/client/testing';
import TestRenderer from 'react-test-renderer';
import { AmIBossDocument } from '@generated/server/graphql';

const mocks = [
  {
    request: {
      query: AmIBossDocument
    },
    result: {
      data: { amIBoss: true }
    }
  }
];

describe('Features', () => {
  it('test', async () => {
    TestRenderer.create(
      <MockedProvider mocks={mocks}>
        <Test />
      </MockedProvider>
    );
  });
});

test.tsx

import { useAmIBossQuery } from '@generated/server/graphql';
import React from 'react';

type TestProps = {};

const Test: React.FC<TestProps> = () => {
  const { loading, error, data } = useAmIBossQuery();
  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error!</p>;
  return <div>{data?.amIBoss}</div>;
};

export default Test;

AmIBossDocument

export const AmIBossDocument = gql`
  query amIBoss {
    amIBoss
  }
`;

jest.config.js

module.exports = {
  roots: ['<rootDir>'],
  preset: 'ts-jest',
  testEnvironment: 'jsdom',
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
  moduleNameMapper: {
    '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
      '<rootDir>/__mocks__/styleMock.js',
    '\\.(css|less|scss)$': '<rootDir>/__mocks__/styleMock.js',
    '^@commons/(.*)': '<rootDir>/src/commons/$1',
    '^@components/(.*)': '<rootDir>/src/components/$1',
    '^@features/(.*)': '<rootDir>/src/features/$1',
    '^@libraries/(.*)': '<rootDir>/src/libraries/$1',
    '^@contexts/(.*)': '<rootDir>/src/contexts/$1',
    '^@styles/(.*)': '<rootDir>/styles/$1',
    '^@generated/(.*)': '<rootDir>/generated/$1',
    '^@graphql/(.*)': '<rootDir>/graphql/$1'
  },
  transform: {
    '^.+\\.(js|jsx|ts|tsx)$': 'ts-jest'
  },
  transformIgnorePatterns: ['/node_modules/', '<rootDir>/node_modules/'],
  testMatch: ['**/__tests__/*.ts?(x)', '**/?(*.)+(spec|test).ts?(x)'],
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
  testPathIgnorePatterns: ['<rootDir>/.next/', '<rootDir>/node_modules/'],
  globals: {
    'ts-jest': {
      tsConfig: '<rootDir>/tsconfig.jest.json'
    }
  },
  moduleDirectories: ['node_modules', 'src', 'styles', 'generated', 'graphql']
};

jest.setup.js

import '@testing-library/jest-dom/extend-expect';

tsconfig.jest.json

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "jsx": "react"
  }
}

Versions

NextJS 9.4.0

System:
    OS: macOS 11.0.1
  Binaries:
    Node: 14.5.0 - /usr/local/bin/node
    Yarn: 1.22.10 - ~/Documents/snuper/web_app/node_modules/.bin/yarn
    npm: 6.14.8 - ~/Documents/snuper/web_app/node_modules/.bin/npm
  Browsers:
    Chrome: 86.0.4240.198
    Safari: 14.0.1
  npmPackages:
    @apollo/client: 3.2.5 => 3.2.5
    apollo: ^2.27.3 => 2.31.0
    apollo-link-logger: ^1.2.3 => 1.2.3
    apollo-link-timeout: ^1.4.1 => 1.4.1
    apollo-link-token-refresh: ^0.3.2 => 0.3.2
    apollo-link-ws: ^1.0.20 => 1.0.20
    next-with-apollo: 5.1.0 => 5.1.0

Most helpful comment

@guiaramos This appears to be a known issue related to the graphql package's use of the .mjs file extension: https://github.com/graphql/graphql-js/issues/1272. Can you try adding mjs to your moduleFileExtensions, at the beginning of the list (so it takes precedence over js)? If that doesn't fix the problem, please put these snippets of code together into a reproduction so that we can investigate further.

In case you're wondering, reverting #7185 is not an option for the reasons I explained in https://github.com/apollographql/apollo-client/pull/7185#pullrequestreview-512013147. Both graphql v14 and v15 export visit and BREAK from the top-level graphql package, so I don't see anything wrong with the way we're importing those exports within @apollo/client.

Just to be sure, though, what version of the graphql package are you using?

All 7 comments

i suffer same problem.

this issue happened on versio update to 3.2.5, its working on 3.2.4:

problem:
the pr: https://github.com/apollographql/apollo-client/pull/7185
the commit: https://github.com/apollographql/apollo-client/commit/e145a860a10c12fdc4d863379f32e4080597323b
at src/utilities/graphql/transform.ts

@guiaramos This appears to be a known issue related to the graphql package's use of the .mjs file extension: https://github.com/graphql/graphql-js/issues/1272. Can you try adding mjs to your moduleFileExtensions, at the beginning of the list (so it takes precedence over js)? If that doesn't fix the problem, please put these snippets of code together into a reproduction so that we can investigate further.

In case you're wondering, reverting #7185 is not an option for the reasons I explained in https://github.com/apollographql/apollo-client/pull/7185#pullrequestreview-512013147. Both graphql v14 and v15 export visit and BREAK from the top-level graphql package, so I don't see anything wrong with the way we're importing those exports within @apollo/client.

Just to be sure, though, what version of the graphql package are you using?

@benjamn thanks for your reply. fully understand the point.

Can you try adding mjs to your moduleFileExtensions, at the beginning of the list (so it takes precedence over js)?

causes the following error:

    Details:

    /Users/guilhermeramos/Desktop/projects.nosync/snuper/web/node_modules/graphql/graphql.mjs:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import isPromise from "./jsutils/isPromise.mjs";
                                                                                             ^^^^^^

    SyntaxError: Cannot use import statement outside a module

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1350:14)
      at Object.<anonymous> (node_modules/@apollo/client/utilities/utilities.cjs.js:7:15)

Just to be sure, though, what version of the graphql package are you using?

    "graphql": "15.4.0",

I will create a reproduction soon and post here

@guiaramos Did you fixed the issue? i get the same error running my tests, which work fine in the version before.

The mentioned workaround

Can you try adding mjs to your moduleFileExtensions, at the beginning of the list (so it takes precedence over js)?

gives me the same SyntaxError

SyntaxError: Cannot use import statement outside a module

@guiaramos Did you fixed the issue? i get the same error running my tests, which work fine in the version before.

The mentioned workaround

Can you try adding mjs to your moduleFileExtensions, at the beginning of the list (so it takes precedence over js)?

gives me the same SyntaxError

SyntaxError: Cannot use import statement outside a module

@zerocewl I was able to fix the issue by just pin the @apollo/client to version 3.2.4:
@apollo/client: "3.2.4"

@guiaramos
Obviously pinning the version is not the preferred option ;-)

Did you get a reproduction repo ready?

Was this page helpful?
0 / 5 - 0 ratings