Karma + Webpack (babel-loader) + ES6 "Неожиданный импорт токена"

/edit: я полностью отключил конфигурацию до минимума, демонстрируя проблему. Я также загрузил рабочий проект в GitHub, который вы можете проверить, чтобы вы могли убедиться сами.

Проблемный вариант использования GitHub: webpack-angular15-es6-karma (скачать 7z-архив)

npm install
npm run build
npm run test

Я знаю, что есть несколько связанных вопросов, но мир движется так быстро, и существует так много факторов/зависимостей, что я не могу взломать эту проблему с текущими предлагаемыми решениями.

У меня есть конфигурация webpack, которая заботится обо всем моем исходном коде и отлично работает.

Для тестирования я повторно использую эту конфигурацию, чтобы позаботиться о единой центральной записи script, которая загружает как источники, так и тестовые файлы. Я не мог найти другой способ импортировать модули из моего исходного кода в свой тестовый код для тестирования.

Karma строит прекрасное повторное использование моей конфигурации webpack, но браузер сообщает об ошибке, как только она открывается.

Исходный код использует импорт ES6 и запросы на использование webpack.

package.json:

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

npm run test → > Начало кармы --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;
    }
};

Как вы можете видеть, я не использую плагины karma-babel: я не уверен, зачем мне это нужно, поскольку у меня уже есть рабочая сборка для кода с операторами 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);

Сборка webpack выполняется без заминки (и испускает кусок ожидаемого файла test_entry.js), но затем Karma открывает Chrome, и как только загружается страница, я приветствую следующую ошибку:

Chrome 51.0.2704 (Windows 7 0.0.0) ОШИБКА

Uncaught SyntaxError: неожиданный импорт токена

в файле__path/test_entry.js: 41

test_entry.js не имеет 41 строки и не содержит операторов импорта, и в любом случае они должны были быть рассмотрены. Что не так?

Если вы хотите узнать конфигурацию 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')
	},
};

Ответы

Ответ 1

Проблема заключается в том, что вы не транслируете свои тестовые источники - файл src/global/filters/dateFormat.filter.spec.js не был передан.

Вам нужно изменить конфигурацию загрузчика:

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

Как показано ниже, чтобы заставить его работать:

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

Также существует проблема с плагином webpack.optimize.CommonsChunkPlugin - он должен быть отключен для кармы: https://github.com/webpack/karma-webpack/issues/22

Чем после отключения этого плагина в вашем тестовом файле будут ошибки:

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");
        });
    });
});

в этом тесте несколько ошибок:

  • import jasmine from 'jasmine-core'; - вы не должны этого делать (карма будет делать, также она добавит describe, it и expect)
  • import readableNumberFilter from 'readableNumber.filter'; - это не так, как вы можете создавать экземпляры служб angular для их тестирования.

Вы должны сделать что-то вроде этого (этот тест действительно работает со всеми исправлениями, упомянутыми выше):

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");
        });
    });
});

Примечание: вам необходимо установить модуль angular-mocks;


Чтобы поддерживать отчет о покрытии кода, вам нужно настроить настройку конфигурации веб-пакета, чтобы использовать что-то вроде babel-istanbul-loader. Кстати, вам также нужно будет перейти на Babel6.

Также вам нужно будет настроить конфигурацию webpack config (конфигурации для тестирования и производства должны быть немного разными).

Я отправил вам запрос pull со всеми этими исправлениями: https://github.com/bbottema/webpack-angular15-es6-karma/pull/1


О создании проекта angular 1.x с webpack, включая тестирование с охватом кода через карму - возможно, вас будет интересовать мой проект: https://github.com/zxbodya/angular-webpack-seed - это стартовый шаблон со всеми необходимыми конфигурациями.