jest config hanging when getting coverage - vue.js

I have a vue application that has got jest installed as the testing framework. The jest config is in the package.json file. It looks like:
"jest": {
"moduleFileExtensions": [
"js",
"jsx",
"json",
"vue"
],
"transform": {
"^.+\\.vue$": "vue-jest",
".+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$": "jest-transform-stub",
"^.+\\.jsx?$": "babel-jest"
},
"moduleNameMapper": {
"^#/(.*)$": "<rootDir>/src/$1"
},
"snapshotSerializers": [
"jest-serializer-vue"
],
"testMatch": [
"**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)",
"**/tests/unit/**/*.test.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"
],
"testURL": "http://localhost",
"collectCoverage": true,
"collectCoverageFrom": [
"!**/node_modules/**",
"**/*.{js,vue}"
],
"coverageDirectory": "../coverage",
"coverageReporters": [
"html",
"text-summary"
]
}
These are i think the default setting when i installed the vue application using the vue cli.
I am experiencing issues after my tests run the terminal says Running coverage on untested files... and then it just hangs there forever.
If i remove the js bit from "**/*.{js,vue}" in the collectCoverageFrom so that it is "**/*.{vue}" then the problem doesn't occur and the coverage report completes.
Does anyone have experience of this problem? are there any config settings needed to prevent this issue?

Related

How to properly import ES6+ React Native components with Jest ESM

Using Jest w/ESM for a React Native project, and can't figure out how to properly import modules that have ESM in them. Importing the react-native-phone-number-input module, I get Jest encountered an unexpected token:
/repo/node_modules/react-native-phone-number-input/lib/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import React, { PureComponent } from "react";
^^^^^^
SyntaxError: Cannot use import statement outside a module
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1796:14)
So far the only way I have been able to get it running is mocking:
jest.unstable_mockModule('react-native-phone-number-input', () => ({
default: jest.fn(),
}));
Here is my Jest config (in package.json):
{
"haste": {
"defaultPlatform": "ios",
"platforms": [
"android",
"ios",
"native"
]
},
"resetMocks": true,
"testEnvironment": "node",
"testMatch": [
"**/src/**/*.(spec|test).[tj]s?(x)"
],
"preset": "ts-jest/presets/default-esm",
"transform": {
"^.+\\.js$": "babel-jest"
},
"transformIgnorePatterns": [
"node_modules/(?!((jest-)?react-native|#?react-native(-community)?)/)"
],
"extensionsToTreatAsEsm": [
".ts",
".tsx"
],
"globals": {
"ts-jest": {
"useESM": true
}
},
"setupFiles": [
"<rootDir>/node_modules/react-native/jest/setup.js"
],
"setupFilesAfterEnv": [
"#testing-library/jest-native/extend-expect"
]
}

Coverage Report with Jest and Vue not working

I am unit testing my Vue project with Jest and I get the code coverage in the console, no problems there, however the HTML report is not working -
package.json:
...
"unit": "jest --config test/unit/jest.conf.js --coverage",
...
jest.conf.js:
const path = require('path')
module.exports = {
verbose: true,
testURL: "http://localhost/",
rootDir: path.resolve(__dirname, '../../'),
moduleFileExtensions: [
'js',
'json',
'vue'
],
moduleNameMapper: {
'^#/(.*)$': '<rootDir>/src/$1'
},
transform: {
'^.+\\.js$': '<rootDir>/node_modules/babel-jest',
'.*\\.(vue)$': '<rootDir>/node_modules/vue-jest'
},
testPathIgnorePatterns: [
'<rootDir>/test/e2e'
],
snapshotSerializers: ['<rootDir>/node_modules/jest-serializer-vue'],
setupFiles: ['<rootDir>/test/unit/setup'],
mapCoverage: true,
coverageDirectory: '<rootDir>/test/unit/coverage',
collectCoverageFrom: [
'src/**/*.{js,vue}',
'!src/main.js',
'!src/router/index.js',
'!src/plugins/vuetify.js',
'!**/node_modules/**'
]
}
What might be the cause of that? Thank you in advance.
It looks like your coverage report property might need to be adjusted. You should try including html in your coverageReporters, like this:
module.exports = {
...
coverageReporters: ['html']
...
}

Vue Jest Invalid or unexpected token

I'm new to Jest and Vue, but I'm getting an error in one of my tests.
The error is:
Test suite failed to run
/...../node_modules/element-ui/lib/theme-chalk/table-column.css:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){#charset "UTF-8";.el-checkbox,.el-checkbox__input{white-space:nowrap;display:inline-block;position:relative}.el-checkbox{color:#606266;font-weight:500;font-size:14px;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;margin-right:30px}.el-checkbox.is-bordered{padding:9px 20px 9px 10px;border-radius:4px;border:1px solid #DCDFE6;-webkit-box-sizing:border-box;box-sizing:border-box;line-height:normal;height:40px}.el-checkbox.is-bordered.is-checked{border-color:#409EFF}.el-checkbox.is-bordered.is-disabled{border-color:#EBEEF5;cursor:not-allowed}.el-checkbox.is-bordered+.el-checkbox.is-bordered{margin-left:10px}.el-checkbox.is-bordered.el-checkbox--medium{padding:7px 20px 7px 10px;border-radius:4px;height:36px}.el-checkbox.is-bordered.el-checkbox--medium .el-checkbox__l
SyntaxError: Invalid or unexpected token
Here's my package.json file:
"jest": {
"moduleFileExtensions": [
"js",
"json",
"vue"
],
"transform": {
".*\\.(vue)$": "vue-jest",
".*\\.(js)$": "babel-jest"
},
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
"\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js",
"^#/(.*)$": "<rootDir>/src/$1"
},
"testPathIgnorePatterns": [
"<rootDir>/(build|docs|node_modules)/*"
],
"testEnvironment": "node"
},
"babel": {
"presets": [
[
"#babel/preset-env",
{
"targets": {
"node": "current"
}
}
]
]
},
I don't understand why node_modules isn't being excluded, but even if they aren't excluded why isn't the .css file being mocked?
I suspected the issue was jest was not reading my config from package.json.
To verify this I used the jest --showConfig. Indeed, it was different from package.json.
I then created a new config file, jest.json and I changed the test script in package.json to be "test": "jest --config jest.json"
This is the contents of my config:
{
"verbose": true,
"automock": false,
"globals": {
"_Table": {"name": "el-table"},
"_TableColumn": {"name": "el-table-column"}},
"moduleFileExtensions": [
"js",
"json",
"vue"
],
"transform": {
".*\\.(vue)$": "vue-jest",
".*\\.(js)$": "babel-jest"
},
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
"\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js",
"^#/(.*)$": "<rootDir>/src/$1"
},
"testPathIgnorePatterns": [
"<rootDir>/(build|docs|node_modules)/"
]
}
There are a few more issues, but this was the main one.

ElementUI tests throw ReferenceError: _Message is not defined

Bug report on ElementUI
I am using On-demand loading of ElementUI components. I've followed the instructions correctly and it works just fine when running the app.
The problem arises when I try to test with Jest and Vue test utils. None of the components I am importing seem to be found, so I get this error when running my tests:
ReferenceError: _Message is not defined
I get the same error for any of the other components, that my test touches.
On the bug report I mentioned above, I am being suggested that my babel configuration is not being applied in my testing environment? Or its something about my Jest configuration. I've tried various things to fix this:
Doing a manual mocks
Spying on the component
Importing the whole ElementUI package inside my test
Updating Jest configuration
Nothing seems to work and I have no idea what is wrong...
bebel.config.js
module.exports = {
presets: [
'#vue/app',
],
plugins: [
[
'component',
{
libraryName: 'element-ui',
styleLibraryName: 'theme-chalk',
},
],
],
};
jest.config.js
module.exports = {
// roots: ['<rootDir>/src/', '<rootDir>/tests/'],
moduleFileExtensions: [
'js',
'jsx',
'json',
'vue',
],
transform: {
'^.+\\.vue$': 'vue-jest',
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
'^.+\\.jsx?$': 'babel-jest',
},
transformIgnorePatterns: [
'/node_modules/(?!element-ui)',
],
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'],
};
I have a couple of suggestions for you here:
change this in jest.config.js
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'],
};
and this in 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"] } }
};
Also I believe #babel/plugin-transform-modules-commonjs is needed in yarn.
Let me know if this works.

how to get intellisense for methods of modules which are imported from an alias in .vue

In .vue and .js, I can enjoy the intellisense of vscode when developing.
But I found it doesn't work any more when I use an alias.
So I have searched for a while on blogs, found a solution, which is to configure a 'jsconfig.json' as below.
{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"allowSyntheticDefaultImports": true,
"baseUrl": "./",
"paths": {
"#/*": [
"src/*"
]
}
}
}
it worked in the .js file but didn't work in .vue file.
Does anyone know how to resolve it ?
Does work in .js
Not work in .vue
With vue-cli the alias is defined in the webpack-config (since #vue/cli uses webpack under the hood). So instead of jsconfig.json (delete it! just do it!) , I would:
1: Install the webpack resolver for eslint:
npm i eslint-import-resolver-webpack
2: Reference the plugin from your .eslintrc.js
"settings": {
"import/resolver": "webpack"
},
Done!
This is my complete .eslintrc.js just to be thorough:
module.exports = {
"settings": {
"import/resolver": "webpack"
},
parserOptions: {
parser: "babel-eslint"
},
extends: [
"eslint:recommended",
"plugin:vue/recommended"
],
"env": {
"browser": true,
"node": true
},
rules: {}
}
If any issues remains I would check the eslint-settings in vscode settings.json:
"eslint.enable": true,
"eslint.provideLintTask": true,
"eslint.workingDirectories": ["src"],
"eslint.validate": ["javascript","javascriptreact","vue"],