4
votes

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

3

3 Answers

1
votes

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:

0
votes

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
  })
}
0
votes

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