web-dev-qa-db-fra.com

Karma + Webpack (babel-loader) + ES6 "Importation inattendue de jetons"

/edit: j'ai complètement dépouillé la configuration au minimum démontrant le problème. J'ai également téléchargé un projet de travail sur GitHub que vous pouvez vérifier, afin que vous puissiez voir par vous-même.

Cas d'utilisation problématique sur GitHub: webpack-angular15-es6-karma ( télécharger l'archive 7z )

npm install
npm run build
npm run test

Je sais qu'il y a quelques questions connexes, mais le monde évolue si vite et il y a tellement de facteurs/dépendances que je ne suis pas en mesure de résoudre ce problème avec les solutions proposées actuellement.

J'ai une configuration webpack qui s'occupe de tout mon code source et cela fonctionne très bien.

Pour les tests, je réutilise cette configuration pour prendre soin d'un script d'entrée central unique qui charge à la fois les sources et les fichiers de test. Je n'ai pas pu trouver un autre moyen d'importer des modules de mon code source dans mon code de test pour les tests.

Karma se construit très bien en réutilisant ma configuration webpack, mais le navigateur signale une erreur dès son ouverture.

Le code source utilise les importations ES6 et les instructions Webpack require.

package.json:

npm run build >>> webpack --config webpack.config.js --display-error-details --colors --progress

npm run test >>> karma start --single-run --no-auto-watch karma.config.js

{
  "name": "ProblemDemo",
  "scripts": {
    "build": "rimraf dist && webpack --config webpack.config.js --display-error-details --colors --progress",
    "test": "karma start --single-run --no-auto-watch karma.config.js"
  },
  "dependencies": {
    "angular": "^1.5.7",
    "angular-filter": "^0.5.8"
  },
  "devDependencies": {
      "webpack": "1.13.1",
      "html-loader": "0.4.3",
      "babel-loader": "5.3.2",
      "html-webpack-plugin": "1.6.1",
      "rimraf": "^2.5.3",
      "run-sequence": "1.1.2",
      "jasmine-core": "^2.4.1",
      "karma": "^0.13.19",
      "karma-chrome-launcher": "^0.2.2",
      "karma-coverage": "^0.5.3",
      "karma-jasmine": "^0.3.6",
      "karma-webpack": "^1.7.0",
      "loader-utils": "^0.2.12"
  }
}

karma.config.js:

module.exports = function (config) {
    config.set({
        browsers: ['Chrome'],
        coverageReporter: {
            reporters: [
                { type: 'html', subdir: 'html' },
                { type: 'lcovonly', subdir: '.' }
            ]
        },
        files: ['./tests.webpack.js'],
        frameworks: ['jasmine'],
        preprocessors: { './tests.webpack.js': ['webpack'] },
        reporters: ['progress', 'coverage'],
        webpack: configureWebpack()
    });

    function configureWebpack(webpackConfigFunction) {
        var webpackConfig = require('./webpack.config');
        webpackConfig.entry = undefined; // karma will pass the proper argument for entry
        return webpackConfig;
    }
};

Comme vous pouvez le voir, je n'utilise pas de plugins karma-babel: je ne sais pas pourquoi j'en aurais besoin, vu que j'ai déjà une construction de code de travail avec des instructions import/require.

test_entry.js:

var testsContext = require.context('./test', true, /\.js$/);
testsContext.keys().forEach(testsContext);

var srcContext = require.context('./app', true, /\.js$/);
srcContext.keys().forEach(srcContext);

La construction du webpack réussit sans accroc (et émet test_entry.js morceau de taille de fichier attendue), mais ensuite Karma ouvre Chrome et dès que la page est chargé, je suis accueilli avec l'erreur suivante:

ERREUR Chrome 51.0.2704 (Windows 7 0.0.0)

SyntaxError non capturée: importation inattendue de jetons

sur the_path/test_entry.js: 41

test_entry.js n'a pas 41 lignes et ne contient pas d'instructions d'importation et de toute façon elles auraient dû être prises en charge. Qu'est-ce qui ne va pas?

Si vous souhaitez également connaître la configuration du webpack:

// webpack.config.js, works perfectly for normal builds but not with Karma
var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
        debug: true,
        entry: {
                app: ['./app/index.js'],
                vendor: ['./app/vendor.js']
        },
        output: {
                path: path.join(__dirname, 'dist'),
                filename: 'js/[name].js'
        },
        plugins: [
                new HtmlWebpackPlugin({
                        template: './app/index.html',
                        inject: 'body',
                        minify: false
                }),
                new webpack.optimize.CommonsChunkPlugin('vendor', 'js/vendor.js'),
                new webpack.SourceMapDevToolPlugin({
                        filename: '[file].map',
                        exclude: /vendor/
                })
        ],
        resolve: {
                extensions: ['', '.js'],
                alias: {
                        app: path.join(__dirname, 'app')
                }
        },
        module: {
                loaders: [
                        {
                                test: /\.js$/,
                                loader: 'babel-loader',
                                include: path.join(__dirname, 'app'),
                                exclude: path.join(__dirname, 'node_modules')
                        },
                        {
                                test: /\.html$/,
                                loader: 'html-loader'
                        }
                ]
        },
        resolveLoader: {
                root: path.join(__dirname, 'node_modules')
        },
};

Dans le cas où vous souhaitez voir mon test, requis par test_entry.js, que je ne peux pas exécuter:

import jasmine from 'jasmine-core';
import readableNumberFilter from './file_path/readableNumber.filter';

// for some reason needed, or else unexpected token errors during build:
var describe = jasmine.describe;
var it = jasmine.it;
var expect = jasmine.expect;

describe('readableNumber Filter', function () {
        describe('readableNumber Filter formatting', () => {
                it('it should support optional arguments', function () {
                        expect(readableNumberFilter("50.3")).toEqual("50,30");
                });
        });
});

modifier le 20-7-2016

Le problème persiste également avec les dépendances mises à jour du chargeur Babel (y compris la définition de l'option de préréglages es2015). "babel-core": "^ 6.11.4", "babel-loader": "^ 6.2.4", "babel-preset-es2015": "^ 6.9.0",

21
Benny Bottema

Le problème est que vous ne transpilez pas vos sources de test - fichier src/global/filters/dateFormat.filter.spec.js n'a pas été transposé.

Vous devez changer cette configuration de chargeur:

{
    test: /\.js$/,
    loader: 'babel-loader',
    include: path.join(__dirname, 'app'),
    exclude: path.join(__dirname, 'node_modules')
},

Comme suit, pour le faire fonctionner:

{
    test: /\.js$/,
    loader: 'babel-loader',
    include: [
        path.join(__dirname, 'app'),
        path.join(__dirname, 'test')
    ],
    exclude: path.join(__dirname, 'node_modules')
},

Il y a également un problème avec webpack.optimize.CommonsChunkPlugin plugin - il doit être désactivé pour le karma: https://github.com/webpack/karma-webpack/issues/22

Qu'après avoir désactivé ce plugin, il y a des erreurs dans votre fichier de test:

import jasmine from 'jasmine-core';

import readableNumberFilter from 'readableNumber.filter';

var describe = jasmine.describe;
var it = jasmine.it;
var expect = jasmine.expect;

describe('readableNumber Filter', function () {
    describe('readableNumber Filter formatting', () => {
        it('it should support optional arguments', function () {
            expect(readableNumberFilter("50.3")).toEqual("50,30");
        });
    });
});

il y a peu d'erreurs dans ce test:

  1. import jasmine from 'jasmine-core'; - vous ne devriez pas faire cela (le karma fera l'affaire, il ajoutera également describe, it et expect)
  2. import readableNumberFilter from 'readableNumber.filter'; - ce n'est pas la façon dont vous pouvez instancier angular, pour les tester.

Vous devriez faire quelque chose comme ceci (ce test fonctionne en fait avec tous les correctifs mentionnés ci-dessus):

import angular from 'angular';
import 'angular-mocks';

import testModule from '../../../../app/src/global/index';

const { module, inject } = angular.mock;

describe('readableNumber Filter', () => {
    beforeEach(module(testModule));

    let $filter;

    beforeEach(inject((_$filter_) => {
        $filter = _$filter_;
    }));

    describe('readableNumber Filter formatting', () => {
        it('it should support optional arguments', () => {
            const result = $filter('readableNumber')("50.3");
            expect(result).toEqual("50,30");
        });
    });
});

Remarque: vous devrez installer le module angular-mocks;


Pour prendre en charge les rapports de couverture de code, vous devrez configurer votre configuration de test de webpack pour utiliser quelque chose comme babel-istanbul-loader. Au fait, vous devrez également passer à Babel6.

Vous devrez également rendre la configuration de webpack plus configurable (les configurations pour les tests et la production doivent être légèrement différentes).

Je vous ai envoyé une pull-request avec toutes ces corrections: https://github.com/bbottema/webpack-angular15-es6-karma/pull/1


À propos de la construction angular 1.x avec webpack, y compris les tests avec une couverture de code via karma - peut-être que vous seriez intéressé par mon projet: https://github.com/zxbodya/ angular-webpack-seed - c'est un modèle de démarrage avec toutes les configurations requises.

33
Bogdan Savluk