Karma 无法加载导入的文件
Karma cannot load imported files
由于我无法 运行 使用 Karma 进行任何实际测试,我已经为此苦苦挣扎了好几天。我可以 运行 不需要导入的测试(比如基本的健全性测试),但是一旦我必须从我的应用程序导入一些东西,我就会收到错误消息:
system.src.js:1085 GET http://localhost:9876/base/dist/components/test.service 404 (Not Found)fetchTextFromURL @ system.src.js:1085(anonymous function) @ system.src.js:1646ZoneAwarePromise @ angular2-polyfills.js:589(anonymous function) @ system.src.js:1645(anonymous function) @ system.src.js:2667(anonymous function) @ system.src.js:3239(anonymous function) @ system.src.js:3506(anonymous function) @ system.src.js:3888(anonymous function) @ system.src.js:4347(anonymous function) @ system.src.js:4599(anonymous function) @ system.src.js:337ZoneDelegate.invoke @ angular2-polyfills.js:332Zone.run @ angular2-polyfills.js:227(anonymous function) @ angular2-polyfills.js:576ZoneDelegate.invokeTask @ angular2-polyfills.js:365Zone.runTask @ angular2-polyfills.js:263drainMicroTaskQueue @ angular2-polyfills.js:482ZoneTask.invoke @ angular2-polyfills.js:434
angular2-polyfills.js:469 Unhandled Promise rejection: karma.error is not a function ; Zone: ; Task: Promise.then ; Value: TypeError: karma.error is not a function(…)consoleError @ angular2-polyfills.js:469drainMicroTaskQueue @ angular2-polyfills.js:498ZoneTask.invoke @ angular2-polyfills.js:434
angular2-polyfills.js:471 Error: Uncaught (in promise): TypeError: karma.error is not a function(…)
我需要提及:
示例测试:
import { provide } from 'angular2/core';
import {TestService} from './test.service';
import {
// beforeEach,
beforeEachProviders,
describe,
expect,
it,
inject,
// injectAsync
} from 'angular2/testing';
describe('TestService', () => {
beforeEachProviders(() => [
provide(TestService, {useClass: TestService})
]);
it('should say hello with name', inject([TestService], (testService: TestService) => {
expect(testService.name).toBe('Injected Service');
}));
it('should say hello with name', () => {
expect(true).toBe(true);
});
});
我的项目结构是基于多模块的:
Karma.conf.js:
frameworks: ['jasmine'],
files: [
// paths loaded by Karma
{ pattern: 'node_modules/angular2/bundles/angular2-polyfills.js', included: true, watched: true },
{ pattern: 'node_modules/systemjs/dist/system.src.js', included: true, watched: true },
{ pattern: 'node_modules/rxjs/bundles/rx.js', included: true, watched: true },
{ pattern: 'node_modules/angular2/bundles/angular2.js', included: true, watched: true },
{ pattern: 'node_modules/angular2/bundles/testing.dev.js', included: true, watched: true },
{ pattern: 'karma-test-shim.js', included: true, watched: true },
{ pattern: 'dist/components/matchers.js', included: true, watched: true },
// paths loaded via module imports
{ pattern: 'dist/components/**/*.js', included: false, watched: true },
// paths loaded via Angular's component compiler
// (these paths need to be rewritten, see proxies section)
{ pattern: 'dist/*.html', included: false, watched: true },
{ pattern: 'dist/styles/*.css', included: false, watched: true },
{ pattern: 'dist/components/**/*.html', included: false, watched: true },
{ pattern: 'dist/components/**/*.css', included: false, watched: true },
// paths to support debugging with source maps in dev tools
{ pattern: 'src/components/**/*.ts', included: false, watched: false },
{ pattern: 'dist/components/**/*.js.map', included: false, watched: false }
],
// proxied base paths
proxies: {
// required for component assests fetched by Angular's compiler
"/src/": "/base/src"
},
业力测试-shim.js:
...
System.config({
packages: {
'base/src': {
defaultExtension: false,
format: 'register',
map: Object.keys(window.__karma__.files).
filter(onlyAppFiles).
reduce(function createPathRecords(pathsMapping, appPath) {
// creates local module name mapping to global path with karma's fingerprint in path, e.g.:
// './hero.service': '/base/src/app/hero.service.js?f4523daf879cfb7310ef6242682ccf10b2041b3e'
var moduleName = appPath.replace(/^\/base\/src\//, './').replace(/\.js$/, '');
pathsMapping[moduleName] = appPath + '?' + window.__karma__.files[appPath]
return pathsMapping;
}, {})
}
}
});
function filePath2moduleName(filePath) {
console.log('filePath2moduleName', filePath)
return filePath.
replace(/^\//, ''). // remove / prefix
replace(/\.\w+$/, ''); // remove suffix
}
function onlyAppFiles(filePath) {
console.log('filePath', filePath)
return /^\/base\/src\/.*\.js$/.test(filePath)
}
function onlySpecFiles(path) {
return /.spec\.js$/.test(path);
}
非常欢迎任何想法!
如果你把你的TS文件编译到dist
文件夹里,我觉得你有差距。我会在你的 karma-test-shim.js
文件中尝试以下操作:
System.config({
packages: {
'base/dist': {
defaultExtension: false,
format: 'cjs',
map: Object.keys(window.__karma__.files).filter(onlyAppFiles).reduce(createPathRecords, {})
}
}
});
(...)
function createPathRecords(pathsMapping, appPath) {
var pathParts = appPath.split('/');
var moduleName = './' + pathParts.slice(Math.max(pathParts.length - 2, 1)).join('/');
moduleName = moduleName.replace(/\.js$/, '');
pathsMapping[moduleName] = appPath + '?' + window.__karma__.files[appPath];
return pathsMapping;
}
您的 createPathRecords
函数中的以下行看起来很奇怪,因为您不应该拥有来自 src
的文件,而是来自 dist
.
使用此代码,我生成了以下 SystemJS 配置(map
块):
System.config({
packages: {
'base/dist': {
defaultExtension: false,
format: 'register',
map: {
'./comps/my-list': '/base/dist/comps/my-list.js?e9(...)',
'./dist/my-app': '/base/dist/my-app.js?fe(...)',
'./pipes/my-pipe': '/base/dist/pipes/my-pipe.js?78(...)',
'./services/http-service': '/base/dist/services/http-service.js?c1(...)',
'./services/my-service': '/base/dist/services/my-service.js?b1(...)'
}
}
}
});
在你的情况下 /base/dist/components/test.service
无法被 SystemJS 解析,所以我猜你的 map
块不正确或者 packages
块的条目。
注意 map
块的条目是相对于 packages
块的键的。在您的情况下,我猜您会生成以下配置:
System.config({
packages: {
'base/src': {
defaultExtension: false,
format: 'register',
map: {
'./components/test.service': '/base/dist/components/test.service.js',
(...)
}
}
}
});
因此,为了调试您的问题,我将执行以下操作:
在您的 createPathRecords
函数中记录 appPath
:
reduce(function createPathRecords(pathsMapping, appPath) {
console.log('appPath = '+appPath);
(...)
}
记录整个 map
配置:
console.log(Object.keys(window.__karma__.files).filter(onlyAppFiles).reduce(createPathRecords, {}));
根据这些提示,您需要调整代码以具有此配置:
{
'./components/test.service': '/base/dist/components/test.service.js',
(...)
}
由于我无法 运行 使用 Karma 进行任何实际测试,我已经为此苦苦挣扎了好几天。我可以 运行 不需要导入的测试(比如基本的健全性测试),但是一旦我必须从我的应用程序导入一些东西,我就会收到错误消息:
system.src.js:1085 GET http://localhost:9876/base/dist/components/test.service 404 (Not Found)fetchTextFromURL @ system.src.js:1085(anonymous function) @ system.src.js:1646ZoneAwarePromise @ angular2-polyfills.js:589(anonymous function) @ system.src.js:1645(anonymous function) @ system.src.js:2667(anonymous function) @ system.src.js:3239(anonymous function) @ system.src.js:3506(anonymous function) @ system.src.js:3888(anonymous function) @ system.src.js:4347(anonymous function) @ system.src.js:4599(anonymous function) @ system.src.js:337ZoneDelegate.invoke @ angular2-polyfills.js:332Zone.run @ angular2-polyfills.js:227(anonymous function) @ angular2-polyfills.js:576ZoneDelegate.invokeTask @ angular2-polyfills.js:365Zone.runTask @ angular2-polyfills.js:263drainMicroTaskQueue @ angular2-polyfills.js:482ZoneTask.invoke @ angular2-polyfills.js:434 angular2-polyfills.js:469 Unhandled Promise rejection: karma.error is not a function ; Zone: ; Task: Promise.then ; Value: TypeError: karma.error is not a function(…)consoleError @ angular2-polyfills.js:469drainMicroTaskQueue @ angular2-polyfills.js:498ZoneTask.invoke @ angular2-polyfills.js:434 angular2-polyfills.js:471 Error: Uncaught (in promise): TypeError: karma.error is not a function(…)
我需要提及: 示例测试:
import { provide } from 'angular2/core';
import {TestService} from './test.service';
import {
// beforeEach,
beforeEachProviders,
describe,
expect,
it,
inject,
// injectAsync
} from 'angular2/testing';
describe('TestService', () => {
beforeEachProviders(() => [
provide(TestService, {useClass: TestService})
]);
it('should say hello with name', inject([TestService], (testService: TestService) => {
expect(testService.name).toBe('Injected Service');
}));
it('should say hello with name', () => {
expect(true).toBe(true);
});
});
我的项目结构是基于多模块的:
Karma.conf.js:
frameworks: ['jasmine'],
files: [
// paths loaded by Karma
{ pattern: 'node_modules/angular2/bundles/angular2-polyfills.js', included: true, watched: true },
{ pattern: 'node_modules/systemjs/dist/system.src.js', included: true, watched: true },
{ pattern: 'node_modules/rxjs/bundles/rx.js', included: true, watched: true },
{ pattern: 'node_modules/angular2/bundles/angular2.js', included: true, watched: true },
{ pattern: 'node_modules/angular2/bundles/testing.dev.js', included: true, watched: true },
{ pattern: 'karma-test-shim.js', included: true, watched: true },
{ pattern: 'dist/components/matchers.js', included: true, watched: true },
// paths loaded via module imports
{ pattern: 'dist/components/**/*.js', included: false, watched: true },
// paths loaded via Angular's component compiler
// (these paths need to be rewritten, see proxies section)
{ pattern: 'dist/*.html', included: false, watched: true },
{ pattern: 'dist/styles/*.css', included: false, watched: true },
{ pattern: 'dist/components/**/*.html', included: false, watched: true },
{ pattern: 'dist/components/**/*.css', included: false, watched: true },
// paths to support debugging with source maps in dev tools
{ pattern: 'src/components/**/*.ts', included: false, watched: false },
{ pattern: 'dist/components/**/*.js.map', included: false, watched: false }
],
// proxied base paths
proxies: {
// required for component assests fetched by Angular's compiler
"/src/": "/base/src"
},
业力测试-shim.js:
...
System.config({
packages: {
'base/src': {
defaultExtension: false,
format: 'register',
map: Object.keys(window.__karma__.files).
filter(onlyAppFiles).
reduce(function createPathRecords(pathsMapping, appPath) {
// creates local module name mapping to global path with karma's fingerprint in path, e.g.:
// './hero.service': '/base/src/app/hero.service.js?f4523daf879cfb7310ef6242682ccf10b2041b3e'
var moduleName = appPath.replace(/^\/base\/src\//, './').replace(/\.js$/, '');
pathsMapping[moduleName] = appPath + '?' + window.__karma__.files[appPath]
return pathsMapping;
}, {})
}
}
});
function filePath2moduleName(filePath) {
console.log('filePath2moduleName', filePath)
return filePath.
replace(/^\//, ''). // remove / prefix
replace(/\.\w+$/, ''); // remove suffix
}
function onlyAppFiles(filePath) {
console.log('filePath', filePath)
return /^\/base\/src\/.*\.js$/.test(filePath)
}
function onlySpecFiles(path) {
return /.spec\.js$/.test(path);
}
非常欢迎任何想法!
如果你把你的TS文件编译到dist
文件夹里,我觉得你有差距。我会在你的 karma-test-shim.js
文件中尝试以下操作:
System.config({
packages: {
'base/dist': {
defaultExtension: false,
format: 'cjs',
map: Object.keys(window.__karma__.files).filter(onlyAppFiles).reduce(createPathRecords, {})
}
}
});
(...)
function createPathRecords(pathsMapping, appPath) {
var pathParts = appPath.split('/');
var moduleName = './' + pathParts.slice(Math.max(pathParts.length - 2, 1)).join('/');
moduleName = moduleName.replace(/\.js$/, '');
pathsMapping[moduleName] = appPath + '?' + window.__karma__.files[appPath];
return pathsMapping;
}
您的 createPathRecords
函数中的以下行看起来很奇怪,因为您不应该拥有来自 src
的文件,而是来自 dist
.
使用此代码,我生成了以下 SystemJS 配置(map
块):
System.config({
packages: {
'base/dist': {
defaultExtension: false,
format: 'register',
map: {
'./comps/my-list': '/base/dist/comps/my-list.js?e9(...)',
'./dist/my-app': '/base/dist/my-app.js?fe(...)',
'./pipes/my-pipe': '/base/dist/pipes/my-pipe.js?78(...)',
'./services/http-service': '/base/dist/services/http-service.js?c1(...)',
'./services/my-service': '/base/dist/services/my-service.js?b1(...)'
}
}
}
});
在你的情况下 /base/dist/components/test.service
无法被 SystemJS 解析,所以我猜你的 map
块不正确或者 packages
块的条目。
注意 map
块的条目是相对于 packages
块的键的。在您的情况下,我猜您会生成以下配置:
System.config({
packages: {
'base/src': {
defaultExtension: false,
format: 'register',
map: {
'./components/test.service': '/base/dist/components/test.service.js',
(...)
}
}
}
});
因此,为了调试您的问题,我将执行以下操作:
在您的
createPathRecords
函数中记录appPath
:reduce(function createPathRecords(pathsMapping, appPath) { console.log('appPath = '+appPath); (...) }
记录整个
map
配置:console.log(Object.keys(window.__karma__.files).filter(onlyAppFiles).reduce(createPathRecords, {}));
根据这些提示,您需要调整代码以具有此配置:
{
'./components/test.service': '/base/dist/components/test.service.js',
(...)
}