JuniorTour / vue-template-babel-compiler

Enable Optional Chaining(?.), Nullish Coalescing(??) and many new ES syntax for Vue.js SFC based on Babel
https://www.npmjs.com/package/vue-template-babel-compiler
120 stars 9 forks source link

Any idea how to get this to use babel-plugin-istanbul for coverage in templates? #38

Open trusktr opened 2 years ago

trusktr commented 2 years ago

I'm trying to do this in Webpack:

use: {
    loader: 'vue-loader',
    options: {
        compiler: require('vue-template-babel-compiler'),
        compilerOptions: {
            babelOptions: {
              plugins: [['babel-plugin-istanbul', {
                  extension: ['.js', '.vue'],
                  excludeNodeModules: false
              }]]
            }
        }
    }
};

hoping it will, for example, add coverage instrumentation for JS expressions inside <template>, but no luck.

Any ideas?

JuniorTour commented 2 years ago

This lib works fine with babel-plugin-istanbul coverage test


You may need:

1. Add babel-plugin-istanbul to your root/babel.config.js, not vue.config.js

// instrument code only during testing
const plugins = []
if (process.env.NODE_ENV === 'test') {
  plugins.push([
    "babel-plugin-istanbul", {
      extension: ['.js', '.vue'],
    }
  ])
}
module.exports = {
  presets: [
    '@vue/app'
  ],
  plugins
}

2. Collect coverage data by test tool like jest || cypress

I refered to this article.

And I added [vue-template-babel-compiler](https://github.com/JuniorTour/vue-template-babel-compiler) to this project, they all works fine.

image image image
trusktr commented 2 years ago

Hello @JuniorTour, does that instrument JS expressions inside the <template>, not just in the <script>?

JuniorTour commented 2 years ago

Too long; didn't read:

We can add instrument to template, but we have some obstacles from vue/component-compiler-utils


We can add instrument to template, by add option filename: 'newFilename.js' like this:

// vue.config.js
module.exports = {
  chainWebpack: (config) => {
    config.module
      .rule('vue')
      .use('vue-loader')
      .tap((options) => {
        options.compilerOptions.babelOptions = {
          filename: 'VueTemplateBabelCompilerCompiledRender.js',
        }
        options.compiler = require('vue-template-babel-compiler');
        return options;
      });
  },
};

This option value should be default to source code, Welcome for Pull Request to change it: https://github.com/JuniorTour/vue-template-babel-compiler/blob/53a01c08fd49be58499e99c54af16c9d118ad896/src/renderCompiler.js#L17

Then the render function from vue template will get instrument like this:

function cov_1b2esh9sgc() {
  // ...
}

cov_1b2esh9sgc()

var render = function {
  // ...
}

Because vue-template-babel-compiler use babel to compile the render function:

https://github.com/JuniorTour/vue-template-babel-compiler/blob/53a01c08fd49be58499e99c54af16c9d118ad896/src/renderCompiler.js#L16

However, node_modules/@vue/component-compiler-utils/dist/compileTemplate.js will reformat the instrumented render function, and throw a error, this is the obstacle.

https://github.com/vuejs/component-compiler-utils/blob/82a37174990e31eaec609887a0ec262f06b454dd/lib/compileTemplate.ts#L158-L168

// after process by @vue/component-compiler-utils
function render () {
  // ...
}

cov_1b2esh9sgc() // Error: cov_1b2esh9sgc not defined

var render = function {
  // ...
}

I am still thinking about solution, I want this lib can work for coverage too.

Your suggestions or pull request are also welcome. 😊