2016-02-15 8 views
9

Ich baue eine Web-App mit Angular 2, SystemJS und Karma für Tests.Load Knotenmodul mit SystemJS und Karma in Angular 2

Ich versuche, den Knotenmodul ngrx/store in einem Test zu laden:

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

import { Store } from '@ngrx/store'; 

describe('Graphs store',() => { 
    let graphs; 

    beforeEach(inject([Store], (store: Store<any>) => { 
    graphs = store.select('graphs'); 
    })); 

    it('works',() => { 
    // expect graphs to do something... 
    }); 
}); 

jedoch nicht meine Tests mit der folgenden Meldung:

404: /@ngrx/store 
Chrome 48.0.2564 (Mac OS X 10.11.3) ERROR 
    Error: XHR error (404 Not Found) loading http://localhost:9876/@ngrx/store 

ich eigentlich das gleiche Problem in dev hatte auch, und es stellt sich heraus, SystemJS wusste nicht, wo @ngrx/store zu finden. Um dies zu lösen, habe ich dies:

System.config({ 
    packages: { 
    src: { 
     format: 'register', 
     defaultExtension: 'js' 
    } 
    }, 
    map: { '@ngrx/store' : 'node_modules/@ngrx/store/dist/store.js' } // <-- this 
}); 

ich mein Karma Shim-Datei modifiziert, um das gleiche zu tun. Bei der den Tests ein zweites Mal ausgeführt wird, bekomme ich jetzt einen anderen Fehler:

404: /node_modules/@ngrx/store/dist/store.js 
Chrome 48.0.2564 (Mac OS X 10.11.3) ERROR 
    Error: XHR error (404 Not Found) loading http://localhost:9876/node_modules/@ngrx/store/dist/store.js 

Dies bedeutet, muss es den expliziten Pfad nimmt ich es in Betracht gab, aber es kann immer noch nicht das Modul finden. Es ist jedoch der korrekte Pfad zum Modul und funktioniert, wenn es in einen Browser geladen wird.

Ich bin ziemlich verloren auf was als nächstes zu tun. Kann mir jemand in die richtige Richtung zeigen?

ein paar Dinge zu beachten:

  • den Knotenmodul Karma files Array Hinzufügen keine Option ist, da seine Abhängigkeiten mit SystemJS gelöst werden müssen
  • Dies ist nur mit Knotenmodule, für die SystemJS geschieht benötigt benutzerdefinierte Anweisungen, wo sie sich befinden. Ich kann in meinen Tests ganz gut andere Module laden, ohne einen bestimmten Standort so lange SystemJS Bereitstellung ist in der Lage, es zu finden

Hier ist meine Karma Konfiguration ist:

// Set up with the help of 
// http://twofuckingdevelopers.com/2016/01/testing-angular-2-with-karma-and-jasmine/ 

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/testing.dev.js', included: true, watched: true}, 
     {pattern: 'karma-test-shim.js', included: true, watched: true}, 

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

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

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

    port: 9876, 

    logLevel: config.LOG_INFO, 

    colors: true, 

    autoWatch: true, 

    browsers: ['Chrome'], 

    // Karma plugins loaded 
    plugins: [ 
     'karma-jasmine', 
     'karma-coverage', 
     'karma-chrome-launcher' 
    ], 

    // // Coverage reporter generates the coverage 
    // reporters: ['progress', 'dots', 'coverage'], 
    // 
    // // Source files that you wanna generate coverage for. 
    // // Do not include tests or libraries (these files will be instrumented by Istanbul) 
    // preprocessors: { 
    // 'src/**/!(*spec).js': ['coverage'] 
    // }, 

    // coverageReporter: { 
    // reporters:[ 
    //  {type: 'json', subdir: '.', file: 'coverage-final.json'} 
    // ] 
    // }, 

    singleRun: true 
    }) 
}; 

Und hier ist mein Karma Shim:

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

jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000; 

// // Cancel Karma's synchronous start, 
// // we will call `__karma__.start()` later, once all the specs are loaded. 
__karma__.loaded = function() {}; 

System.config({ 
    packages: { 
    'base/src': { 
     defaultExtension: 'js', 
     format: 'register', 
     map: Object.keys(window.__karma__.files).filter(onlyAppFiles).reduce(createPathRecords, {}) 
    } 
    }, 
    // This makes it work in the browser, but not in my tests! 
    paths: { '@ngrx/store' : 'node_modules/@ngrx/store/dist/store.js' } 
}); 

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) { 
    // creates local module name mapping to global path with karma's fingerprint in path, e.g.: 
    // './vg-player/vg-player': 
    // '/base/src/vg-player/vg-player.js?f4523daf879cfb7310ef6242682ccf10b2041b3e' 
    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\/src\/(?!.*\.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/src/vg-player/vg-player.spec') 
     return System.import(moduleName); 
    }); 
} 

aktualisieren

Es ist ein Beispiel-Repository mit dem Fehler here. Sie können die spezifischen Änderungen sehen, die den Fehler here verursachen. Führen Sie $ npm install und $ npm test aus, um den Fehler zu erhalten.

+0

Ich bin vor ähnlichen Problemen, wenn sie von der Prüfung Browser. Die Wege scheinen hier das Thema zu sein. Irgendwelche Updates zu diesem Problem oder wurde Ihr Problem behoben? – Gary

+0

Noch nicht gelöst. Ich denke darüber nach, ein Kopfgeld zu eröffnen. Ich muss das beheben. – weltschmerz

+0

könntest du ein [mcve] (http://stackoverflow.com/help/mcve) als git repo hochladen? –

Antwort

7

Einschließlich @ngrx/store mit dem Rest Ihrer Bundles, würde 404 Fehler beheben

// for testing in karma.conf.js 
    files: [ 
     // paths loaded by Karma 
     {pattern: 'node_modules/@ngrx/store/dist/store.js', included: true, watched: true}, 
    ], 

Aber im Gegensatz zum Rest des Bündels, die als System-Module kompiliert werden, wird @ngrx/store kompiliert als Commonjs Modul

// 'node_modules/angular2/bundles/angular2.dev.js' 
"format register"; 
System.register("angular2/src/facade/lang", [], true, function(require, exports, module) { 
.... 

// 'node_modules/rxjs/bundles/Rx.js' 
"format register"; 
System.register("rxjs/util/root", [], true, function(require, exports, module) { 
.... 

// 'node_modules/@ngrx/store/dist/store.js' 
.... 
var Observable_1 = require('rxjs/Observable'); 
.... 

, die einen Fehler verursacht:

Uncaught ReferenceError: require is not defined

// with {pattern: '~/store.js', indluded: true} 
// context.html includes 
<script type="text/javascript" src="/base/node_modules/@ngrx/store/dist/store.js?fb5e807149603c3c2f998c98faf6826c7e301d71"></script> 

Deshalb sollten Sie sollte es nicht enthalten:

{pattern: 'node_modules/@ngrx/store/dist/store.js', included: false, watched: true} 

Dies wird im Grunde listet es in window.__karma__.files Objekt, aber wird es nicht als Skript in Karma context.html hinzufügen - Browser wird nicht geladen und führen Sie den Code, der den Fehler verursacht. Das Laden sollte von SystemJS ...

gehandhabt werden Wenn Sie Karmatests mit singleRun: false ausführen, können Sie Dateien in Chrome Devtools> Netzwerk überprüfen. Sie finden eine Liste der geladenen Dateien sehen und das ist, wo das letzte Stück des Puzzles ist:

In Ihrem karma-test-shim.js Änderung System.config.map zu:

map: { '@ngrx/store' : '/base/node_modules/@ngrx/store/dist/store.js' } 

Executed 4 of 4 SUCCESS (0.037 secs/0.008 secs)

+0

Schön. Vielen Dank. – weltschmerz

+0

Also mussten Sie nur das Muster aus den 'Dateien' entfernen und die' map' zu System.config hinzufügen? –

+0

@mithun_daa Sie müssen das Muster in 'files []' beibehalten oder die Datei wird nicht geliefert, wenn SystemJS versucht, sie zu laden. Sie müssen nur 'include: false' setzen, damit es nicht vom Browser geladen und ausgeführt wird, und das Laden dem SystemJS überlassen. – Sasxa

0

Eine PR mit dem Fix gesendet.Es könnte eine bessere Möglichkeit, dies zu tun, aber das funktioniert:

Kopieren Sie die store.js Datei in den dist Ordner durch die package.json Aktualisierung ‚s build Skript

... && cp node_modules/@ngrx/store/dist/store.js dist/store.js 

Aktualisieren Sie den Pfad in karma-test.shim.js

paths: { '@ngrx/store' : '/base/dist/store.js' } 
+2

Danke für die PR, aber das wird nicht funktionieren. Es ist im Wesentlichen das gleiche wie nur das Paket herum zu bewegen. Es wird auch nicht skalieren, wenn dies mit mehr Paketen passiert. Ich würde gerne verstehen, warum SystemJS das Modul nicht laden und eine Lösung dafür finden kann. – weltschmerz

+0

Ich habe auch Probleme mit Pfad, Karma und SystemJS. Gab es irgendeine Lösung? –

Verwandte Themen