2016-02-15 22 views
9

Sto costruendo un'app Web utilizzando Angular 2, SystemJS e Karma per i test.Carica il modulo nodo con SystemJS e Karma in Angular 2

Sto cercando di caricare il modulo del nodo ngrx/store in un test:

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... 
    }); 
}); 

Tuttavia, il mio test non con il seguente messaggio:

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 

realtà ho avuto lo stesso problema in dev pure, e si scopre che SystemJS non sapeva dove trovare @ngrx/store. Per risolvere questo, ho fatto questo:

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

Ho modificato il mio file di shma Karma per fare lo stesso. Al momento l'esecuzione dei test una seconda volta, ora ottengo un errore diverso:

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 

Ciò significa che deve essere prendendo il percorso esplicito ho dato conto, ma ancora non riesco a trovare il modulo. Tuttavia, è il percorso corretto per il modulo e funziona quando viene caricato in un browser.

Sono abbastanza perso su cosa fare dopo. Qualcuno può indicarmi la giusta direzione?

Alcune cose da notare:

  • Aggiunta del modulo nodo files matrice Karma non è un'opzione, in quanto le sue dipendenze devono essere risolti con SystemJS
  • questo accade solo con moduli nodo per cui SystemJS ha bisogno di istruzioni personalizzate su dove si trovano. Posso caricare altri moduli proprio bene nel mio test senza fornire una posizione specifica purché SystemJS è in grado di trovarlo

Ecco la mia configurazione Karma:

// 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 
    }) 
}; 

Ed ecco il mio Karma spessore:

// 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); 
    }); 
} 

Aggiornamento

C'è un repository ad esempio con l'errore here. È possibile visualizzare le modifiche specifiche che causano l'errore here. Esegui $ npm install e $ npm test per ottenere l'errore.

+0

sto affrontando problemi simili durante il test dal browser. I percorsi sembrano essere il problema qui. Eventuali aggiornamenti su questo o il tuo problema è stato risolto? – Gary

+0

Non ancora risolto. Stai pensando di aprire una taglia. Devo aggiustare questo. – weltschmerz

+0

potresti caricare un [mcve] (http://stackoverflow.com/help/mcve) come un repo git? –

risposta

7

Compreso il @ngrx/store con il resto dei pacchetti, risolverebbe l'errore 404

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

Ma a differenza del resto dei fasci che vengono compilati come moduli di sistema, @ngrx/store è compilato come commonjs modulo

// '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'); 
.... 

che causa un errore:

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> 

Ecco perché non dovrebbe includerlo:

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

Questo lo listerà fondamentalmente nell'oggetto window.__karma__.files, ma non lo aggiungerà come script in Karma context.html - il browser non caricherà ed eseguirà il codice che causa l'errore. Il caricamento deve essere gestito da SystemJS ...

Se si eseguono test di karma con singleRun: false, è possibile esaminare i file in Devtools> Network di Chrome. Vedrete c'è un elenco di file caricati ed è lì che l'ultimo pezzo del puzzle è:

Nella tua karma-test-shim.js cambiamento System.config.map a:

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

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

+0

Bello. Grazie. – weltschmerz

+0

Quindi è sufficiente rimuovere il pattern dai 'file' e aggiungere' map' a System.config? –

+0

@mithun_daa Devi mantenere lo schema in 'files []', altrimenti il ​​file non verrebbe mostrato quando SystemJS prova a caricarlo. Devi solo impostare 'include: false' in modo che non sia caricato ed eseguito dal browser e lasci il caricamento a SystemJS. – Sasxa

0

Inviato un PR con la correzione.Ci potrebbe essere un modo migliore per fare questo, ma questo funziona:

Copiare il file store.js nella cartella dist aggiornando s' il package.jsonbuild sceneggiatura

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

Aggiornare il percorso nel karma-test.shim.js

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

Grazie per il PR, ma questo non funzionerà. È essenzialmente lo stesso del semplice spostamento del pacchetto. Inoltre non si ridimensionerà se questo accade con più pacchetti. Mi piacerebbe capire perché SystemJS non può caricare il modulo e trovare una soluzione per questo. – weltschmerz

+0

Ho anche problemi con pathing, Karma e SystemJS. C'era qualche soluzione a questo? –

Problemi correlati