Generating nyc coverage report for VueJS project with @vue/cli-plugin-unit-mocha, TypeScript and SFC's
Asked Answered
A

0

6

I am currently working on setting up a testing environment for a Vue project that uses the @vue/cli-plugin-unit-mocha to run unit tests. The project uses TypeScript and .vue Single-File-Components. I have successfully set-up my project to run unit tests and generate code coverage reports for TypeScript files but when I try adding tests for SFC's I get an error.

To generate coverage reports I use nyc + istanbul-instrumenter-loader. I think my configuration is correct for regular Typescript files but when it has to deal with .vue files istanbul-instrumenter-loader throws an error:

error  in ./src/pages/rapportages/components/reports-grid/reports-grid-container.vue?vue&type=script&lang=ts&
Module build failed (from ./node_modules/istanbul-instrumenter-loader/dist/cjs.js):
TypeError: Cannot read property 'fileCoverage' of undefined

To me it looks like the .vue file hasn't been properly transformed/transpiled.

This is my package.json:

{
 ...
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "test": "vue-cli-service test:unit src/**/__tests__/*.spec.ts --require mocha-setup.js",
    "test:ci": "yarn run test --reporter mocha-teamcity-reporter",
    "test:cover": "cross-env NODE_ENV=coverage nyc vue-cli-service test:unit src/**/__tests__/*.spec.ts --require mocha-setup.js"
  }
...
"nyc": {
    "sourceMap": false,
    "instrument": false,
    "extension": [
      ".ts",
      ".vue"
    ],
    "reporter": [
      "text",
      "lcov"
    ]
  },
}

and my vue.config.js:

...
const glob = require('glob')

path = require('path');
var nodeExternals = require('webpack-node-externals');
const isCoverage = process.env.NODE_ENV === 'coverage';

module.exports = {
  outputDir: "dist",
  assetsDir: "shared",
  pages,
  configureWebpack: {
    resolve: {
      alias: {
        'vue$': 'vue/dist/vue.esm.js',
        'vuex$': "vuex/dist/vuex.esm.js"
      },
      extensions: ['*', '.js', '.vue', '.json']
    },
    stats: {
      warningsFilter: /export .* was not found in/
    },
    devtool: process.env.NODE_ENV === 'development' ? 'source-map' : 'inline-cheap-module-source-map',
    output: {
      // use absolute paths in sourcemaps (important for debugging via IDE)
      devtoolModuleFilenameTemplate: '[absolute-resource-path]',
      devtoolFallbackModuleFilenameTemplate: '[absolute-resource-path]?[hash]'
    },
    module: {
      rules: [].concat(
        isCoverage ? {
          test: /\.(ts|vue)/,
          include: path.resolve('src'), // instrument only testing sources with Istanbul, after ts-loader runs
          loader: 'istanbul-instrumenter-loader',
          enforce: 'post',
          query: {
            esModules: true
          }
        } : []
      )
    },
    target: 'node',  // webpack should compile node compatible code
    externals: [nodeExternals()], // in order to ignore all modules in node_modules folder
  }
}

The file the test coverage fails on look as following:

reports-grid-container.spec.ts

import { expect } from 'chai';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import { store } from '@/shared/vuex/root-store';

import ReportsGridContainer from '../reports-grid-container.vue';
import { STORE_KEY } from '../constants';

describe('ReportsGridContainer', () => {
    it('creates store module with the store key defined in the constants file', () => {
        const localVue = createLocalVue();
        localVue.use(Vuex);

        const wrapper = shallowMount(ReportsGridContainer, {
            localVue,
            store
        });
        expect(wrapper.vm.$store.state[STORE_KEY]).to.not.equal(undefined);
    });
});

Istanbul throws an error because of the .vue file

Any help or directions would be greatly appreciated!

Adames answered 14/12, 2018 at 14:57 Comment(4)
Did you fix it?Armindaarming
@Armindaarming No unfortunately I wasn't able to get it to work and I fell back to using Jest istead of Mocha. I followed the default configuration for Vue in their guide to setting up tests with coverage.Adames
Do you remember what did you do? I followed their documentation, but I always get this 'fileCoverage' of undefined error message. The coverage results show up, but wrong though.Armindaarming
there is a github issue for this problem, at the time, there is no accurate solution that I could find github.com/vuejs/vue-cli/issues/1363Monometallism

© 2022 - 2024 — McMap. All rights reserved.