Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I make dynamic imports work with Jest?

I'm writing unit tests for my application (Vue.js) and I'm having troubles while trying to test a method that imports a module dynamically. I wanted to mock the library (file-saver) to test that it is called correctly but instead all I get is an error. The mock file gets completely ignored.

I used to have a "require.ensure is not a function" error, but after setting up babel-plugin-dynamic-import-node the error changed.

Here is the method I'm testing:

file.js

[...]
   async saveFile() {
     import('file-saver').then(filesaver => {
       return filesaver.saveAs(data, name);
     })
   },
[...]

test.js

    describe('testing methods', () => {
      it('exports files correctly', async () => {
        wrapper.vm.exportAddressGroups();
      });
    });

Jump to the bottom to see what error I'm getting.

These are my configuration files:

jest.config.json

{
  "rootDir": "../",
  "verbose": true,
  "moduleNameMapper": {
    "store/(.*)$": "<rootDir>/src/store/$1",
    "views/(.*)$": "<rootDir>/src/views/$1",
    "components/(.*)$": "<rootDir>/src/components/$1",
    "src/([^\\.]*)$": "<rootDir>/src/$1",
    "user/([^\\.]*)$": "<rootDir>/src/components/user/$1",
    "admin/([^\\.]*)$": "<rootDir>/src/components/admin/$1",
    "shared/([^\\.]*)$": "<rootDir>/src/components/shared/$1",
    "mobile/([^\\.]*)$": "<rootDir>/src/components/mobile/$1",
    "api/([^\\.]*)$": "<rootDir>/src/api/$1",
    "i18n/([^\\.]*)$": "<rootDir>/src/i18n/$1",
    "setup/([^\\.]*)$": "<rootDir>/test/setup/$1",
    "mocks/(.*)$": "<rootDir>/test/mocks/$1",
    "types/([^\\.]*)$": "<rootDir>/types/$1",
    "\\.(png|gif|ttf|eot|svg)$": "<rootDir>/test/mocks/file.js"
  },
  "moduleFileExtensions": ["js", "json", "vue"],
  "modulePathIgnorePatterns": ["<rootDir>/src/components/.*/index.js"],
  "coveragePathIgnorePatterns": [
    "<rootDir>/src/components/.*/index.js",
    "<rootDir>/.*/*.json",
    "<rootDir>/.*/__tests__/.*"
  ],
  "transform": {
    ".+\\.js$": "<rootDir>/node_modules/babel-jest",
    ".+\\.vue$": "<rootDir>/node_modules/vue-jest"
  },
  "setupFiles": [
   "./test/setup/index.js"
  ],
  "coverageDirectory": "<rootDir>/output",
  "collectCoverage": true
}

babelrc

{
  "presets": [
    ["@babel/preset-env", {
      "useBuiltIns": "entry",
      "targets": "ie 11, last 2 chrome versions, last 2 safari versions, last 2 firefox versions, last 2 edge versions"
    }]
  ],
  "plugins": [
    "@babel/plugin-proposal-class-properties",
    "@babel/plugin-proposal-object-rest-spread",
    "@babel/plugin-syntax-dynamic-import",
    "@babel/plugin-syntax-flow",
    "@babel/plugin-transform-async-to-generator",
    "@babel/plugin-transform-flow-strip-types",
    "dynamic-import-webpack"
  ],
  "env": {
    "test": {
      "plugins": ["dynamic-import-node"]
    }
  },
  "comments": false
}

package.json (only somehow relevant plugins)

    "@babel/core": "~7.3.4",
    "@babel/plugin-external-helpers": "~7.2.0",
    "@babel/plugin-proposal-class-properties": "~7.3.4",
    "@babel/plugin-proposal-object-rest-spread": "~7.3.4",
    "@babel/plugin-syntax-dynamic-import": "~7.2.0",
    "@babel/plugin-syntax-flow": "~7.2.0",
    "@babel/plugin-transform-async-to-generator": "~7.3.4",
    "@babel/plugin-transform-flow-strip-types": "~7.3.4",
    "@babel/polyfill": "~7.2.5",
    "@babel/preset-env": "~7.3.4",
    "@babel/register": "~7.0.0",
    "@babel/runtime": "~7.3.4",
    "@vue/test-utils": "^1.0.0-beta.27",
    "babel-core": "7.0.0-bridge.0",
    "babel-eslint": "~10.0.1",
    "babel-jest": "~24.1.0",
    "babel-loader": "~8.0.5",
    "babel-plugin-dynamic-import-node": "^2.2.0",
    "babel-plugin-dynamic-import-webpack": "~1.0.2",
    "fetch-mock": "^7.2.7",
    "jest": "~24.1.0",
    "jest-fetch-mock": "~2.1.1",
    "jest-localstorage-mock": "2.4.0",
    "npm-install-webpack-plugin": "~4.0.5",
    "require-extension-hooks": "~0.3.2",
    "require-extension-hooks-babel": "~0.1.1",
    "require-extension-hooks-vue": "~1.0.1",
    "vue-jest": "~3.0.4",
    "vue-loader": "~15.2.4",
    "vue-style-loader": "~4.1.0",
    "vue-svg-loader": "~0.11.0",
    "webpack": "~4.16.0",
    "webpack-cli": "~3.0.8",
    "webpack-dev-server": "~3.1.4",
    "webpack-merge": "~4.1.3",
    "webpack-monitor": "~1.0.14",
    "webpack-visualizer-plugin": "~0.1.11",

The error I get is the following:

Cannot find module 'function (resolve) {
  require.ensure([], function (require) {
    resolve(require('file-saver'));
  });
}' from 'file.js'

All I can see is that instead of being executed, the code is basically turned into a string. I've spent hours trying to find a solution but couldn't find anything similar online.

Does any of you know what I'm doing wrong?

like image 556
Sacha Morgese Avatar asked Jun 06 '19 03:06

Sacha Morgese


People also ask

How can I use dynamic import module?

To load dynamically a module call import(path) as a function with an argument indicating the specifier (aka path) to a module. const module = await import(path) returns a promise that resolves to an object containing the components of the imported module. } = await import(path);

How do you mock an import in Jest?

To mock an imported function with Jest we use the jest. mock() function. jest. mock() is called with one required argument - the import path of the module we're mocking.

Does Dynamic import improve performance?

Dynamic imports, also known as code splitting, refers to the practice of dividing bundles of JavaScript code into smaller chunks, which are then pieced together and loaded into the runtime of an application as a means to drastically boost site performance.

Is dynamic import cached?

Once a module is fetched dynamically from the server, it is cached permanently on the client and additional requests for the same version of the module will not incur the round-trip request to the server. If the module is changed then a fresh copy will always be retrieved from the server.


1 Answers

Can you try @babel/plugin-syntax-dynamic-import? Most probably, you can also get rid of plugin-syntax-dynamic-import, it should be unneeded while using the former.

like image 58
artus9033 Avatar answered Oct 19 '22 00:10

artus9033