5
votes

I am trying to setup Angular2 (RC1 version) project with Karma. I was able to do this setup for ng2 beta.17, but for RC1 I am getting the following error:

Error: Error: XHR error (404 Not Found) loading http://localhost:9876/@angular/core/testing at XMLHttpRequest.wrapFn [as _onreadystatechange] (http://localhost:9876/base/node_modules/zone.js/dist/zone.js?11128be53f306ea156f04e90b0fb7f23fc2104a5:748:30) at ZoneDelegate.invokeTask (http://localhost:9876/base/node_modules/ zone.js/dist/zone.js?11128be53f306ea156f04e90b0fb7f23fc2104a5:341:38) at Zone.runTask (http://localhost:9876/base/node_modules/zone.js/dis t/zone.js?11128be53f306ea156f04e90b0fb7f23fc2104a5:238:48) at XMLHttpRequest.ZoneTask.invoke (http://localhost:9876/base/node_modules/zone.js/dist/zone.js?11128be53f306ea156f04e90b0fb7f23fc2104a5:408:34)
Error loading http://localhost:9876/@angular/core/testing'

Following is my Karma.conf.js

// Karma configuration
// Generated on Thu May 12 2016 10:43:29 GMT+0530 (India Standard Time)

module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',


    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher')
    ],

    // list of files / patterns to load in the browser
    files: [
      {pattern: 'dist/src/**/*.js', included:false, watched: true},
      // 'dist/src/**/*spec.js',
      'node_modules/es6-shim/es6-shim.js',
      'node_modules/zone.js/dist/zone.js',
      'node_modules/reflect-metadata/Reflect.js',
      'node_modules/systemjs/dist/system-polyfills.js',
      'node_modules/systemjs/dist/system.src.js',
      'karma-test-shim.js',
      'dist/systemjs.config.js',
      {pattern: 'node_modules/@angular/**/*.js', included: false, watched: true},
      {pattern: 'node_modules/@angular/**/*.js.map', included: false, watched: true},
    ],


    // list of files to exclude
    exclude: [
    ],


    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
    },


    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress'],


    // web server port
    port: 9876,


    // enable / disable colors in the output (reporters and logs)
    colors: true,


    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,


    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,


    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['Chrome'],


    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  })
}

And finally following is my karma-test-shim.js. This is where the issue is happening, as I have included @angular/core/testing, it complains:

/*global jasmine, __karma__, window*/
Error.stackTraceLimit = Infinity;

jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;

__karma__.loaded = function () {
};

System.map = {
    '@angular/*':'node_modules/@angular/*'
}

// System.paths = {
//     'test/*': '/base/scripts/test/*.js',
//     'build/*': '/base/scripts/build/*.js',
//     'angular2/*': 'angular2/*',
//     'rx': 'rx'
// };

System.config({
  packages: {
    'base/dist/app': {
      defaultExtension: false,
      format: 'register',
      map: Object.keys(window.__karma__.files)
        .filter(onlyAppFiles)
        .reduce(function (pathsMapping, appPath) {
          var moduleName = appPath.replace(/^\/base\/dist\/app\//, './').replace(/\.js$/, '');
          pathsMapping[moduleName] = appPath + '?' + window.__karma__.files[appPath];
          return pathsMapping;
        }, {})
    }
  }
});

System.import('@angular/core/testing').then(function (testing) {
  return System.import('@angular/platform-browser-dynamic/testing').then(function (providers) {
    testing.setBaseTestProviders(providers.TEST_BROWSER_PLATFORM_PROVIDERS,
      providers.TEST_BROWSER_APPLICATION_PROVIDERS);
  });
}).then(function () {
  return Promise.all(
    Object.keys(window.__karma__.files)
      .filter(onlySpecFiles)
      .map(function (moduleName) {
        console.log('Spec file --- '+moduleName);
        return System.import(moduleName);
      }));
}).then(function () {
  __karma__.start();
}, function (error) {
    console.log("Karma Error----- \n"+error);
  __karma__.error(error.stack || error);
});

function onlyAppFiles(filePath) {
  return /^\/base\/dist\/app\/(?!.*\.spec\.js$)([a-z0-9-_\.\/]+)\.js$/.test(filePath);
}

function onlySpecFiles(path) {
  return /\.spec\.js$/.test(path);
}
1

1 Answers

3
votes

Only defining @angular in the map block of your SystemJS configuration isn't enough. You need an entry in the packages block for each Angular2 module.

Here is the configuration I use for Karma (karma.conf.js):

module.exports = function(config) {
  config.set({
    basePath: '.',
    frameworks: ['jasmine'],

    files: [
      {pattern: 'node_modules/es6-shim/es6-shim.min.js', included: true, watched: true},
      {pattern: 'node_modules/reflect-metadata/Reflect.js', included: true, watched: true},
      {pattern: 'node_modules/zone.js/dist/zone.js', included: true, watched: true},
      {pattern: 'node_modules/systemjs/dist/system.src.js', included: true, watched: true},
      {pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false},
      {pattern: 'node_modules/@angular/**/*.js', included: false, watched: false},
      {pattern: 'karma-test-shim.js', included: true, watched: true},

      {pattern: 'app/**/*.js', included: false, watched: true},

      {pattern: 'app/**/*.ts', included: false, watched: false},
      {pattern: 'app/**/*.js.map', included: false, watched: false}
    ],
    (...)
});

And the content of my karma-test-shim.js file:

// Tun on full stack traces in errors to help debugging
Error.stackTraceLimit = Infinity;

jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;

__karma__.loaded = function() {};

var map = {
  'app': 'base/app',
  'rxjs': 'base/node_modules/rxjs',
  '@angular': 'base/node_modules/@angular'
};

var packages = {
  'app': { main: 'main.js',  defaultExtension: 'js' },
  'rxjs': { defaultExtension: 'js' }
};

var packageNames = [
  '@angular/common',
  '@angular/compiler',
  '@angular/core',
  '@angular/http',
  '@angular/platform-browser',
  '@angular/platform-browser-dynamic',
  '@angular/router',
  '@angular/router-deprecated',
  '@angular/testing',
  '@angular/upgrade',
];

packageNames.forEach(function(pkgName) {
  packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
});

packages['base/app'] = {
        defaultExtension: 'js',
        format: 'cjs',
        map: Object.keys(window.__karma__.files).filter(onlyAppFiles).reduce(createPathRecords, {})
    };

var config = {
  map: map,
  packages: packages
};

System.config(config);

System.import('@angular/platform-browser/src/browser/browser_adapter')
.then(function(browser_adapter) { browser_adapter.BrowserDomAdapter.makeCurrent(); })
.then(function() { return Promise.all(resolveTestFiles()); })
.then(function() { __karma__.start(); }, function(error) { __karma__.error(error.stack || error); });

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

function onlyAppFiles(filePath) {
  return /\/base\/app\/(?!.*\.spec\.js$).*\.js$/.test(filePath);
}

function onlySpecFiles(path) {
  return /\.spec\.js$/.test(path);
}

function resolveTestFiles() {
  return Object.keys(window.__karma__.files)  // All files served by Karma.
    .filter(onlySpecFiles)
    .map(function(moduleName) {
        // loads all spec files via their global module names (e.g.
        // 'base/dist/vg-player/vg-player.spec')
        return System.import(moduleName);
    });
}