Search code examples
vue.jsjestjsimporterror

Jest with Vue 3 - ReferenceError: define is not defined


I would like to test my component with Jest and inside component, I imported @vue/apollo-composable library and when I run test I get the error:

ReferenceError: define is not defined

      2 |   // libraries
      3 |   import { defineComponent, ref, watch } from '@vue/composition-api'
    > 4 |   import { useLazyQuery, useResult } from '@vue/apollo-composable'
        | ^
      5 |   import gql from 'graphql-tag'

In the jest test I don't use apollo-composable and I don't plan to. Code:

import '@/plugins/composition-api'
import App from '@/components/App.vue'
import Vue from 'vue'
import { Wrapper, createLocalVue, mount } from '@vue/test-utils'

Vue.use(Vuetify)

describe('SelectMediaProcess.vue', () => {
  let wrapper: Wrapper<Vue>
  const localVue = createLocalVue()
  beforeEach(() => {
    wrapper = mount(SelectMediaProcess, { localVue })
  })

  it('render', () => {
    expect(wrapper.exists()).toBe(true)
  })
})

I read on the internet what I can use:

jest.mock('@vue/apollo-composable', () => {
   // mock implementation
})

But when I use this piece of code in my test. I get error: (useLazyQuery is a function from @vue/apollo-composable library)

TypeError: Cannot read property 'useLazyQuery' of undefined

      19 |
      20 |       // get default media process
    > 21 |       const { onResult, load: loadDefaultMP } = useLazyQuery<
         | ^
      22 |         getDefaultMediaProcess,
      23 |         getDefaultMediaProcessVariables
      24 |       >(

Does anyone know what can I do please?

EDIT

I added these lines to my jest.config.js. It helped others but not me.

transformIgnorePatterns: ['<rootDir>/node_modules/(?!@vue/apollo-composable).+\\.js$']

moduleNameMapper: { '@vue/apollo-composable': '@vue/apollo-composable/dist/index.js' }

Full jest.config.js:

module.exports = {
  preset: '@vue/cli-plugin-unit-jest/presets/typescript-and-babel',
  moduleFileExtensions: ['js', 'ts', 'json', 'vue'],
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
    'vuetify/lib(.*)': '<rootDir>/node_modules/vuetify/es5$1',
    '@vue/apollo-composable': '@vue/apollo-composable/dist/index.js'
  },
  modulePaths: ['<rootDir>/src', '<rootDir>/node_modules'],
  transform: {
    '.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$':
      'jest-transform-stub',
    '^.+\\.ts?$': 'ts-jest',
    '.*\\.(vue)$': 'vue-jest'
  },
  transformIgnorePatterns: [
    '<rootDir>/node_modules/(?!(vuetify)/)',
    '<rootDir>/node_modules/(?!@vue/apollo-composable).+\\.js$'
  ]
}

and I get these new errors:

FAIL  tests/unit/selectMediaProcess.spec.ts
  ● Test suite failed to run

    Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html

    Details:

    C:\Users\u112200\Documents\deposit-frontend\node_modules\@vue\apollo-composable\dist\index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){export { useQuery, } from './useQuery';
                                                                                             ^^^^^^

    SyntaxError: Unexpected token 'export'

      2 |   // libraries
      3 |   import { defineComponent, ref, watch } from '@vue/composition-api'
    > 4 |   import { useLazyQuery, useResult } from '@vue/apollo-composable'
        | ^
      5 |   import gql from 'graphql-tag'
      6 |   // models
      7 |   import { allMediaProcesses } from '../models/__generated__/allMediaProcesses'

      at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:537:17)
      at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:579:25)
      at src/components/SelectMediaProcess.vue:4:1
      at Object.<anonymous> (src/components/SelectMediaProcess.vue:89:3)

Does anyone know what can I do next please?


Solution

  • You need to define the functions within the mock statement.

    Currently, you've said that rather than using the real thing a mock should be used. The reason you're then getting undefined is because the mock is empty (you've not defined any functions in it).

    So, the next thing to do is to specify how that mocked library should interact. You're importing two functions, so you'll need to define those functions inside the mock statement:

    jest.mock('@vue/apollo-composable', () => {
      return {
        __esModule: true,
        useLazyQuery: jest.fn(() => 42), // Replace 42 with whatever result you'd expect
        useResult: jest.fn(() => 43), // Replace 43 with whatever result you'd expect
      }
    })
    

    There's some more detail about this in the jest documentation.