Element: [Bug Report] ReferenceError: _Message is not defined in jest tests

Created on 21 Aug 2019  ·  11Comments  ·  Source: ElemeFE/element

Element UI version

2.10.1

OS/Browsers version

Mac High Sierra

Vue version

2.6.10

Reproduction Link

https://jsfiddle.com

Steps to reproduce

  • create a vue component with import { Message } from 'element-ui';
  • Call Message.info('test') inside the vue component
  • Create a jest test, that directly interacts with code that calls Message.info('test')
  • Run jest tests

What is Expected?

import { Message } from 'element-ui' works without issues during my testing. Or being able to do a simple manual mock of 'element-ui'.

What is actually happening?

I get a ReferenceError: _Message is not defined error. It happens either in tests or inside the actual vue file. That is not a case for any other node modules. I tried doing all kinds of mocks (manual mock, automatic mock, I tried to spy on it...) but I was unable to get that to work.

I would be fine not using mocks, but simple imports don't work either inside the vue file itself, so my tests just fail.

stale

Most helpful comment

Here is my full jest.config.js, just for reference:

module.exports = {
  moduleFileExtensions: [
    'js',
    'jsx',
    'json',
    'vue',
  ],
  transform: {
    '^.+\\.vue$': 'vue-jest',
    '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
    '^.+\\.(js|jsx)?$': 'babel-jest',
  },
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
    '^.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
  },
  snapshotSerializers: [
    'jest-serializer-vue',
  ],
  testMatch: [
    '**/tests/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)',
  ],
  testURL: 'http://localhost/',
  watchPlugins: [
    'jest-watch-typeahead/filename',
    'jest-watch-typeahead/testname',
  ],
  collectCoverage: true,
  coverageReporters: ['lcov', 'text-summary'],
};

All 11 comments

You need to fix webpack loaders.

On-demand import from element-ui requires additional configuration: https://element.eleme.io/#/en-US/component/quickstart#on-demand

You need to fix webpack loaders.
@wacky6 Its only not working in testing. I have imports working normally when running the app, as I used cli to install it.

testing environment usually has saperate loader/env configuration.

Double checking the docs, I am modifying babel config to have on-demand importing:

module.exports = {
  presets: [
    '@vue/app',
  ],
  plugins: [
    [
      'component',
      {
        libraryName: 'element-ui',
        styleLibraryName: 'theme-chalk',
      },
    ],
  ],
};

Is this not a global configuration, that will be applied to all environments? Do I have to just specify the same configuration for all environments manually (I'd think not)? Can you perhaps provide an example of correct configuration @wacky6?

Which configuration is used depends on the particular testing framework / configuration you are using. I can not give exact advice on this, just a hint on where to look at.

It would be great to see a working example, I've tried all the various Jest configuration options (for example I thought it might have been transformIgnorePatterns option), looked into Babel as well as Webpack... I've been trying to fix this for weeks now, which is why I am here out of desperation.

Still banging my head against this issue, I've tried numerous things, also made a StackOverflow question with some more details: https://stackoverflow.com/questions/57639448/elementui-tests-throw-referenceerror-message-is-not-defined

Would love to hear from anyone who uses on-demand loading and Jest for testing

You can use the test environment in babel to use different config file

You can use the test environment in babel to use a different config file

That is not really the answer to this issue, as it's not just about specifying the plugin configuration for test env. For everyone out there who would ever encounter the same issue (and avoid trying to debug this for days as I did), this is what actually had to be done:

  1. Update your babel.config.js
module.exports = {
  presets: [
    '@vue/app',
  ],
  plugins: [
    [
      'component',
      {
        libraryName: 'element-ui',
        styleLibraryName: 'theme-chalk',
      },
    ],
  ],
  "env": { "test": { "plugins": ["transform-es2015-modules-commonjs", "dynamic-import-node"] } }
};
  1. _Possibly_ remove transformIgnorePatterns from your jest.config.js (you probably could just add an exception, pointing at element-ui)

This is what I had to do specifically when using Vue CLI. There is some specific Babel configuration in there, as it uses babel-preset-app. You can dive into it to understand the intricacies of it.

So thanks @wacky6 for pointing me in the right direction, although it still took days and another person to help find the solution. I think having some testing documentation in Element UI would really help people out...

Here is my full jest.config.js, just for reference:

module.exports = {
  moduleFileExtensions: [
    'js',
    'jsx',
    'json',
    'vue',
  ],
  transform: {
    '^.+\\.vue$': 'vue-jest',
    '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
    '^.+\\.(js|jsx)?$': 'babel-jest',
  },
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
    '^.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
  },
  snapshotSerializers: [
    'jest-serializer-vue',
  ],
  testMatch: [
    '**/tests/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)',
  ],
  testURL: 'http://localhost/',
  watchPlugins: [
    'jest-watch-typeahead/filename',
    'jest-watch-typeahead/testname',
  ],
  collectCoverage: true,
  coverageReporters: ['lcov', 'text-summary'],
};

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Was this page helpful?
0 / 5 - 0 ratings