Karma cannot load imported files

匿名 (未验证) 提交于 2019-12-03 00:59:01

问题:

I've been struggling for days now with the fact I cannot run any real test with Karma. I can run tests which do not require imports (like basic sanity tests) but as soon I have to import something from my app I get the error:

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(…)

I need to mention : Example test:

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

My project structure Is multi module based like :

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" },  

karma-test-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); } 

Any idea very welcomed !

回答1:

If you compile your TS files into the dist folder, I think that you have a gap. I would try the following within your karma-test-shim.js file:

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

The following line in your createPathRecords function seems strange since you shouldn't have files from src but from dist.

With this code, I have the following SystemJS configuration generated (map block):

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(...)'       }     }   } }); 

In your case /base/dist/components/test.service can't be resolved by SystemJS so I guess that either your map block isn't correct or the entry for the packages one.

Notice that the entry of the map block are relative to the key of the packages one. In your case, I guess that you generate the following configuration:

System.config({   packages: {     'base/src': {       defaultExtension: false,       format: 'register',       map: {         './components/test.service': '/base/dist/components/test.service.js',         (...)       }     }   } }); 

So to debug your problem, I would do the following:

  • Logging the appPath within your createPathRecords function:

    reduce(function createPathRecords(pathsMapping, appPath) {   console.log('appPath = '+appPath);   (...) } 
  • Logging the whole map configuration:

    console.log(Object.keys(window.__karma__.files).filter(onlyAppFiles).reduce(createPathRecords, {})); 

Based on these hints, you need to adapt your code to have this configuration:

{   './components/test.service': '/base/dist/components/test.service.js',   (...) } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!