获取 WebStorm + Karma + Webpack 以加载 jQuery 用于 AngularJs 指令单元测试
Get WebStorm + Karma + Webpack to load jQuery for AngularJs Directive Unit Tests
注意: 这尤其会帮助 运行s karma.conf.js 通过 WebStorm 的人。
问题:
我试图 运行 对指令进行一些测试,但由于它不断返回,"TypeError: 'undefined' is not a function" 我开始缩小问题可能所在的范围。结果:它似乎在读取模板,但模板上的 div 好像是空的。
我的测试
describe("Main Component Directive", function() {
var $scope, $element, directiveTemplate;
beforeEach(angular.mock.module('app'))
beforeEach(inject(function ($rootScope, $compile) {
$scope = $rootScope.$new();
directiveTemplate = '<gk-directive></gk-directive>';
$element = $compile(directiveTemplate)($scope);
$scope.$digest();
}));
it("should show reset button when current time is <5s under session/breakLength", function() {
var button = $element.find(".button")
expect(button).toBeDefined();
console.log(button.text())
});
测试通过,但不会 console.log 此模板中的文本:
container.html
<div>
<div class="button">Button Here</div>
</div>
我的指令会不会有问题..?
module.exports = angular.module('app')
.directive('gkTimerDirective', function () {
return {
template: require('./container.html') //gets turned into a string by webpack's raw-loader
}
});
我一直在浏览 Whosebug 并且有很多测试不同类型的指令及其行为的示例,但似乎我在这里缺少一些基本的东西。我确实在 AngularJs 或 Angular-Mocks 之前添加了 jQuery。
我觉得我缺少一些基本的东西。如果我像我一样 console.log,我不应该得到 "Button Here",而不是两个单引号:" '' "?
更新
澄清一下,这里的关键问题是 AngularJs 在寻找 class 时没有使用 $element.find() 遍历 DOM,尽管jQuery 确实应该加载的事实。
我认为你的指令应该是
angular.module('app')
.directive('gkTimerDirective', function () {
return {
templateUrl: './container.html' //gets turned into a string by webpack's raw-loader
}
});
对发生的事情的解释
当我尝试 运行 使用 npm 运行 命令测试时,我注意到所有测试都通过了,但是当我 运行 通过 WebStorm 的 "Run karma.conf.js" 它表现得好像 jQuery 在 Angular 之前没有被加载,因此,它无法通过它的 class 找到 div,最后的测试,我在预加载 jQuery 的情况下使用 angular.element,继续失败。
我只能认为这是因为 jQuery 不容易被构建系统吸收。事实上,您可以看到 Webpack 在达到 jQuery 之后必须如何做一些额外的工作。
Hash: d234b2da503b21a23772
Version: webpack 1.12.9
Time: 395ms
Asset Size Chunks Chunk Names
main 2.77 MB 0, 1 [emitted] main
src/app.module.spec.js 2.77 MB 1, 0 [emitted] src/app.module.spec.js
chunk {0} main (main) 2.56 MB [rendered]
[0] ./src/app.module.spec.js 273 bytes {0} {1}
[1] ./src/jquery.js 1.38 MB {0} {1}
[2] (webpack)/buildin/module.js 251 bytes {0} {1}
[3] (webpack)/buildin/amd-options.js 43 bytes {0} {1}
[4] ./src/app.module.js 2.42 kB {0} {1}
[5] ./~/angular/index.js 48 bytes {0} {1}
[6] ./~/angular/angular.js 1.07 MB {0} {1}
[7] ./src/factories/index.js 1.03 kB {0} {1}
[8] ./src/factories/timer.service.js 9.16 kB {0} {1}
[9] ./src/timer/index.js 1.26 kB {0} {1}
[10] ./src/timer/gkTimer.directive.js 1.82 kB {0} {1}
[11] ./src/timer/gk-timer-container.html 144 bytes {0} {1}
[12] ./src/timer/timerContainerCtrl.controller.js 4.12 kB {0} {1}
[13] ./~/angular-mocks/angular-mocks.js 82.8 kB {0} {1}
[14] ./src/tests/timer.service.spec.js 3.27 kB {0} {1}
[15] ./src/tests/timer.spec.js 1.15 kB {0} {1} [built]
我仍然不确定为什么这是个问题,但它确实激发了解决方案。
解决方案
因为我只使用 jQuery 来测试指令,所以我只是将它添加到我在 Karma 上的文件列表中:
var path = require('path');
var _ = require('lodash');
var here = require('path-here');
// SET-UP SETTINGS
process.env.NODE_ENV = process.env.NODE_ENV || 'test';
// coverage always true when testing (for me)
var coverage = true // = process.env.COVERAGE === 'true';
// ci determines if autowatch and single run will be true or false
var ci = process.env.NODE_ENV === 'test:ci';
if (coverage) {
console.log('-- recording coverage --');
}
// all runs after the NODE_ENV has been set to 'test'
var webpackConfig = require('./webpack.config');
var entry = path.join(webpackConfig.context, webpackConfig.entry);
var preprocessors = {};
preprocessors[entry] = ['webpack'];
// SETTINGS INPUT
module.exports = function(config) {
config.set({
basePath: './',
frameworks: ['jasmine'],
files: [
'./node_modules/jquery/dist/jquery.js', // <-- Added it right here
entry
],
exclude: [],
preprocessors: preprocessors,
reporters: getReporters(),
webpack: webpackConfig,
webpackMiddleware: {noInfo: true},
coverageReporter: {
reporters: [
{type: 'lcov', dir: 'coverage/', subdir: '.'},
{type: 'json', dir: 'coverage/', subdir: '.'},
{type: 'text-summary'}
]
},
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: !ci,
browsers: ['PhantomJS'],
singleRun: ci,
browserNoActivityTimeout: 180000,
plugins: [
'karma-webpack',
'karma-jasmine',
'karma-coverage',
'karma-phantomjs-launcher'
]
});
};
function getReporters() {
var reps = ['progress'];
if (coverage) {
reps.push('coverage');
}
return reps;
}
现在,为了测试,首先加载 jQuery,然后 Angular 可以通过 class、id 或任何选择器 jQuery 搜索 DOM 元素允许。
但是对于生产呢?
我没有理由认为在我的情况下它可能不适用于生产构建,但如果这是你的问题,请尝试以下操作:https://github.com/webpack/webpack/issues/582
注意: 这尤其会帮助 运行s karma.conf.js 通过 WebStorm 的人。
问题:
我试图 运行 对指令进行一些测试,但由于它不断返回,"TypeError: 'undefined' is not a function" 我开始缩小问题可能所在的范围。结果:它似乎在读取模板,但模板上的 div 好像是空的。
我的测试
describe("Main Component Directive", function() {
var $scope, $element, directiveTemplate;
beforeEach(angular.mock.module('app'))
beforeEach(inject(function ($rootScope, $compile) {
$scope = $rootScope.$new();
directiveTemplate = '<gk-directive></gk-directive>';
$element = $compile(directiveTemplate)($scope);
$scope.$digest();
}));
it("should show reset button when current time is <5s under session/breakLength", function() {
var button = $element.find(".button")
expect(button).toBeDefined();
console.log(button.text())
});
测试通过,但不会 console.log 此模板中的文本: container.html
<div>
<div class="button">Button Here</div>
</div>
我的指令会不会有问题..?
module.exports = angular.module('app')
.directive('gkTimerDirective', function () {
return {
template: require('./container.html') //gets turned into a string by webpack's raw-loader
}
});
我一直在浏览 Whosebug 并且有很多测试不同类型的指令及其行为的示例,但似乎我在这里缺少一些基本的东西。我确实在 AngularJs 或 Angular-Mocks 之前添加了 jQuery。
我觉得我缺少一些基本的东西。如果我像我一样 console.log,我不应该得到 "Button Here",而不是两个单引号:" '' "?
更新
澄清一下,这里的关键问题是 AngularJs 在寻找 class 时没有使用 $element.find() 遍历 DOM,尽管jQuery 确实应该加载的事实。
我认为你的指令应该是
angular.module('app')
.directive('gkTimerDirective', function () {
return {
templateUrl: './container.html' //gets turned into a string by webpack's raw-loader
}
});
对发生的事情的解释
当我尝试 运行 使用 npm 运行 命令测试时,我注意到所有测试都通过了,但是当我 运行 通过 WebStorm 的 "Run karma.conf.js" 它表现得好像 jQuery 在 Angular 之前没有被加载,因此,它无法通过它的 class 找到 div,最后的测试,我在预加载 jQuery 的情况下使用 angular.element,继续失败。
我只能认为这是因为 jQuery 不容易被构建系统吸收。事实上,您可以看到 Webpack 在达到 jQuery 之后必须如何做一些额外的工作。
Hash: d234b2da503b21a23772
Version: webpack 1.12.9
Time: 395ms
Asset Size Chunks Chunk Names
main 2.77 MB 0, 1 [emitted] main
src/app.module.spec.js 2.77 MB 1, 0 [emitted] src/app.module.spec.js
chunk {0} main (main) 2.56 MB [rendered]
[0] ./src/app.module.spec.js 273 bytes {0} {1}
[1] ./src/jquery.js 1.38 MB {0} {1}
[2] (webpack)/buildin/module.js 251 bytes {0} {1}
[3] (webpack)/buildin/amd-options.js 43 bytes {0} {1}
[4] ./src/app.module.js 2.42 kB {0} {1}
[5] ./~/angular/index.js 48 bytes {0} {1}
[6] ./~/angular/angular.js 1.07 MB {0} {1}
[7] ./src/factories/index.js 1.03 kB {0} {1}
[8] ./src/factories/timer.service.js 9.16 kB {0} {1}
[9] ./src/timer/index.js 1.26 kB {0} {1}
[10] ./src/timer/gkTimer.directive.js 1.82 kB {0} {1}
[11] ./src/timer/gk-timer-container.html 144 bytes {0} {1}
[12] ./src/timer/timerContainerCtrl.controller.js 4.12 kB {0} {1}
[13] ./~/angular-mocks/angular-mocks.js 82.8 kB {0} {1}
[14] ./src/tests/timer.service.spec.js 3.27 kB {0} {1}
[15] ./src/tests/timer.spec.js 1.15 kB {0} {1} [built]
我仍然不确定为什么这是个问题,但它确实激发了解决方案。
解决方案
因为我只使用 jQuery 来测试指令,所以我只是将它添加到我在 Karma 上的文件列表中:
var path = require('path');
var _ = require('lodash');
var here = require('path-here');
// SET-UP SETTINGS
process.env.NODE_ENV = process.env.NODE_ENV || 'test';
// coverage always true when testing (for me)
var coverage = true // = process.env.COVERAGE === 'true';
// ci determines if autowatch and single run will be true or false
var ci = process.env.NODE_ENV === 'test:ci';
if (coverage) {
console.log('-- recording coverage --');
}
// all runs after the NODE_ENV has been set to 'test'
var webpackConfig = require('./webpack.config');
var entry = path.join(webpackConfig.context, webpackConfig.entry);
var preprocessors = {};
preprocessors[entry] = ['webpack'];
// SETTINGS INPUT
module.exports = function(config) {
config.set({
basePath: './',
frameworks: ['jasmine'],
files: [
'./node_modules/jquery/dist/jquery.js', // <-- Added it right here
entry
],
exclude: [],
preprocessors: preprocessors,
reporters: getReporters(),
webpack: webpackConfig,
webpackMiddleware: {noInfo: true},
coverageReporter: {
reporters: [
{type: 'lcov', dir: 'coverage/', subdir: '.'},
{type: 'json', dir: 'coverage/', subdir: '.'},
{type: 'text-summary'}
]
},
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: !ci,
browsers: ['PhantomJS'],
singleRun: ci,
browserNoActivityTimeout: 180000,
plugins: [
'karma-webpack',
'karma-jasmine',
'karma-coverage',
'karma-phantomjs-launcher'
]
});
};
function getReporters() {
var reps = ['progress'];
if (coverage) {
reps.push('coverage');
}
return reps;
}
现在,为了测试,首先加载 jQuery,然后 Angular 可以通过 class、id 或任何选择器 jQuery 搜索 DOM 元素允许。
但是对于生产呢?
我没有理由认为在我的情况下它可能不适用于生产构建,但如果这是你的问题,请尝试以下操作:https://github.com/webpack/webpack/issues/582