vendredi 9 février 2018

Code coverage with vue 2, typescript, mocha and karma

We are using Vue 2 in combination with Typescript and webpack 3. Vuex is used for state management. Our tests is run with Karma together with Mocha, Sinon, Expect and Avoriaz. Everything works great but I trying to get code coverage to work to get a better visual representation of what tests are missing.

Small representation of the folder structure

  • src

    • components
      • shared
      • button
        • button.vue
        • button.ts
    • index.ts
    • ...
  • tests

    • unit
      • components
        • shared
        • button
          • button.spec.test.ts
    • karma.conf.js
    • karma.coverage.js
    • index.ts
    • ...

button.vue

<template>
    <button onClick="handleClick" visible="visible"></button>
</template>

<script lang="ts" src="./button.ts"></script>

button.ts

import { Component, Prop, Vue } from 'vue-property-decorator';

@Component({})
export default class Button extends Vue {

    @Prop({ default: false })
    public visible: boolean;

    private onClick() {
       // do stuff
    }
}

I currently have not even created a button.spec.ts at all which is something I am trying to get the team to tackle using this informatoin and this is the result from the code coverage:

Code coverage

The coverage in general in the project:

✔ 332 tests completed
=============================== Coverage summary ===============================
Statements   : 43.88% ( 1847/4209 )
Branches     : 36.83% ( 952/2585 )
Functions    : 32.97% ( 456/1383 )
Lines        : 45.28% ( 1732/3825 )
================================================================================

But in general, the results are not actually showing the code coverage at all. Every file is like this:

Code lines

My questions

  • How do I get a better result for this? Am I missing something basic about code coverage?
  • How do I code cover functions that are only run in .vue-files?

Other files that might be related:

karma.coverage.js

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['mocha', 'chai', 'sinon'],
    files: [
      'index.ts'
    ],
    reporters: reporters,
    preprocessors: {
      'index.ts': ['webpack']
    },
    webpack: webpackConfig,
    webpackServer: {
      noInfo: true
    },
    junitReporter: {
      outputDir: 'reports/'
    },
    coverageReporter: {
      reporters: [{
        type: 'json',
        dir: '../../coverage/',
        subdir: '.'
      },
      {
        type: 'text-summary'
      },
    ]
    },
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: false,
    browsers: ['PhantomJS_custom'],
    customLaunchers: {
        'PhantomJS_custom': {
            base: 'PhantomJS',
            options: {
                windowName: 'my-window',
                settings: {
                    webSecurityEnabled: false
                },
            },
            flags: ['--remote-debugger-port=9003', '--remote-debugger-autorun=yes'],
            debug: false
        }
    },
    phantomjsLauncher: {
        // Have phantomjs exit if a ResourceError is encountered (useful if karma exits without killing phantom)
        exitOnResourceError: true
    },
    mime: {
      'text/x-typescript': ['ts']
    },
    singleRun: true,
    concurrency: Infinity
  });
};

unit/index.ts

import 'babel-polyfill';
import Vue from 'vue';

Vue.config.productionTip = false;

function requireAll(r: any): any {
    r.keys().forEach(r);
}

requireAll((require as any).context('./', true, /spec.ts$/));
requireAll((require as any).context('../../src/', true, /^(?!.*(main)).*ts$/));

Aucun commentaire:

Enregistrer un commentaire