12

I am facing issues getting Karma to work with SystemJS, Angular2 and Typescript.

Here is my karma.conf.js:

'use strict';
module.exports = function (config) {
    config.set({

        // base path, that will be used to resolve files and exclude
        basePath: '.',

        // frameworks to use
        frameworks: ['systemjs', 'jasmine'],

        plugins: ['karma-systemjs', 'karma-jasmine', 'karma-phantomjs-launcher'],

        files: [
            'node_modules/reflect-metadata/Reflect.js',
            'app/**/*.spec.ts',
            //'jspm_packages/system-polyfills.js',
            'karma-test-shim.js'
        ],

        systemjs: {
            configFile: "systemjs.config.js",
            config: {
                //baseURL: ".",
                transpiler: "typescript",
                paths: {
                    "systemjs": "jspm_packages/system.js",
                    "system-polyfills": "jspm_packages/system-polyfills.js",
                    "typescript": "node_modules/typescript/lib/typescript.js"
                },
                packages: {
                    'app': {
                        defaultExtension: 'ts'
                    }
                }
            },
            includeFiles: [
                'node_modules/reflect-metadata/Reflect.js'
            ],
            serveFiles: [
                'app/**/*.ts',
                'main-bundle.js'
            ]
        },


        // proxied base paths
        proxies: {
            // required for component assets fetched by Angular's compiler
            "/app/": "/base/app/",
            "/jspm_packages/": "/base/jspm_packages/",
            "/node_modules/": "/base/node_modules/"
        },


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


        // 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_DEBUG,


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


        // Start these browsers, currently available:
        // - Chrome
        // - ChromeCanary
        // - Firefox
        // - Opera
        // - Safari (only Mac)
        // - PhantomJS
        // - IE (only Windows)
        browsers: ['PhantomJS'],


        // If browser does not capture in given timeout [ms], kill it
        captureTimeout: 60000,


        // Continuous Integration mode
        // if true, it capture browsers, run tests and exit
        singleRun: true
    });
};

My karma-test-shim.js:

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

__karma__.loaded = function () {
};


function isJsFile(path) {
    return path.slice(-3) == '.js';
}

function isSpecFile(path) {
    return path.slice(-8) == '.spec.js';
}

function isBuiltFile(path) {
    var builtPath = '/base/app/';
    return isJsFile(path) && (path.substr(0, builtPath.length) == builtPath);
}

var allSpecFiles = Object.keys(window.__karma__.files)
    .filter(isSpecFile)
    .filter(isBuiltFile);

// Load our SystemJS configuration.
System.config({
    baseURL: '/base'
});

System.config(
    {
        map: {
            'rxjs': 'node_modules/rxjs',
            '@angular': 'node_modules/@angular',
            'app': 'app'
        },
        packages: {
            'app': {
                main: 'main.js',
                defaultExtension: 'js'
            },
            '@angular/core': {
                main: 'index.js',
                defaultExtension: 'js'
            },
            '@angular/compiler': {
                main: 'index.js',
                defaultExtension: 'js'
            },
            '@angular/common': {
                main: 'index.js',
                defaultExtension: 'js'
            },
            '@angular/platform-browser': {
                main: 'index.js',
                defaultExtension: 'js'
            },
            '@angular/platform-browser-dynamic': {
                main: 'index.js',
                defaultExtension: 'js'
            },
            'rxjs': {
                defaultExtension: 'js'
            }
        }
    });

Promise.all([
    System.import('@angular/core/testing'),
    System.import('@angular/platform-browser-dynamic/testing')
]).then(function (providers) {
    var testing = providers[0];
    var testingBrowser = providers[1];

    testing.setBaseTestProviders(testingBrowser.TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
        testingBrowser.TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);

}).then(function() {
    // Finally, load all spec files.
    // This will run the tests directly.
    return Promise.all(
        allSpecFiles.map(function (moduleName) {
            return System.import(moduleName);
        }));
}).then(__karma__.start, __karma__.error);

My systemjs.config.js:

(function (global) {

    // map tells the System loader where to look for things
    var map = {
        'app': 'app', // 'dist',
        'rxjs': 'node_modules/rxjs',
        'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
        '@angular': 'node_modules/@angular',
        'crypto': '@empty'// this fixed my last issue
    };

    // packages tells the System loader how to load when no filename and/or no extension
    var packages = {
        'app': {main: 'main.js', defaultExtension: 'js'},
        'rxjs': {defaultExtension: 'js'},
        'angular2-in-memory-web-api': {defaultExtension: 'js'}
    };

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

    // add package entries for angular packages in the form '@angular/common': { main: 'index.js', defaultExtension: 'js' }
    packageNames.forEach(function (pkgName) {
        packages[pkgName] = {main: 'index.js', defaultExtension: 'js'};
    });

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

    // filterSystemConfig - index.html's chance to modify config before we register it.
    if (global.filterSystemConfig) {
        global.filterSystemConfig(config);
    }

    System.config(config);

})(this);

When I run my tests with karma start karma.conf.js and my tests are located alongside the main ts files.

I get this error:

11 05 2016 17:02:24.306:DEBUG [web-server]: serving (cached): /Users/julien/Documents/projects/bignibou/bignibou-site/bignibou-client/node_modules/typescript/lib/typescript.js
PhantomJS 2.1.1 (Mac OS X 0.0.0) ERROR
  Error: eval code
    eval@[native code]
    F@/Users/julien/Documents/projects/bignibou/bignibou-site/bignibou-client/jspm_packages/system-polyfills.js:4:12217
    H@/Users/julien/Documents/projects/bignibou/bignibou-site/bignibou-client/jspm_packages/system-polyfills.js:4:11846
    when@/Users/julien/Documents/projects/bignibou/bignibou-site/bignibou-client/jspm_packages/system-polyfills.js:4:15520
    run@/Users/julien/Documents/projects/bignibou/bignibou-site/bignibou-client/jspm_packages/system-polyfills.js:4:14559
    _drain@/Users/julien/Documents/projects/bignibou/bignibou-site/bignibou-client/jspm_packages/system-polyfills.js:4:3250
    drain@/Users/julien/Documents/projects/bignibou/bignibou-site/bignibou-client/jspm_packages/system-polyfills.js:4:1667
    Evaluating /Users/julien/Documents/projects/bignibou/bignibou-site/bignibou-client/karma-test-shim.js
    Error loading /Users/julien/Documents/projects/bignibou/bignibou-site/bignibou-client/karma-test-shim.js


11 05 2016 17:02:24.316:DEBUG [karma]: Run complete, exiting.
11 05 2016 17:02:24.316:DEBUG [launcher]: Disconnecting all browsers
11 05 2016 17:02:24.324:DEBUG [launcher]: Process PhantomJS exited with code 0
11 05 2016 17:02:24.324:DEBUG [temp-dir]: Cleaning temp dir /var/folders/1p/pcqq7s0x58l_s7ds52gxt_fw0000gp/T/karma-62098834
11 05 2016 17:02:24.329:DEBUG [launcher]: Finished all browsers
npm ERR! Test failed.  See above for more details.

Can anyone please help?

balteo
  • 23,602
  • 63
  • 219
  • 412
  • Have you checked this tutorial and the sample project? https://jaxenter.com/awesome-testing-with-netbeans-angular-2-and-typescript-126078.html – Thomas May 11 '16 at 15:28
  • Thanks Thomas. I had a look at the suggested sample project but it is not based upon Karma-SystemJS. Have you personally managed to get a Karma/SystemJs/Typescript project? – balteo May 11 '16 at 15:48
  • The sample is using System.js, but based on older Angular 2 version. I assume that you configure your System.js wrong in the karma-shim. Do you have a 'base' directory? – Thomas May 11 '16 at 16:19
  • 1
    @balteo I suggest you install the `angular-cli` and generate a project there, the karma setup in generated projects uses the same tool chain. (TypeScript, Karma, SystemJS) – Brocco May 11 '16 at 17:14
  • 2
    Thanks all for your suggestions. I am rather trying to pinpoint what is wrong with my configuration by understanding the root of the problem. – balteo May 12 '16 at 07:01

2 Answers2

5

I've spent the past couple days looking at all the different A2 seeds/clis and 90% of them are using old A2 code and I found it to be difficult to interpret them into the newest A2 code.

I eventually found this. https://github.com/juliemr/ng2-test-seed

This got my karma tests running with systemjs. It is a very nice very simple project that gets the basics and no extra garbage forced on you.

You will need to change some file urls around to match whatever you are working with. Using this as I guide, I was able to get unit tests running with typescript and systemjs.

ribsies
  • 1,218
  • 2
  • 10
  • 16
  • including system-polyfill saved me when running with phantomjs – Cayan Sep 03 '16 at 16:39
  • actually with this i got the same problem like without it, i clone her repo and run build then tests, 0 of 0 tests - karma wont match to any file path – longbow Sep 07 '16 at 14:22
  • @longbow make sure you don't have symlinks in your path, or that symlinks are correctly followed – Sebas Dec 12 '16 at 11:16
4

I can see several problem in what you did.

First I think that you configure twice SystemJS:

  • once in the test-shim-karma.js file
  • once in the karma.conf.js one throught the SystemJS karma plugin.

Then you don't configure your source modules that will be used within your spec files:

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

You call several times the System.config method.

I would also add some entries in the files section of your karma.conf.js file:

files: [
  // Paths loaded by Karma
  {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/zone.js/dist/async-test.js', included: true, watched: true},
  {pattern: 'node_modules/systemjs/dist/system-polyfills.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},

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

  // Paths to support debugging with source maps in dev tools
  {pattern: 'app/**/*.ts', included: false, watched: true},
  {pattern: 'app/**/*.js.map', included: false, watched: false}
],

You could have a look at this project for a working configuration of Karma with Angular2 RC1 and TypeScript:

Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • Thanks Thierry. I have adapted my configuration to match yours. I get an error on mac osX that several peoples are getting with karma 0.13.22 see here: https://github.com/karma-runner/karma/issues/1751#issuecomment-220630693 – balteo May 30 '16 at 16:17
  • 1
    Most of times, this error corresponds to a wrong path in your `files` configuration. For example: `{pattern: 'node_modules/zone.js/dist/zonejs.js', included: true, watched: true},` instanceof `{pattern: 'node_modules/zone.js/dist/zone.js', included: true, watched: true},`. In old versions of Karma, the message isn't very explicit ;-) It was fixed in latest versions... – Thierry Templier Jun 03 '16 at 09:11
  • I use the latest version of Karma though – balteo Jun 04 '16 at 13:09
  • Do you have any tips to get more explicit error message? Which version are you referring to by "latest versions"? – balteo Jun 04 '16 at 13:26