我有一个用Typescript编写的大型Angular项目,它被Webpack变成了一个bundle . 当使用Karma时,我得到的是page reload issue,我无法解决 . 因此我转而尝试摩卡,但我无法让它正常工作 . 我已经按照this question的接受答案来解决这个问题 .

First problem

也许有人可以告诉我我做错了什么,或者告诉我正确的设置方法 .

我运行webpack-dev-server进行测试,如下所示:

./node_modules/.bin/webpack-dev-server --config webpack.test.config.js

这给了我一个网页,我可以看到测试运行输出 . 如果我更改了我的任何Typescript,那么捆绑包将被重建并且热模块重新加载,但是我在网页上收到错误:

TypeError: Cannot read property 'call' of undefined
    at callFn (eval at <anonymous> (test/test.build.js:8459:9), <anonymous>:4471:20)
    at Hook.Runnable.run (eval at <anonymous> (test/test.build.js:8459:9), <anonymous>:4464:7)
    at next (eval at <anonymous> (test/test.build.js:8459:9), <anonymous>:4810:10)
    at eval (eval at <anonymous> (test/test.build.js:8459:9), <anonymous>:4832:5)
    at timeslice (eval at <anonymous> (test/test.build.js:8459:9), <anonymous>:75:27)

如果我刷新页面,则测试再次运行 .

Second problem

我以前工作的指令测试现在中断了,因为范围对象与以前不同 . 我传入 $compile 函数的范围没有指令的函数 . 现在这些都在 scope.$$childTail 我不知道这是否是切换到Mocha或我做错了什么的副作用 .

webpack.config.js

var path = require('path');
var webpack = require('webpack');
var BundleTracker = require('webpack-bundle-tracker');

module.exports = {
      devtool: 'inline-source-map', //just do inline source maps instead of the default
      module: {
        loaders: [
          { test: /\.css$/, loader: "style-loader!css-loader" },
          {
            test: /\.json$/,
            loader: 'json',
          },
          {
            test: /\.ts(x?)$/,
            exclude: /node_modules/,
            loader: 'babel-loader!ts-loader',
            //loader: 'babel-loader?presets[]=es2015&presets[]=react!ts-loader'
          },
          {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            //loader: 'babel-loader?presets[]=es2015&presets[]=react!ts-loader'
          },
        {
            test: /masonry|imagesloaded|fizzy\-ui\-utils|desandro\-|outlayer|get\-size|doc\-ready|eventie|eventemitter/,
            loader: 'imports?define=>false&this=>window'
        }
        ],
      },
      resolve: {
        root: [ path.resolve('./ng/ng') ],
        extensions: ['', '.ts', '.tsx', '.js', '.css'],
       alias: {
           'react-dom': 'react/lib/ReactDOM',
      //    'react$'      : path.resolve(__dirname, 'node_modules/react/dist/react-with-addons.js'),
          'react/addons': path.resolve(__dirname, 'node_modules/react-addons/index.js'),
          'xeditable.css': path.resolve(__dirname, 'node_modules/angular-xeditable/dist/css/xeditable.css'),
          'textAngular.css': path.resolve(__dirname, 'node_modules/textangular/dist/textAngular.css'),
       }
      },
      externals: {
        'cheerio': 'window',
        'react': 'React',
        'react-addons': 'React',
        'react-dom': 'ReactDOM',
        'react-dom/server': true,
        //'react-addons-test-utils': true,
        'ChemDoodle': true,
        //'react': true,
        //'react/addons': true,
        //'react/lib/ExecutionEnvironment': true,
        //'react/lib/ReactContext': true
      },
      entry: {
               itracker: './ng/ng/app.ts',
      },
      output: {
        //path: '.',
        //publicPath: '/website/js/',
        path: path.resolve('.'),
        publicPath: 'http://localhost:3000/assets/bundles/', // Tell django to use this URL to load packages and not use STATIC_URL + bundle_name
        //filename: 'itracker.bundle.js'
        filename: "[name]-[hash].js",
      },
      plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NoErrorsPlugin(), // don't reload if there is an error
        new BundleTracker({filename: './webpack-stats.json'}),
        //new webpack.optimize.OccurenceOrderPlugin(),
        // Export a global jQuery
        new webpack.ProvidePlugin({
          $: "jquery",
          jQuery: "jquery",
          "window.jQuery": "jquery"
      })
      ]
}

webpack.test.config.js

var path = require('path');
var webpack = require('webpack')
var BundleTracker = require('webpack-bundle-tracker')

var config = require('./webpack.config.js');
const index = path.resolve(__dirname, './test/test_index.js');

config.entry = { tests: 'mocha!'+ index };

config.module.loaders = [
        {
            test: /\.ts(x?)$/,
            exclude: /node_modules/,
            loader: 'babel-loader!ts-loader',
        },
        {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
        },
        {
            test: /masonry|imagesloaded|fizzy\-ui\-utils|desandro\-|outlayer|get\-size|doc\-ready|eventie|eventemitter/,
            loader: 'imports?define=>false&this=>window'
        },
        {
            test: /(\.jpg|\.jpeg|\.png|\.gif)$/,
            loader: 'null-loader'
        },
        {
            test: /(\.css|\.less|\.scss)$/,
            loader: 'null-loader'
        },
        {
            test: /\.html$/,
            loader: 'ngtemplate?relativeTo=' + __dirname + '&prefix=/website/js!html'
        }
];

// config.plugins = config.plugins.concat([
//     // keeps hashes consistent between compilations
//     new webpack.optimize.OccurenceOrderPlugin(),

// ]);

config.output = {
    filename: 'test.build.js',
    path: 'test/',
    publicPath: 'http://0.0.0.0:3000/test',
};

config.devServer = {
    host: '0.0.0.0',
    port: 3000,
    hot: true,
    inline: true,
    historyApiFallback: true,
    watchOptions: {
        aggregateTimeout: 300,
        poll: 1000
    }
};

config.target = 'web';

module.exports = config;

test_index.js

// Add all tests to context so they are put in bundle
const context = require.context('.', true, /.+[st]\.spec\.tsx?$/);
context.keys().forEach(context);

// Add all partials to context so they are put in bundle
var templates = require.context('../partials', true, /\.html$/);
templates.keys().forEach(function(key) {  
  templates(key);
});

module.exports = context;

test.html

<!DOCTYPE html>
<html>
    <head>
        <title>Mocha</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="./node_modules/mocha/mocha.css" />

        <script src="/node_modules/react/dist/react-with-addons.js"></script>
        <script src="/node_modules/react-dom/dist/react-dom.js"></script>

        <script src="/test/test.build.js"></script>
    </head>
    <body>
    </body>
</html>