Stryker: Investigate es6 support

Created on 25 May 2016  路  8Comments  路  Source: stryker-mutator/stryker

Do we support all language constructs from http://es6-features.org ?

Most helpful comment

How about this:

  1. We create a new repository. In that repository we add a file for every es2015 feature out there.
  2. We add a build process to test if each feature is supported. Supported means:

    • Stryker supports running mutation testing on it.

  3. In that build process, we test which features we could support. Could support means:
  4. We document exactly which features we currently support, which features we are going to support in the near feature, which features are not implemented yet by one of our dependencies in a handy readme.
  5. We create issues per feature we need to support.

All 8 comments

Esprima supports ES6 starting from version 2.0 (source). We use version ^2.7.0 by default (on my machine this is 2.7.2 as of right now).

Escodegen however does not seem to support arrow functions as the online demo states that the following code is invalid:
let multiply = (number) => { return number * 2 };. I do not know which version of Esprima the online demo is using.

_(I have not tried every ES6 feature)_

EDIT: I have created an issue

How about this:

  1. We create a new repository. In that repository we add a file for every es2015 feature out there.
  2. We add a build process to test if each feature is supported. Supported means:

    • Stryker supports running mutation testing on it.

  3. In that build process, we test which features we could support. Could support means:
  4. We document exactly which features we currently support, which features we are going to support in the near feature, which features are not implemented yet by one of our dependencies in a handy readme.
  5. We create issues per feature we need to support.

I'm excited for this! Any progress updates you are prepared to share?

I'm working on a branch which replaces the current mutaton generation process with Babel to mutate code :) I'll share the branch soon!

@CrazyBS Do you have any code that does not work with Stryker right now so I can test it?

@simondel Unfortunately, I am working on client-side code and can't share it. However, I will post the karma.conf.js and a partial package.json. Hopefully that will give you enough to be helpful, sorry I can't give you the direct source code.

package.json

{
  "private": true,
  "dependencies": {
    "babel-runtime": "^6.23.0",
    "bootstrap": "^3.3.7",
    "deep-freeze": "^0.0.1",
    "intl": "^1.2.5",
    "moment": "^2.18.1",
    "moment-business": "^3.0.1",
    "moment-timezone": "^0.5.13",
    "normalizr": "^3.2.2",
    "promise-polyfill": "^6.0.2",
    "prop-types": "^15.5.8",
    "react": "^15.4.2",
    "react-data-grid": "^2.0.39",
    "react-datepicker": "^0.46.0",
    "react-dom": "^15.4.2",
    "react-intl": "^2.3.0",
    "react-intl-redux": "^0.5.0",
    "react-redux": "^5.0.2",
    "react-router": "^3.0.2",
    "react-router-redux": "^4.0.8",
    "react-select": "^1.0.0-rc.5",
    "react-tap-event-plugin": "^2.0.1",
    "react-tooltip": "^3.3.0",
    "redux": "^3.6.0",
    "redux-observable": "^0.14.1",
    "rxjs": "^5.2",
    "styled-components": "^1.4.6"
  },
  "devDependencies": {
    "add-asset-html-webpack-plugin": "^1.0.2",
    "babel-core": "^6.23.1",
    "babel-eslint": "^7.1.1",
    "babel-loader": "^6.3.2",
    "babel-plugin-array-includes": "^2.0.3",
    "babel-plugin-istanbul": "^4.0.0",
    "babel-plugin-react-intl": "^2.3.1",
    "babel-plugin-syntax-dynamic-import": "^6.18.0",
    "babel-plugin-transform-class-properties": "^6.23.0",
    "babel-plugin-transform-object-assign": "^6.22.0",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-airbnb": "^2.2.3",
    "babel-preset-es2015": "^6.22.0",
    "babel-preset-react": "^6.23.0",
    "babel-preset-stage-2": "^6.22.0",
    "browser-sync": "^2.18.8",
    "browser-sync-webpack-plugin": "^1.1.4",
    "chai": "^3.5.0",
    "chalk": "^1.1.3",
    "command-line-args": "^4.0.5",
    "compression-webpack-plugin": "^0.4.0",
    "concurrently": "^3.3.0",
    "copy-webpack-plugin": "^4.0.1",
    "css-loader": "^0.26.1",
    "cucumber": "^2.0.0-rc.9",
    "debug": "^2.6.3",
    "enzyme": "^2.8.2",
    "eslint": "^3.16.1",
    "eslint-loader": "^1.6.3",
    "eslint-plugin-react": "^6.10.0",
    "exports-loader": "^0.6.3",
    "extract-text-webpack-plugin": "2.1.0",
    "file-loader": "^0.10.0",
    "html-webpack-plugin": "^2.28.0",
    "image-webpack-loader": "^3.2.0",
    "inject-loader": "^3.0.0",
    "intl-webpack-plugin": "^0.1.2",
    "jsdom": "^10.1.0",
    "json-loader": "^0.5.4",
    "karma": "^1.5.0",
    "karma-babel-preprocessor": "^6.0.1",
    "karma-chrome-launcher": "^2.0.0",
    "karma-coverage": "^1.1.1",
    "karma-coverage-istanbul-reporter": "^1.2.0",
    "karma-htmlfile-reporter": "^0.3.5",
    "karma-junit-reporter": "^1.2.0",
    "karma-mocha": "^1.3.0",
    "karma-mocha-reporter": "^2.2.2",
    "karma-phantomjs-launcher": "^1.0.2",
    "karma-sinon-chai": "^1.2.4",
    "karma-sonarqube-unit-reporter": "^0.0.11",
    "karma-sourcemap-loader": "^0.3.7",
    "karma-webpack": "^2.0.2",
    "mocha": "^3.2.0",
    "nightwatch": "^0.9.14",
    "nightwatch-cucumber": "^7.1.0",
    "node-sass": "^4.5.0",
    "phantomjs-prebuilt": "^2.1.14",
    "postcss-loader": "^1.3.0",
    "preload-image-loader": "^1.0.0",
    "proxy-middleware": "^0.15.0",
    "raw-loader": "^0.5.1",
    "react-addons-test-utils": "^15.4.2",
    "react-intl-translations-manager": "^5.0.0",
    "react-intl-webpack-plugin": "^0.0.3",
    "react-test-renderer": "^15.5.4",
    "redux-mock-store": "^1.2.2",
    "sinon": "^2.1.0",
    "sinon-chai": "^2.8.0",
    "string-replace-webpack-plugin": "^0.0.5",
    "style-loader": "^0.13.1",
    "stylus": "^0.54.5",
    "stylus-loader": "^3.0.1",
    "to-string-loader": "^1.1.5",
    "webpack": "^2.4.1",
    "webpack-dev-server": "^2.3.0",
    "webpack-merge": "^2.6.1",
    "webpack-visualizer-plugin": "^0.1.10",
    "write-file-webpack-plugin": "^3.4.2"
  },
  "scripts": {
    "lint": "eslint 'src/main/webapp/app/**/*.js'",
    "lint:fix": "eslint 'src/main/webapp/app/**/*.js' --fix",
    "start": "npm run webpack:dev",
    "test": "npm run lint && karma start src/test/webapp/karma.config.js",
    "test:watch": "karma start src/test/webapp/karma.config.js --watch",
    "webpack:dev": "webpack-dev-server --config webpack/webpack.dev.js  --progress --inline --hot --profile --history-api-fallback --port=9060",
    "webpack:build:dev": "webpack --config webpack/webpack.vendor.js && webpack --config webpack/webpack.dev.js && npm run manage:translations",
    "webpack:prod": "eslint -o build/reports/eslint/main.html -f html 'src/main/webapp/app/**/*.js' && eslint -o build/reports/eslint/main.xml -f checkstyle 'src/main/webapp/app/**/*.js' && karma start src/test/webapp/karma.config.js --no-color && webpack -p --config webpack/webpack.vendor.js && webpack -p --config webpack/webpack.prod.js && node ./translation-manager.js --exitCodeOnError --htmlReport build/reports/i18n",
    "dev:watch": "concurrently --kill-others --raw \"npm run webpack:dev\" \"npm run test:watch\"",
    "postinstall": "node node_modules/pngquant-bin/lib/install.js && node node_modules/phantomjs-prebuilt/install.js",
    "integrationTest": "nightwatch",
    "manage:translations": "node ./translation-manager.js"
  }
}

karma.conf.js

/* eslint-disable */
let path = require('path');
const WATCH = process.argv.indexOf('--watch') > -1;
const CHROME = process.argv.indexOf('--chrome') > -1;

module.exports = function(config) {
    config.set({
        basePath: path.join(__dirname, '..' , '..', '..'),

        frameworks: ['mocha', 'sinon-chai'],

        files: [
            'node_modules/intl/dist/Intl.js', // PhantomJS doesn't have Intl and needs a polyfill
            'src/test/webapp/app/**/*.spec.js',
        ],

        client: {
            chai: {
                includeStack: true
            }
        },

        preprocessors: {
            // add webpack as preprocessor
            'src/main/webapp/app/**/*.js': ['webpack', 'sourcemap'],
            'src/test/webapp/**/*.js': ['webpack', 'sourcemap']
        },

        webpack: { //kind of a copy of your webpack config
            devtool: 'inline-source-map', //just do inline source maps instead of the default
            module: {
                loaders: [
                    {
                        test: /\.js$/,
                        loader: 'eslint-loader',
                        enforce: 'pre',
                        exclude: ['node_modules'],
                        options: {
                            emitWarning: true
                        }
                    },
                    {
                        test: /\.css$/,
                        loaders: ['style-loader', 'css-loader'],
                        exclude: /(vendor\.css|global\.css)/
                    },
                    {
                        test: /\.styl$/,
                        loaders: ['style-loader', 'css-loader', 'stylus-loader'],
                        exclude: /(vendor\.scss|global\.scss)/
                    },
                    {
                        test: /\.(jpe?g|png|gif|svg|woff|woff2|ttf|eot)$/i,
                        loaders: [
                            'file-loader?hash=sha512&digest=hex&name=[hash].[ext]',
                            {
                                loader: 'image-webpack-loader',
                                query: {
                                    bypassOnDebug: true,
                                    optipng: {
                                        optimizationLevel: 7
                                    },
                                    gifsicle: {
                                        interlaced: false
                                    }
                                }
                            }
                        ]
                    },
                    {
                        test: /\.js$/,
                        loader: 'babel-loader',
                        exclude: path.resolve(path.join(__dirname, '..' , '..', '..'), 'node_modules'),
                        query: {
                            presets: ['stage-2', 'es2015', 'airbnb', 'react'],
                            plugins: [
                                ['istanbul', {'exclude': ['src/test/**/*.js','src/main/webapp/app/view/**/*.js']}],
                                'transform-class-properties',
                                'transform-object-assign',
                                'array-includes',
                                ['transform-runtime', { regenerator: false }]
                            ]
                        }
                    },
                    {
                        test: /\.json$/,
                        exclude: /webapp\/i18n\/.*\.json$/,
                        loader: 'json-loader',
                    }
                ]
            },
            externals: {
                'react/lib/ExecutionEnvironment': true,
                'react/lib/ReactContext': 'window',
                'react-dom/lib/ReactTestUtils': true,
                'react/addons': true,
                'cheerio': 'window'
            }
        },

        webpackServer: {
            noInfo: true //please don't spam the console when running in karma!
        },

        babelPreprocessor: {
            options: {
                presets: ['airbnb']
            }
        },

        webpackMiddleware: {
            stats: 'errors-only',
            noInfo: true
        },

        reporters: WATCH ? ['mocha', 'coverage-istanbul'] : ['mocha', 'junit', 'sonarqubeUnit', 'coverage-istanbul', 'html'],

        junitReporter: {
            outputFile: path.join('build', 'test-results', 'TEST-frontend.xml'),
            useBrowserName: false
        },

        htmlReporter: {
            outputFile: path.join('build', 'reports', 'mocha', 'index.html'),
            groupSuites: true,
            useCompactStyle: true
        },

        coverageIstanbulReporter: {
            reports: WATCH ? ['text-summary', 'html'] : ['lcovonly', 'text-summary', 'html'],
            dir: path.join('build', 'test-results', 'coverage'),
            'report-config': {
                html: {
                    subdir: '../../reports/istanbul'
                }
            }
            // thresholds: {
            //     global: {
            //         statements: 90,
            //         lines: 90,
            //         branches: 80,
            //         functions: 90
            //     }
            // }
        },

        mochaReporter: {
            showDiff: true
        },

        sonarQubeUnitReporter: {
            sonarQubeVersion: 'LATEST',
            outputFile: path.join('build', 'test-results', 'TEST-sonar.xml'),
            useBrowserName: false,
            suite: path.join('src', 'test', 'webapp', 'app'),
            filenameFormatter: (nextPath, result) => {
                return nextPath + '/' + result.suite[result.suite.length-1] + '.spec.js';
            },
            testnameFormatter: (testname, result) => {
                return result.description;
            }
        },

        phantomjsLauncher: {
            // Have phantomjs exit if a ResourceError is encountered (useful if karma exits without killing phantom)
            exitOnResourceError: true
        },

        port: 9876,
        colors: true,
        logLevel: WATCH ? config.LOG_DEBUG : config.LOG_INFO,
        autoWatch: WATCH,
        browsers: CHROME ? ['Chrome'] : ['PhantomJS'],
        singleRun: !WATCH,
    })
};

With the stryker-javascript-mutator and stryker-babel-transpiler we should have ES6 support. @CrazyBS You can track #525 for React support 馃憤

This issue can be closed. Anyone experiencing issues: please upgrade to the stryker-javascript-mutator

Was this page helpful?
0 / 5 - 0 ratings

Related issues

anthony-telljohann picture anthony-telljohann  路  19Comments

Chowarmaan picture Chowarmaan  路  18Comments

prsn670 picture prsn670  路  22Comments

j-truax picture j-truax  路  20Comments

simondel picture simondel  路  25Comments