"System is not defined" 在 运行 Karma 测试 Angular 2 应用程序时在节点模块中

"System is not defined" in node module when running Karma tests of Angular 2 app

当我 运行 "npm run test" 时,我曾经完成所有单元测试 运行ning。现在,在为我需要使用的库(称为 Wijmo)添加节点模块后,我在控制台中收到以下错误,这似乎阻止了我所有单元测试的执行(相反,出现了 Karma 浏览器绿色,没有测试 运行)。

需要注意的是,当使用 "npm start."

时,节点模块加载和 运行s 在应用程序本身没有问题

这是错误:

Chrome 57.0.2987 (Windows 7 0.0.0) ERROR
  Uncaught ReferenceError: System is not defined
  at node_modules/wijmo/wijmo.js:13

Chrome 57.0.2987 (Windows 7 0.0.0) ERROR
  Uncaught ReferenceError: System is not defined
  at node_modules/wijmo/wijmo.js:13

我是不是忘记在某处的配置中添加这个模块?或者可能是实际节点模块的问题?

karma.config.js:

// #docregion
module.exports = function(config) {

    var appBase    = 'app/';       // transpiled app JS and map files
    var appSrcBase = 'app/';       // app source TS files
    var appAssets  = '/base/app/'; // component assets fetched by Angular's compiler

    var testingBase    = 'testing/';       // transpiled test JS and map files
    var testingSrcBase = 'testing/';       // test source TS files

    config.set({
        basePath: '',
        frameworks: ['jasmine'],
        plugins: [
            require('karma-jasmine'),
            require('karma-chrome-launcher'),
            require('karma-jasmine-html-reporter'), // click "Debug" in browser to see it
            require('karma-htmlfile-reporter') // crashing w/ strange socket error
        ],

        client: {
            builtPaths: [appBase, testingBase], // add more spec base paths as needed
            clearContext: false // leave Jasmine Spec Runner output visible in browser
        },

        customLaunchers: {
            // From the CLI. Not used here but interesting
            // chrome setup for travis CI using chromium
            Chrome_travis_ci: {
                base: 'Chrome',
                flags: ['--no-sandbox']
            }
        },
        files: [
            'node_modules/lodash/lodash.js',
            'node_modules/wijmo/wijmo.js',
            'node_modules/wijmo/wijmo.chart.js',
            'node_modules/wijmo/wijmo.chart.interaction.js',
            // System.js for module loading
            'node_modules/systemjs/dist/system.src.js',

            // Polyfills
            'node_modules/core-js/client/shim.js',
            'node_modules/reflect-metadata/Reflect.js',

            // zone.js
            'node_modules/zone.js/dist/zone.js',
            'node_modules/zone.js/dist/long-stack-trace-zone.js',
            'node_modules/zone.js/dist/proxy.js',
            'node_modules/zone.js/dist/sync-test.js',
            'node_modules/zone.js/dist/jasmine-patch.js',
            'node_modules/zone.js/dist/async-test.js',
            'node_modules/zone.js/dist/fake-async-test.js',

            // RxJs
            { pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false },
            { pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false },

            // Paths loaded via module imports:
            // Angular itself
            { pattern: 'node_modules/@angular/**/*.js', included: false, watched: false },
            { pattern: 'node_modules/@angular/**/*.js.map', included: false, watched: false },

            { pattern: 'systemjs.config.js', included: false, watched: false },
            { pattern: 'systemjs.config.extras.js', included: false, watched: false },
            'karma-test-shim.js', // optionally extend SystemJS mapping e.g., with barrels

            // transpiled application & spec code paths loaded via module imports
            { pattern: appBase + '**/*.js', included: false, watched: true },
            { pattern: testingBase + '**/*.js', included: false, watched: true },


            // Asset (HTML & CSS) paths loaded via Angular's component compiler
            // (these paths need to be rewritten, see proxies section)
            { pattern: appBase + '**/*.html', included: false, watched: true },
            { pattern: appBase + '**/*.css', included: false, watched: true },

            // Paths for debugging with source maps in dev tools
            { pattern: appSrcBase + '**/*.ts', included: false, watched: false },
            { pattern: appBase + '**/*.js.map', included: false, watched: false },
            { pattern: testingSrcBase + '**/*.ts', included: false, watched: false },
            { pattern: testingBase + '**/*.js.map', included: false, watched: false}
        ],

        // Proxied base paths for loading assets
        proxies: {
            // required for component assets fetched by Angular's compiler
            "/app/": appAssets
        },

        exclude: [],
        preprocessors: {},
        // disabled HtmlReporter; suddenly crashing w/ strange socket error
        reporters: ['progress', 'kjhtml'],//'html'],

        port: 9876,
        colors: true,
        logLevel: config.LOG_INFO,
        autoWatch: true,
        browsers: ['Chrome'],
        singleRun: false
    })
}

业力测试-shim.js:

// /*global jasmine, __karma__, window*/
Error.stackTraceLimit = 0; // "No stacktrace"" is usually best for app testing.

// Uncomment to get full stacktrace output. Sometimes helpful, usually not.
// Error.stackTraceLimit = Infinity; //

jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;

// builtPaths: root paths for output ("built") files
// get from karma.config.js, then prefix with '/base/' (default is 'app/')
var builtPaths = (__karma__.config.builtPaths || ['app/'])
    .map(function(p) { return '/base/'+p;});

__karma__.loaded = function () { };

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

function isSpecFile(path) {
    return /\.spec\.(.*\.)?js$/.test(path);
}

// Is a "built" file if is JavaScript file in one of the "built" folders
function isBuiltFile(path) {
    return isJsFile(path) &&
        builtPaths.reduce(function(keep, bp) {
            return keep || (path.substr(0, bp.length) === bp);
        }, false);
}

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

System.config({
    baseURL: 'base',  // was originally /base... if ng2-translate messes up, try going back to that
    // Extend usual application package list with test folder
    packages: { 'testing': { main: 'index.js', defaultExtension: 'js' } },

    // Assume npm: is set in `paths` in systemjs.config
    // Map the angular testing umd bundles
    map: {
        '@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
        '@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
        '@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
        '@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
        '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
        '@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js',
        '@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
        '@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js',
        'ng2-translate': '/base/node_modules/ng2-translate'
    }
});

System.import('systemjs.config.js')
    .then(importSystemJsExtras)
    .then(initTestBed)
    .then(initTesting);

/** Optional SystemJS configuration extras. Keep going w/o it */
function importSystemJsExtras(){
    return System.import('systemjs.config.extras.js')
        .catch(function(reason) {
            console.log(
                'Warning: System.import could not load the optional "systemjs.config.extras.js". Did you omit it by accident? Continuing without it.'
            );
            console.log(reason);
        });
}

function initTestBed(){
    return Promise.all([
        System.import('@angular/core/testing'),
        System.import('@angular/platform-browser-dynamic/testing')
    ])

        .then(function (providers) {
            var coreTesting    = providers[0];
            var browserTesting = providers[1];

            coreTesting.TestBed.initTestEnvironment(
                browserTesting.BrowserDynamicTestingModule,
                browserTesting.platformBrowserDynamicTesting());
        })
}

// Import all spec files and start karma
function initTesting () {
    return Promise.all(
        allSpecFiles.map(function (moduleName) {
            return System.import(moduleName);
        })
    )
        .then(__karma__.start, __karma__.error);
}

package.json,以防万一:

{
  "name": "app",
  "version": "1.0.1",
  "scripts": {
    "start": "tsc && concurrently \"tsc -w\" \"lite-server\" \"npm run generate-css\" \"npm run watch-css\" ",
    "pree2e": "npm run webdriver:update",
    "e2e": "tsc && concurrently \"http-server -s\" \"protractor protractor.config.js\" --kill-others --success first",
    "lint": "tslint ./app/**/*.ts -t verbose",
    "generate-css": "node-sass -r app --output ./generated-css",
    "watch-css": "node-sass -w -r app --output ./generated-css",
    "lite": "lite-server",
    "test": "tsc && concurrently \"tsc -w\" \"karma start karma.conf.js\"",
    "test-once": "tsc && karma start karma.conf.js --single-run",
    "tsc": "tsc",
    "tsc:w": "tsc -w"
  },
  "license": "",
  "author": "me",
  "dependencies": {
    "@angular/animations": "4.0.2",
    "@angular/common": "4.0.2",
    "@angular/compiler": "4.0.2",
    "@angular/compiler-cli": "4.0.2",
    "@angular/core": "4.0.2",
    "@angular/forms": "4.0.2",
    "@angular/material": "^2.0.0-beta.3",
    "@angular/http": "4.0.2",
    "@angular/platform-browser": "4.0.2",
    "@angular/platform-browser-dynamic": "4.0.2",
    "@angular/platform-server": "4.0.2",
    "@angular/router": "4.0.2",
    "angular-in-memory-web-api": "0.2.4",
    "angular2-ui-switch": "1.2.0",
    "bootstrap": "3.3.7",
    "core-js": "2.4.1",
    "mydatepicker":"1.2.9",
    "ng2-translate": "5.0.0",
    "reflect-metadata": "0.1.9",
    "rxjs": "5.0.1",
    "socket.io": "1.7.2",
    "lodash": "4.17.4",
    "socket.io-client": "1.7.2",
    "systemjs": "0.19.40",
    "wijmo": "wijmo-system-min",
    "zone.js": "0.8.5",
    "typescript": "2.2.2"
  },
  "devDependencies": {
    "@types/core-js": "0.9.35",
    "@types/jasmine": "2.5.40",
    "@types/node": "6.0.58",
    "@types/selenium-webdriver": "2.53.39",
    "@types/lodash": "4.14.62",
    "canonical-path":"0.0.2",
    "codelyzer": "0.0.25",
    "concurrently": "3.1.0",
    "http-server": "0.9.0",
    "jasmine-core": "2.5.2",
    "karma": "1.3.0",
    "karma-chrome-launcher": "2.0.0",
    "karma-cli": "1.0.1",
    "karma-htmlfile-reporter": "0.3.4",
    "karma-jasmine": "1.1.0",
    "karma-jasmine-html-reporter": "0.2.2",
    "lite-server": "2.2.2",
    "live-server": "1.1.0",
    "lodash": "4.17.4",
    "node-sass": "3.13.1",
    "nodemon": "1.11.0",
    "protractor": "3.3.0",
    "rimraf": "2.5.4",
    "tslint": "3.15.1"
  }
}

systemjs.config.js

(function (global) {
    System.config({
        paths: {
            // paths serve as alias
            'npm:': 'node_modules/'
        },
        // map tells the System loader where to look for things
        map: {
            // our app is within the app folder
            app: 'app',
            // angular bundles
            '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
            '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
            '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
            '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
            '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
            '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
            '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
            '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',

            // other libraries
            'rxjs':                      'npm:rxjs',
            'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
            'ng2-translate':             'npm:ng2-translate/bundles',
            'lodash':                    'npm:lodash',
            'socket.io-client':          'npm:socket.io-client/socket.io.js',
            'mydatepicker':              'npm:mydatepicker',
            'wijmo':                     'npm:wijmo',
            'angular2-ui-switch':        'npm:angular2-ui-switch'
        },
        // packages tells the System loader how to load when no filename and/or no extension
        packages: {
            app: {
                main: './main.js',
                defaultExtension: 'js'
            },
            rxjs: {
                defaultExtension: 'js'
            },
            'ng2-translate': {
                main: 'ng2-translate',
                defaultExtension: 'umd.js'
            },
            'socket.io-client': {
                defaultExtension: 'js'
            },
            'mydatepicker': {
                main: './dist/index.js',
                defaultExtension: 'js'
            },
            'angular2-ui-switch': {
                main: './dist/index.js',
                defaultExtension: 'js'
            },
            lodash: {
                main: './lodash.js',
                defaultExtension: 'js'
            },
            wijmo: {
                main: './wijmo.js',
                defaultExtension: 'js'
            }
        }
    });
})(this);

我最终通过更新 .html 文档解决了这个问题,我在文档中定义了哪些测试显示在业力报告中。我很确定问题只是因为我没有在本文档中引用规范文件。由于 spec 文件是通过 karma 的正则表达式检测到的,它试图 运行 测试,但是当它没有在 .html 中定义时,它会抛出错误。