Vue-cli: How to enable Istanbul code coverage for the mocha plugin?

Created on 24 May 2018  Â·  41Comments  Â·  Source: vuejs/vue-cli

What problem does this feature solve?

Coverage reporting for unit tests

What does the proposed API look like?

Is there a way to enable coverage for the mocha plugin? When set up manually on another project, you add the istanbul coverage instrumenter as a webpack loader like this:

webpackConfig.module.rules.unshift({
  test: /\.(js)$/,
  loader:  `istanbul-instrumenter-loader`,
  options: {esModules:true},
  exclude: [
    path.resolve(`node_modules`),
    // Exclude tests from test coverage
    path.resolve(`src/tests`),
    /\.(spec|e2e|tests)\.ts$/,
  ]
})

And then you need to add lcov as a reporter.

This explanation is pretty comprehensive:
https://github.com/zinserjan/mocha-webpack/blob/master/docs/guides/code-coverage.md

contribution welcome enhancement unit-mocha

Most helpful comment

Here's how I made test coverage work for both apollo-server and src directory:

UPDATE: This comment is outdated, please check out @stephsavoie's solution below.

[1/4] Install babel-plugin-istanbul + configure it in babel.config.js

yarn add --dev babel-plugin-instanbul
# or
npm install --save-dev babel-plugin-istanbul

js // babel.config.js module.exports = { presets: ["@vue/app"], plugins: ["istanbul"] };

[2/4] Install istanbul-instrumenter-loader + configure it in vue.config.js

yarn add --dev istanbul-instrumenter-loader
# or
npm install --save-dev istanbul-instrumenter-loader
// vue.config.js
// ...
  chainWebpack: config => {
    if (process.env.NODE_ENV !== "production") {
      config.module
        .rule("istanbul")
        .test(/\.(js|vue)$/)
        .enforce("post")
        .include.add("apollo-server")
        .add("src")
        .end()
        .use("istanbul-instrumenter-loader")
        .loader("istanbul-instrumenter-loader")
        .options({ esModules: true })
        .end();
    }
// ...

[3/4]: Install nyc + configure it in package.json

yarn add --dev nyc
# or
npm install --save-dev nyc
// package.json
// ...
  "nyc": {
    "check-coverage": true,
    "per-file": true,
    "lines": 90,
    "statements": 90,
    "functions": 90,
    "branches": 90,
    "include": [
      "apollo-server/**/*.js",
      "src/**/*.{js,vue}"
    ],
    "exclude": [
      "apollo-server/*.js",
      "src/*.js",
    ],
    "reporter": [
      "lcov",
      "text",
      "text-summary"
    ],
    "extension": [
      ".js"
    ],
    "cache": true,
    "all": true
  }

[4/4]: Use it

  • Single-run: nyc vue-cli-service test:unit
  • Watched run: nodemon --exec nyc vue-cli-service test:unit

PS: I also recommend adding coverage and .nyc_output to your .gitignore.

All 41 comments

I don't know it is an expected answer, but it worked for me by following that mocha-webpack guide and adding the loader to vue.config.js.

You can check whether the rule is successfully added with vue inspect --mode test module.rules:

...
  {
    test: /\.(js|ts)$/,
    include: '/Users/yahatakeiji/work/d3ledger/back-office/src',
    loader: 'istanbul-instrumenter-loader',
    query: {
      esModules: true
    }
  }
...

Also, I changed test:unit script to use nyc as below:

-    "test:unit": "vue-cli-service test:unit",
+    "test:unit": "nyc --reporter=lcov --reporter=text vue-cli-service test:unit",

Me too! I feel that coverage should be part of vue-cli. I can look at how challenging this would be to add in a PR

Here's how I made test coverage work for both apollo-server and src directory:

UPDATE: This comment is outdated, please check out @stephsavoie's solution below.

[1/4] Install babel-plugin-istanbul + configure it in babel.config.js

yarn add --dev babel-plugin-instanbul
# or
npm install --save-dev babel-plugin-istanbul

js // babel.config.js module.exports = { presets: ["@vue/app"], plugins: ["istanbul"] };

[2/4] Install istanbul-instrumenter-loader + configure it in vue.config.js

yarn add --dev istanbul-instrumenter-loader
# or
npm install --save-dev istanbul-instrumenter-loader
// vue.config.js
// ...
  chainWebpack: config => {
    if (process.env.NODE_ENV !== "production") {
      config.module
        .rule("istanbul")
        .test(/\.(js|vue)$/)
        .enforce("post")
        .include.add("apollo-server")
        .add("src")
        .end()
        .use("istanbul-instrumenter-loader")
        .loader("istanbul-instrumenter-loader")
        .options({ esModules: true })
        .end();
    }
// ...

[3/4]: Install nyc + configure it in package.json

yarn add --dev nyc
# or
npm install --save-dev nyc
// package.json
// ...
  "nyc": {
    "check-coverage": true,
    "per-file": true,
    "lines": 90,
    "statements": 90,
    "functions": 90,
    "branches": 90,
    "include": [
      "apollo-server/**/*.js",
      "src/**/*.{js,vue}"
    ],
    "exclude": [
      "apollo-server/*.js",
      "src/*.js",
    ],
    "reporter": [
      "lcov",
      "text",
      "text-summary"
    ],
    "extension": [
      ".js"
    ],
    "cache": true,
    "all": true
  }

[4/4]: Use it

  • Single-run: nyc vue-cli-service test:unit
  • Watched run: nodemon --exec nyc vue-cli-service test:unit

PS: I also recommend adding coverage and .nyc_output to your .gitignore.

@caugner

Hi,

I followed your steps but something gone wrong. I'm getting Unable to lookup source: error. src/components showed twice in paths so i couldn't preview coverage report.

screenshot from 2018-08-01 22-07-55

What is your istanbul-instrumenter-loader version and babel-plugin-istanbul version?

Also, my package.json

{
  "name": "tempus",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "test:unit": "nyc vue-cli-service test:unit",
    "test:e2e": "vue-cli-service test:e2e"
  },
  "dependencies": {
    "bulma": "^0.7.1",
    "bulma-timeline": "^3.0.0",
    "register-service-worker": "^1.0.0",
    "vue": "^2.5.16",
    "vue-router": "^3.0.1",
    "vuex": "^3.0.1"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "^3.0.0-rc.9",
    "@vue/cli-plugin-e2e-nightwatch": "^3.0.0-rc.9",
    "@vue/cli-plugin-eslint": "^3.0.0-rc.9",
    "@vue/cli-plugin-pwa": "^3.0.0-rc.9",
    "@vue/cli-plugin-unit-mocha": "^3.0.0-rc.9",
    "@vue/cli-service": "^3.0.0-rc.9",
    "@vue/eslint-config-airbnb": "^3.0.0-rc.9",
    "@vue/test-utils": "^1.0.0-beta.20",
    "babel-plugin-istanbul": "^4.1.6",
    "chai": "^4.1.2",
    "istanbul-instrumenter-loader": "^3.0.1",
    "node-sass": "^4.9.0",
    "nyc": "^12.0.2",
    "sass-loader": "^7.0.1",
    "vue-template-compiler": "^2.5.16"
  },
  "nyc": {
    "check-coverage": true,
    "per-file": true,
    "lines": 90,
    "statements": 90,
    "functions": 90,
    "branches": 90,
    "include": [
      "src/**/*.{js,vue}"
    ],
    "exclude": [
      "src/*.js"
    ],
    "reporter": [
      "lcov",
      "text-summary"
    ],
    "extension": [
      ".js"
    ],
    "cache": true,
    "all": true
  }
}

And my vue.config.js

module.exports = {
  chainWebpack: (config) => {
    if (process.env.NODE_ENV !== 'production') {
      config.module
        .rule('istanbul')
        .test(/\.(js|vue)$/)
        .enforce('post')
        .include.add('src')
        .end()
        .use('istanbul-instrumenter-loader')
        .loader('istanbul-instrumenter-loader')
        .options({ esModules: true })
        .end();
    }
  },
};

@caugner thanks, your solution works for me if I use this as babel.config.js:

module.exports = {
  presets: [
    '@vue/app'
  ],
  plugins: [
    'babel-plugin-istanbul'
  ]
}

Thanks @caugner , That solution worked for me as well.
I ran across the same issue as @yusufkaracin and setting config.devtool('eval') in my vue.config.js , just above config.module seems to have fixed the source-mapping for vue components.

I got that from this issue.

@caugner can you make example repository on github ? i can't make it work. Very frustrated. I can't find where vue.config.js locate in. Should have use Jest for testing instead of waste time configure this.

I know that coverage is included in Jest by default, should we generate the coverage configuration described above when creating a new Vue app with the Mocha+Chai test options?

I have updated to vue-cli 3.0.4 and nothing is working.
@caugner Do you still have a working setup ?

Does anyone have a working example project for test coverage for vue-cli 3.0.x with vue-cli-mocha-plugin? There are very little examples and the snippets we found do not work.

In later version of webpack (shipped in vue-cli) the include.add('src') will resulted in errors, here is my work around:

    const path = require('path')

    if (process.env.NODE_ENV !== 'production') {
      config.devtool('eval')
      config.module
        .rule('istanbul')
          .test(/\.(js|vue)$/)
          .enforce('post')
          .include
            .add(path.resolve(__dirname, '/src'))
            .end()
          .use('istanbul-instrumenter-loader')
            .loader('istanbul-instrumenter-loader')
            .options({ esModules: true })
    }

I had similar problems and neither @oimou nor @caugner solutions worked.

I finally could track down the mistake:
I put my tests next to my sources, rather than having all tests inside another folder.
When I added the istanbul-instrumenter-loader to my webpack config via vue.config.js I only tested for /\.js$/ which also would include my test files.
Because my test also includes (require) the subject component, obviously, it would be loaded twice. I found this line which causes the

Module build failed (from ./node_modules/istanbul-instrumenter-loader/dist/cjs.js):
  TypeError: Cannot read property 'fileCoverage' of undefined

error messages.

I can not get this working and I have the same issue as @jdoubleu when i created a project using [email protected] . It produces a coverage folder but there is no line coverage in the report. just the same as the out put of the cli below.

I have the same nyc config in my package.json as @yusufkaracin

My vue.config.js file

const path = require('path')

module.exports = { 
  chainWebpack: (config) => {
      var test = path.resolve(__dirname, 'test');
      var src = path.resolve(__dirname, 'src');
      var nodes = path.resolve(__dirname, 'node_modules');
      config.module
        .rule('istanbul')
          .test(/\.(js)$/)
          .enforce('post')
          .include.add(test).add(src)
          .end()
          .exclude.add(nodes)
          .end()
          .use('istanbul-instrumenter-loader')
            .loader('istanbul-instrumenter-loader')
            .options({ produceSourceMap: true, esModules: true }); 
  }
}

one error printed
 WEBPACK  Failed to compile with 1 error(s)

Error in ./src/components/HelloWorld.vue?vue&type=script&lang=js&

  Module build failed (from ./node_modules/istanbul-instrumenter-loader/dist/cjs.js):
  TypeError: Cannot read property 'fileCoverage' of undefined

 ERROR  mocha-webpack exited with code 1.

=============================== Coverage summary ==================
Statements   : Unknown% ( 0/0 )
Branches     : Unknown% ( 0/0 )
Functions    : Unknown% ( 0/0 )
Lines        : Unknown% ( 0/0 )
================================================================

I could finally fix the issue for me and it slightly differs from @caugner solution.

Disclaimer: My environment might differ from yours:

  • I placed my unit tests next to my source files (see also https://github.com/vuejs/vue-cli/issues/1245).
  • The Vue app's entry file is inside a subdirectory (src/renderer/index.js)

Steps to reproduce

Assuming you have already install the mocha plugin.

1.

Install the istanbul-instrumenter-loader webpack plugin since we are using the webpack build system.
I think there is no need to install the babel-plugin-istanbul because we are already using the webpack plugin. However they might also work together somehow.

2.

Add the istanbul-instrumenter-loader to your webpack config using vue-cli's chainWebpack option:

module.exports = {
  ...
  chainWebpack: config => {
    ...

    if (isTesting) {
      config.module.rule('js')
        .use('istanbul')
        .loader('istanbul-instrumenter-loader')
        .options({ esModules: true })
        .before('babel-loader')

      config.output
        .devtoolModuleFilenameTemplate('[absolute-resource-path]')
        .devtoolFallbackModuleFilenameTemplate('[absolute-resource-path]?[hash]')

      config.devtool('inline-cheap-module-source-map')
    }
  }
}

Important: Insert the istanbul-instrumenter-loader before the babel-loader! This caused the

TypeError: Cannot read property 'fileCoverage' of undefined

error messages. I guess it had something todo with babel's transformation and he probable reuse of modules inside webpack (as describe in my earlier comment).
I'm not 100% sure if this breaks code coverage for modules written in ES6+ which are transpiled by babel after the istanbul-instrumenter-loader. So far all my modules looked okay.

3.

Update your test command to include all files (even vue). This is required so the instrument loader will also take non tested files into account. Also wrap the test command with nyc
In my case I changed the following scripts in my package.json:

    "test:unit": "vue-cli-service test:unit 'src/renderer/**/*.spec.js'",
    "coverage:unit": "nyc vue-cli-service test:unit 'src/renderer/**/*.{js,vue}'"

4.

(optional) Add a nycrc file:

 {
    "instrument": false,
    "sourceMap": false,
    "reporter": [
        "lcov",
        "text",
        "text-summary"
    ],
    "exclude": [
      "src/renderer/**/*.spec.js",
      "src/renderer/__mocks__/"
    ]
}

At the end this worked for me and the coverage of normal modules seems to be accurate. However I couldn't get coverage reports of .vue files to work (there's an issue).
And I don't know if placing the istanbul-instrumenter-loader before the babel-loader has any drawbacks.

Update: Using before caused the coverage to fail because of exceeded memory usage (FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory).
A quick test showed, that only the post() webpack-chain shorthand does not work.

The istanbul-instrument-loader is included after the babel-loader now, I guess.

My configuration changed to that (vue.config.js):

...
config.module.rule('js')
        .use('istanbul')
        .loader('istanbul-instrumenter-loader')
        .options({ esModules: true })
...

I can not get this working and I have the same issue as @jdoubleu when i created a project using [email protected] . It produces a coverage folder but there is no line coverage in the report. just the same as the out put of the cli below.

I have the same nyc config in my package.json as @yusufkaracin

My vue.config.js file

const path = require('path')

module.exports = { 
  chainWebpack: (config) => {
      var test = path.resolve(__dirname, 'test');
      var src = path.resolve(__dirname, 'src');
      var nodes = path.resolve(__dirname, 'node_modules');
      config.module
        .rule('istanbul')
          .test(/\.(js)$/)
          .enforce('post')
          .include.add(test).add(src)
          .end()
          .exclude.add(nodes)
          .end()
          .use('istanbul-instrumenter-loader')
            .loader('istanbul-instrumenter-loader')
            .options({ produceSourceMap: true, esModules: true }); 
  }
}

```
one error printed
WEBPACK Failed to compile with 1 error(s)

Error in ./src/components/HelloWorld.vue?vue&type=script&lang=js&

Module build failed (from ./node_modules/istanbul-instrumenter-loader/dist/cjs.js):
TypeError: Cannot read property 'fileCoverage' of undefined

ERROR mocha-webpack exited with code 1.

=============================== Coverage summary ==================
Statements : Unknown% ( 0/0 )
Branches : Unknown% ( 0/0 )
Functions : Unknown% ( 0/0 )

Lines : Unknown% ( 0/0 )

```

@martinnaughton I had similar problems, did you solve this problem?

I am also getting this error. Couldn't find out any solution...

Module build failed (from ./node_modules/istanbul-instrumenter-loader/dist/cjs.js):
TypeError: Cannot read property 'fileCoverage' of undefined

I can not get this working and I have the same issue as @jdoubleu when i created a project using [email protected] . It produces a coverage folder but there is no line coverage in the report. just the same as the out put of the cli below.
I have the same nyc config in my package.json as @yusufkaracin
My vue.config.js file

const path = require('path')

module.exports = { 
  chainWebpack: (config) => {
      var test = path.resolve(__dirname, 'test');
      var src = path.resolve(__dirname, 'src');
      var nodes = path.resolve(__dirname, 'node_modules');
      config.module
        .rule('istanbul')
          .test(/\.(js)$/)
          .enforce('post')
          .include.add(test).add(src)
          .end()
          .exclude.add(nodes)
          .end()
          .use('istanbul-instrumenter-loader')
            .loader('istanbul-instrumenter-loader')
            .options({ produceSourceMap: true, esModules: true }); 
  }
}
one error printed
 WEBPACK  Failed to compile with 1 error(s)

Error in ./src/components/HelloWorld.vue?vue&type=script&lang=js&

  Module build failed (from ./node_modules/istanbul-instrumenter-loader/dist/cjs.js):
  TypeError: Cannot read property 'fileCoverage' of undefined

 ERROR  mocha-webpack exited with code 1.

=============================== Coverage summary ==================
Statements   : Unknown% ( 0/0 )
Branches     : Unknown% ( 0/0 )
Functions    : Unknown% ( 0/0 )
Lines        : Unknown% ( 0/0 )
================================================================

@martinnaughton I had similar problems, did you solve this problem?

Im also having this problem, I'm also using Typescript and followed this tutorial for typescript
https://istanbul.js.org/docs/tutorials/typescript/

This config is working for me, sort of :

devtool: 'eval-source-map'
// ...
config.module
        .rule('js')
        .use('istanbul')
        .loader('istanbul-instrumenter-loader')
        .options({ esModules: true })
        .before('babel-loader')
// and the same for rule('ts')

And I removed babel-plugin-istanbul

For .vue files, the fixWebpackSourcePaths options of karma-coverage-istanbul-reporter looks promising (it cleans the resource path from vue-loader which contains the loaders string and query parameters)

can anyone help me I'm using

@vue/cli-plugin-unit-mocha and Typescript,

added this in my vue.config.js

const path = require('path')
      config.module
        .rule('istanbul')
        .test(/\.(ts|vue)$/)
        .enforce('post')
        .include.add(path.resolve(__dirname, '/src'))
        .end()
        .use('istanbul-instrumenter-loader')
        .loader('istanbul-instrumenter-loader')
        .options({ esModules: true })

here my nyc config

"nyc": {
    "check-coverage": true,
    "per-file": true,
    "lines": 90,
    "statements": 90,
    "functions": 90,
    "branches": 90,
    "include": [
      "src/**/*.{ts,vue}"
    ],
    "reporter": [
      "lcov",
      "text-summary"
    ],
    "extension": [
      ".ts", "*.vue"
    ],
    "cache": true,
    "all": true
  }

all tests passing, but no coverage generated.

 337 passing (18s)
  3 pending

 MOCHA  Tests completed successfully


=============================== Coverage summary ===============================
Statements   : Unknown% ( 0/0 )
Branches     : Unknown% ( 0/0 )
Functions    : Unknown% ( 0/0 )
Lines        : Unknown% ( 0/0 )
================================================================================

@silva96 There are maybe other issues but I'm pretty sure you need to remove the slash from '/src'. And maybe remove the * from "*.vue" too.

thanks @rndmerle I fixed that and then the error decribed by others appeared.

Module build failed (from ./node_modules/istanbul-instrumenter-loader/dist/cjs.js):
  TypeError: Cannot read property 'fileCoverage' of undefined

Using a dedicated post-rule never worked for me either. What did work was to plug istanbul before babel-loader/ts-loader and cache-loader:

config.module
        .rule('js')
        .use('istanbul')
        .loader('istanbul-instrumenter-loader')
        .options({ esModules: true })
        .after('cache-loader')
config.module
        .rule('ts')
        .use('istanbul')
        .loader('istanbul-instrumenter-loader')
        .options({ esModules: true })
        .after('cache-loader')

Make sure to check the resulting rules with vue inspect.

Using a dedicated post-rule never worked for me either. What did work was to plug istanbul before babel-loader/ts-loader and cache-loader:

config.module
        .rule('js')
        .use('istanbul')
        .loader('istanbul-instrumenter-loader')
        .options({ esModules: true })
        .after('cache-loader')
config.module
        .rule('ts')
        .use('istanbul')
        .loader('istanbul-instrumenter-loader')
        .options({ esModules: true })
        .after('cache-loader')

Make sure to check the resulting rules with vue inspect.

@rndmerle that didn't make the trick I believe, can you provide your config nyc in package.json, babel config and vue.config.js ?

Here are the config files. However, I'm not using Mocha at all. I came across this thread while trying to configure the coverage on Cypress tests.

.nyrc.json

{
  "include": [
    "src/**/*.{ts,js,vue}"
  ],
  "exclude": [
    "**/*.{spec,test}.{js,ts}",
    "**/*.d.ts",
    "*/types/**/*.ts"
  ],
  "extension": [
    ".ts",
    ".js",
    ".vue"
  ],
  "all": true,
  "check-coverage": false
}

babel.config.js

module.exports = {
  plugins: process.env.COVERAGE === 'true' ? ['istanbul'] : [],
  presets: ['@vue/app'],
}

There is nothing relevant anymore in vue.config.js because I switched from istanbul-instrumenter-loader to babel-plugin-istanbul. Both were working tho.

@rndmerle unfortunately it didn't work switching from istanbul-instrumenter-loader to babel-plugin-istanbul

it gives me this error now.

 MOCHA  Testing...

 RUNTIME EXCEPTION  Exception occurred while loading your tests

TypeError: Cannot read property 'f' of undefined
    at Module.getTimezones (/Users/benja/dev/ventanilla-front/dist/webpack:/src/utils/functions.ts:62:1)
    at Module../src/store/modules/settings/getters.ts (/Users/benja/dev/ventanilla-front/dist/webpack:/src/store/modules/settings/getters.ts:35:1)
    at __webpack_require__ (/Users/benja/dev/ventanilla-front/dist/webpack:/webpack/bootstrap:25:1)
    at Module../src/store/modules/settings/index.ts (/Users/benja/dev/ventanilla-front/dist/main.js:408493:66)
    at __webpack_require__ (/Users/benja/dev/ventanilla-front/dist/webpack:/webpack/bootstrap:25:1)
    at Module../src/store/index.ts (/Users/benja/dev/ventanilla-front/dist/main.js:372220:75)
    at __webpack_require__ (/Users/benja/dev/ventanilla-front/dist/webpack:/webpack/bootstrap:25:1)
    at Module../src/utils/functions.ts (/Users/benja/dev/ventanilla-front/dist/main.js:418113:64)
    at __webpack_require__ (/Users/benja/dev/ventanilla-front/dist/webpack:/webpack/bootstrap:25:1)
    at Module../node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/components/inputs/types/SeatSelectInput.vue?vue&type=script&lang=ts& (/Users/benja/dev/ventanilla-front/dist/main.js:32054:74)
    at __webpack_require__ (/Users/benja/dev/ventanilla-front/dist/webpack:/webpack/bootstrap:25:1)
    at Module../src/components/inputs/types/SeatSelectInput.vue?vue&type=script&lang=ts& (/Users/benja/dev/ventanilla-front/dist/webpack:/src/components/inputs/types/SeatSelectInput.vue?1a11:1:1)
    at __webpack_require__ (/Users/benja/dev/ventanilla-front/dist/webpack:/webpack/bootstrap:25:1)
    at Module../src/components/inputs/types/SeatSelectInput.vue (/Users/benja/dev/ventanilla-front/dist/webpack:/src/components/inputs/types/SeatSelectInput.vue?c837:1:1)
    at __webpack_require__ (/Users/benja/dev/ventanilla-front/dist/webpack:/webpack/bootstrap:25:1)
    at Module../node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/components/inputs/types/SeatMapBuilder.vue?vue&type=script&lang=ts& (/Users/benja/dev/ventanilla-front/dist/main.js:30215:102)
    at __webpack_require__ (/Users/benja/dev/ventanilla-front/dist/webpack:/webpack/bootstrap:25:1)
    at Module../src/components/inputs/types/SeatMapBuilder.vue?vue&type=script&lang=ts& (/Users/benja/dev/ventanilla-front/dist/webpack:/src/components/inputs/types/SeatMapBuilder.vue?a97d:1:1)
    at __webpack_require__ (/Users/benja/dev/ventanilla-front/dist/webpack:/webpack/bootstrap:25:1)
    at Module../src/components/inputs/types/SeatMapBuilder.vue (/Users/benja/dev/ventanilla-front/dist/webpack:/src/components/inputs/types/SeatMapBuilder.vue?56f0:1:1)
    at __webpack_require__ (/Users/benja/dev/ventanilla-front/dist/webpack:/webpack/bootstrap:25:1)
    at Module../tests/unit/components/inputs/types/SeatMapBuilder.spec.ts (/Users/benja/dev/ventanilla-front/dist/main.js:424121:101)
    at __webpack_require__ (/Users/benja/dev/ventanilla-front/dist/webpack:/webpack/bootstrap:25:1)
    at run (/Users/benja/dev/ventanilla-front/dist/webpack:/node_modules/mocha-webpack/lib/entry.js:3:1)
    at Array.forEach (<anonymous>)
    at Object../node_modules/mocha-webpack/lib/entry.js (/Users/benja/dev/ventanilla-front/dist/webpack:/node_modules/mocha-webpack/lib/entry.js:10:1)
    at __webpack_require__ (/Users/benja/dev/ventanilla-front/dist/webpack:/webpack/bootstrap:25:1)
    at /Users/benja/dev/ventanilla-front/dist/webpack:/webpack/bootstrap:116:1
    at Object.<anonymous> (/Users/benja/dev/ventanilla-front/dist/main.js:120:10)
    at Module._compile (internal/modules/cjs/loader.js:723:30)
    at Module.replacementCompile (/Users/benja/dev/ventanilla-front/node_modules/append-transform/index.js:58:13)
    at _module2.default._extensions.(anonymous function) (/Users/benja/dev/ventanilla-front/node_modules/mocha-webpack/lib/util/registerRequireHook.js:148:12)
    at Object.<anonymous> (/Users/benja/dev/ventanilla-front/node_modules/append-transform/index.js:62:4)
    at Module.load (internal/modules/cjs/loader.js:620:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:560:12)
    at Function.Module._load (internal/modules/cjs/loader.js:552:3)
    at Module.require (internal/modules/cjs/loader.js:659:17)
    at require (internal/modules/cjs/helpers.js:22:18)
    at /Users/benja/dev/ventanilla-front/node_modules/mocha/lib/mocha.js:250:27
    at Array.forEach (<anonymous>)
    at Mocha.loadFiles (/Users/benja/dev/ventanilla-front/node_modules/mocha/lib/mocha.js:247:14)
    at Mocha.run (/Users/benja/dev/ventanilla-front/node_modules/mocha/lib/mocha.js:576:10)
    at /Users/benja/dev/ventanilla-front/node_modules/mocha-webpack/lib/runner/TestRunner.js:191:27
    at /Users/benja/dev/ventanilla-front/node_modules/mocha-webpack/lib/webpack/compiler/registerReadyCallback.js:26:7
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/Users/benja/dev/ventanilla-front/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:63:1)
    at AsyncSeriesHook.lazyCompileHook (/Users/benja/dev/ventanilla-front/node_modules/tapable/lib/Hook.js:154:20)
    at emitRecords.err (/Users/benja/dev/ventanilla-front/node_modules/webpack/lib/Compiler.js:267:22)
    at Compiler.emitRecords (/Users/benja/dev/ventanilla-front/node_modules/webpack/lib/Compiler.js:449:39)
    at emitAssets.err (/Users/benja/dev/ventanilla-front/node_modules/webpack/lib/Compiler.js:261:10)
    at hooks.afterEmit.callAsync.err (/Users/benja/dev/ventanilla-front/node_modules/webpack/lib/Compiler.js:435:14)
    at _err0 (eval at create (/Users/benja/dev/ventanilla-front/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:16:1)
    at callback (/Users/benja/dev/ventanilla-front/node_modules/copy-webpack-plugin/dist/index.js:126:17)
    at afterEmit (/Users/benja/dev/ventanilla-front/node_modules/copy-webpack-plugin/dist/index.js:220:13)
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/Users/benja/dev/ventanilla-front/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:12:1)
    at AsyncSeriesHook.lazyCompileHook (/Users/benja/dev/ventanilla-front/node_modules/tapable/lib/Hook.js:154:20)
    at asyncLib.forEachLimit.err (/Users/benja/dev/ventanilla-front/node_modules/webpack/lib/Compiler.js:432:27)
    at /Users/benja/dev/ventanilla-front/node_modules/neo-async/async.js:2818:7
    at done (/Users/benja/dev/ventanilla-front/node_modules/neo-async/async.js:3522:9)
    at MemoryFileSystem.writeFile (/Users/benja/dev/ventanilla-front/node_modules/memory-fs/lib/MemoryFileSystem.js:328:9)
    at writeOut (/Users/benja/dev/ventanilla-front/node_modules/webpack/lib/Compiler.js:415:30)
    at asyncLib.forEachLimit (/Users/benja/dev/ventanilla-front/node_modules/webpack/lib/Compiler.js:426:7)
    at objectIteratorWithKey (/Users/benja/dev/ventanilla-front/node_modules/neo-async/async.js:3509:9)
    at timesSync (/Users/benja/dev/ventanilla-front/node_modules/neo-async/async.js:2297:7)
    at Object.eachLimit (/Users/benja/dev/ventanilla-front/node_modules/neo-async/async.js:3463:5)
    at emitFiles (/Users/benja/dev/ventanilla-front/node_modules/webpack/lib/Compiler.js:321:13)
    at Immediate._onImmediate (/Users/benja/dev/ventanilla-front/node_modules/memory-fs/lib/MemoryFileSystem.js:288:4)
    at processImmediate (timers.js:632:19)

 ERROR  mocha-webpack exited with code 1.

=============================== Coverage summary ===============================
Statements   : Unknown% ( 0/0 )
Branches     : Unknown% ( 0/0 )
Functions    : Unknown% ( 0/0 )
Lines        : Unknown% ( 0/0 )
================================================================================
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] test:unit: `nyc vue-cli-service test:unit --require ./tests/unit/setup.js --timeout 10000`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] test:unit script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/benja/.npm/_logs/2019-06-26T15_44_03_366Z-debug.log
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] test: `npm run test:unit`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] test script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/benja/.npm/_logs/2019-06-26T15_44_03_396Z-debug.log

Based on @caugner 's answer, I made it work in a simpler way (by skipping the step 2 and enhanced a bit the nyc configuration in package.json) I'm using Vue CLI-3 with Mocha-webpack as my tests runner.

Here's my current configuration:

[1/3] Install babel-plugin-istanbul + configure it in babel.config.js

npm install --save-dev babel-plugin-istanbul
// babel.config.js
module.exports = {
  presets: [
    '@vue/app'
  ],
  env: {
    test: {
      plugins: [
        ['istanbul', {
          useInlineSourceMaps: false
        }]
      ]
    }
  }
};



md5-9c842d1e51b564b09703695d81f22495



npm install nyc --save-dev



md5-33f356164752fbfe3ab370727c637230



// nyc.config.js
module.exports = {
  'check-coverage': false,
  'per-file': true,
  'skip-full': true,
  all: true,
  include: [
    'src/**/*.{js,vue}'
  ],
  exclude: [
    'src/*.js',
    '**/index.js'
  ],
  reporter: [
    'lcov',
    'text',
    'text-summary'
  ],
  extension: [
    '.js',
    '.vue'
  ]
};



md5-c085a0badeec20539ebe1e4d1e607a14



nyc vue-cli-service test:unit --require tests/setup.js

No more errors or anything else. I'm not sure if I am missing something but at first sight, coverage report seems to represent the reality of tests scenarios I've created so far.

EDIT: Updated configuration to fix wrong .vue file paths in the coverage report and enhance it to my personal taste

@stephsavoie Your solution is worked, Thanks a lot.

@stephsavoie with that solution my nyc output is only showing one .vue file, not all of them.

None of the solutions on here worked for me (either Vue files were excluded, or the line numbers and highlighting in all files was thrown off in the coverage reports). Basically, setting devtool to eval throws off line numbers, but setting it to cheap-module-eval-source-map results in duplication in Vue file paths, throwing Istanbul off.

There's an (admittedly hacky) way to fix this, and it involves just changing one line in one of Istanbul/nyc's dependencies. From the directory containing your vue.config.js file and node_modules directory, you can run this to change the line:

sed -i '' 's/source: pathutils.relativeTo(start.source, origFile),/source: origFile,/' node_modules/istanbul-lib-source-maps/lib/get-mapping.js

Of course, that's annoying to have to do every time the file gets changed (I'm looking at you, yarn), so you can automate running that script every time you go to run your tests.

Just for the sake of completeness, I wrote up a short gist that details everything you need to do to add tests (with coverage) to a Vue project: https://gist.github.com/lsapan/3bfd0ffc0fb3d4a036fce84f6eea142e

@stephsavoie thank you, your solution worked for me, but I'm wondering about the idea behind using tests/setup.js, what's the purpose of it as you did not post the content of this file?

@stephsavoie This works great, however once I upgraded from vue cli3 to version 4, it no longer works. Have you had any luck with the newer version of the cli?

I tried a bunch of things but still nyc report is not loading with vue files. Did anyone succeed with vue-cli-4?

@batuhantozun did you try my guide above? It’s a bit hacky, but it works.

https://gist.github.com/lsapan/3bfd0ffc0fb3d4a036fce84f6eea142e

Hello for me juste work with

Script in package.json
nyc vue-cli-service test:unit

.nycrc:

{
    "extension": [
      ".js",
      ".vue"
    ],
    "instrument": false,
    "sourceMap": false
}

vue.config.js:

module.exports = {
  chainWebpack: (config) => {
    if (process.env.NODE_ENV === 'test') {
      config.module.rule('js')
        .test(/\.js$/)
        .use('istanbul-instrumenter-loader')
        .loader('istanbul-instrumenter-loader')
        .options({
          esModules: true,
        });
    }
  },
};

Packages:
@vue/cli: 4.3.0
@vue/test-utils: 1.0.0-beta.32
vue: 2.6.11
istanbul-instrumenter-loader: 3.0.1
nyc: 15.0.1

Edit:
Like sayed @lsapan in gist istanbul duplicate the path for .vue files because in source maps the path of source looks like
``json { "source": ["file.vue"], "sourceRoot": ["/src/components/" ] } ```` This path it's computed in/src/components/file.vue and istanbul build path of file with path.resolve(path.dirname(origFile), file) origFileit's the absolute path of vue file andfile` it's path from source map.

So this produce path like /absolute/path/src/components/src/components/file.vue
The js files doesn't have this problems becauses the source it's absolute path (ex: /absolute/path/src/plugins/file.js).

I don't find the option to custom the source for vue file to obtain the absolute path in source,

The generation of source map seems correct for me. For me the problem is in istanbul.js so I have comment this issue to correct the build path in this case.
https://github.com/istanbuljs/istanbuljs/issues/464#issuecomment-610258911

@sebtiz13 config worked for me!

Hey, @arielj which version of vue-cli are you using?
Are you sure that in your coverage html report it generates you are seeing vue components not test files.

@stripathix I see code coverage information for the components (not the test files) but I do have that problem on the duplicated src/components string on the path so I can't see the code coverage details line by line on each component (it looks like the data is inside the json report, though), only the table with statements, branches, functions, lines %.

I have vue 2.6.11 and vue-cli-service 4.2.0 inside packages.json

Hi all, sorry if it's an obvious question, but I'm new to the Vue.
I have followed some of the examples here and now I am getting the coverage for all .vue components, but .js files just show 100 percent coverage, regardless If test exists or not. I must be missing something obvious?

I've tried a few of the solutions here on a Vue CLI (version 4.4.6, uses TypeScript) project with no luck - either I get 0% coverage across the board or it shows coverage for .js and/or .ts files but not .vue files - maybe that's just me being an idiot and expecting something that's not supposed to be there? Is it going to show the .vue files as .js or something like that?

Have a repro up here of the 0% coverage cropping up: https://github.com/Jack-Barry/vue-with-istanbul

Not really sure where to go from here. Feels like I'm in the right neighborhood but walked into the wrong building or something.

Edit: with some tweaks to the config in the demo repo, I've been able to get closer to the goal but still seeing 0% coverage

HelloWorld.vue
    ✓ renders props.msg when passed


  1 passing (30ms)

 MOCHA  Tests completed successfully

----------------|---------|----------|---------|---------|-------------------
File            | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------------|---------|----------|---------|---------|-------------------
All files       |       0 |        0 |       0 |       0 |                   
 HelloWorld.vue |       0 |        0 |       0 |       0 |                   
----------------|---------|----------|---------|---------|-------------------

Is there anyone who could get it working with TypeScript so far 😢?

Another comment here to bump this every other month 😞

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jgribonvald picture jgribonvald  Â·  3Comments

JIANGYUJING1995 picture JIANGYUJING1995  Â·  3Comments

Benzenes picture Benzenes  Â·  3Comments

wahidrahim picture wahidrahim  Â·  3Comments

Gonzalo2683 picture Gonzalo2683  Â·  3Comments