Karma testing with Angular2: Unexpected anonymous System.register call

When I run Karma Tests in Angular2 i get the following error.

Uncaught TypeError: Unexpected anonymous System.register call. at http://localhost:9876/base/node_modules/systemjs/dist/system.src.js?38538ebca96bc7b222f7e7ba15943f173a485f6e:2885

I suppose its because the var System is currently not available. Even if its actually loaded. Does anyone have an idea why this is not working?

Here is my stripped down configuration:

C:\project\karma.conf.js

module.exports = function(config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine'],
    files: [
      'node_modules/systemjs/dist/system.src.js',
      'node_modules/angular2/bundles/angular2.dev.js',
      'tests/**/*Spec.js'
    ],
    exclude: [
    ],
    preprocessors: {
    },
    reporters: ['progress'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: false,
    browsers: ['Chrome', 'Firefox'],
    singleRun: false,
    concurrency: Infinity
  })
}

C:\project\tests\MyTestSpec.ts This one line is enough to trigger the error.

import {describe, expect, it, xit, inject, beforeEachProviders} from 'angular2/testing';

that renders to C:\project\tests\MyTestSpec.js and produces an error on the first occurance of System

System.register([], function(exports_1) {
    return {
        setters:[],
        execute: function() {
        }
    }
});
//# sourceMappingURL=CmiCloudSpec.js.map

C:\project\tsconfig.json

{
  "compilerOptions": {
    "target": "es5",
    "module": "system",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false,
    "watch": true,
  },
  "exclude": [
    "node_modules",
    "typings/main",
    "typings/main.d.ts"
  ]
}

C:\project\src\node_modules

contains the folders angular2 and systemjs as well as karma, karma-jasmine, jasmine-core and typescript

Answers


The problem is that you should include all your test files into Karma directly within the files attribute of karma.conf.js. Because you don't define an outFile property in your tsc configuration (and that's fine here), the name of modules aren't specified into the compiled JS files.

You need rather to create a karma-test-shim.js file (that will be included) and configure SystemJS to load module by file names and import these file using System.import.

Here is a sample of karma-test-shim.js file:

Error.stackTraceLimit = Infinity;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;

__karma__.loaded = function() {};

System.config({
  packages: {
    'base/dist': {
        defaultExtension: false,
        format: 'cjs',
        map: Object.keys(window.__karma__.files).filter(onlyAppFiles).reduce(createPathRecords, {})
    }
  }
});

System.import('angular2/src/platform/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\/dist\/(?!.*\.spec\.js$).*\.js$/.test(filePath);
}

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

function resolveTestFiles() {
  return Object.keys(window.__karma__.files)
    .filter(onlySpecFiles)
    .map(function(moduleName) {
        return System.import(moduleName);
    });
}

and the corresponding configuration in karma.conf.js:

module.exports = function(config) {
  config.set({
    basePath: '.',
    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.dev.js', included: true, watched: true},
      {pattern: 'node_modules/angular2/bundles/http.dev.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},

      // paths loaded via module imports
      {pattern: 'dist/**/*.js', included: false, watched: true},

      // paths to support debugging with source maps in dev tools
      {pattern: 'src/**/*.ts', included: false, watched: false},
      {pattern: 'dist/**/*.js.map', included: false, watched: false}
    ],
    (...)
  });
};

It think that this article and its source code could help you:


Thank you very much. The explanation that the bundled files in 'tests/**/*Spec.js' could not be loaded made perfect sense.

And it is working now.

To keep the explanation simple I added the karma-test-shim.js to the files section and that was it.

I will change the files section style later.

module.exports = function(config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine'],
    files: [
      'node_modules/systemjs/dist/system.src.js',
      'node_modules/angular2/bundles/angular2.dev.js',
      'karma-test-shim.js',
      'tests/**/*Spec.js'
    ],
    exclude: [
    ],
    preprocessors: {
    },
    reporters: ['progress'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: false,
    browsers: ['Chrome', 'Firefox'],
    singleRun: false,
    concurrency: Infinity
  })
}

Another thing was necessary in the karma.conf.js file

basePath: '.',

proxies: {
    // required for component assets fetched by Angular's compiler
    '/src/': '/base/src/'
},

Needed because otherwise the tests will not be executed


Need Your Help

Why can't MonoDroid find my assemblies?

c# android xamarin.android xamarin-studio

I made a simple Android HelloWorld app using Xamarin Studio 4.2.3 that doesn't do anything except it prints out some message if a random number is greater than 0.5. It works just great on a Nexus 4...