Karma plugin for using SystemJS as a module loader.
karma-systemjs
works by loading files with System.import()
instead of including them with <script/>
, as Karma normally does.
Install from npm, along with systemjs
, es6-module-loader
, and your transpiler:
npm install karma-systemjs systemjs es6-module-loader systemjs-plugin-babel
Make sure all your dependencies, including SystemJS itself, are specified in your SystemJS config.
This is so karma-systemjs can add them to the list of files that karma serves.
// system.conf.js
System.config({
paths: {
'plugin-babel': 'node_modules/systemjs-plugin-babel/plugin-babel.js',
'systemjs-babel-build': 'node_modules/systemjs-plugin-babel/systemjs-babel-browser.js',
'systemjs': 'node_modules/systemjs/dist/system.js',
'system-polyfills': 'node_modules/systemjs/dist/system-polyfills.js',
'es6-module-loader': 'node_modules/es6-module-loader/dist/es6-module-loader.js'
}
});
Dependencies can be specified under paths
or map
.
// system.conf.js
System.config({
map: {
'plugin-babel': 'node_modules/systemjs-plugin-babel/plugin-babel.js',
'systemjs-babel-build': 'node_modules/systemjs-plugin-babel/systemjs-babel-browser.js',
'system-polyfills': 'node_modules/systemjs/dist/system-polyfills.js',
'es6-module-loader': 'node_modules/es6-module-loader/dist/es6-module-loader.js'
}
});
Add karma-systemjs
to your list of plugins:
plugins: ['karma-systemjs', ...]
Add systemjs
to your list of frameworks, (NB. must be included as first framework in list):
frameworks: ['systemjs', ...]
Add SystemJS configuration:
// karma.conf.js
systemjs: {
// Path to your SystemJS configuration file
configFile: 'app/system.conf.js',
// Patterns for files that you want Karma to make available, but not loaded until a module requests them. eg. Third-party libraries.
serveFiles: [
'lib/**/*.js'
],
// SystemJS configuration specifically for tests, added after your config file.
// Good for adding test libraries and mock modules
config: {
paths: {
'angular-mocks': 'bower_components/angular-mocks/angular-mocks.js'
}
}
}
karma-systemjs defaults to using Traceur as transpiler.
You can specify another transpiler (eg. plugin-babel
or plugin-typescript
) by adding it to your SystemJS config:
System.config({
transpiler: 'plugin-babel'
})
The transpiler can also be omitted by setting transpiler
to null
.
karma-systemjs looks up the paths for es6-module-loader
, systemjs
, and your transpiler (plugin-babel
, traceur
, or plugin-typescript
)
in the paths
or map
object of your SystemJS configuration.
systemjs: {
config: {
paths: {
'es6-module-loader': 'bower_components/es6-module-loader/dist/es6-module-loader.js'
}
}
}
SystemJS bundles are excluded by default, they can be included by setting the useBundles
flag of the systemjs configuration object.
System.config({
useBundles: 'true'
})
PhantomJS v1.x doesn't provide the Function.prototype.bind
method, which is used by some transpilers.
The best solution is to install phantomjs-polyfill
and include it in your SystemJS config.
npm install phantomjs-polyfill
System.config({
paths: {
'phantomjs-polyfill': 'node_modules/phantomjs-polyfill/bind-polyfill.js'
}
});
Absolutely, but you'll need to configure karma-coverage
to use an instrumenter which supports ES6.
preprocessors: {
'src/!(*spec).js': ['coverage']
},
coverageReporter: {
instrumenters: { isparta : require('isparta') },
instrumenter: {
'**/*.js': 'isparta'
}
}
karma-systemjs
hijacks every pattern added to files
with {included: true}
, which may include changes applied by other plugins - such as karma-chai
.
The solution is to make sure systemjs
is the first item in your frameworks
list, so it won't affect the other frameworks.
frameworks: ['systemjs', 'chai']
This appears to be a quirk in minimatch
, the glob engine used by both karma
and karma-systemjs
.
The problem is that the second /
is treated as a static part of the pattern. So the shortest path it will match is src//Spec.js
.
Simplest solution is to double up your patterns - one for the folder, and another for the subfolder.
['src/*Spec.js', 'src/**/*Spec.js']
You can add patterns for these files to systemjs.includeFiles
.
Any patterns in this array will be kept at the start of the files
list (ie. Before SystemJS and everything else) as is.
The initial modules are loaded using Promise.all([System.import(), ...])
, which means it's possible for one module to be imported and run before a previous module was run.
This can cause problems if you depend upon this ordering for global modules. eg. angular
must be loaded before angular-mocks
.
I recommend only importing test suites, not libraries. Libraries should be imported inside your test suites using import
or require()
statements that would maintain the sequence.
Otherwise you can use systemjs.includeFiles
in your Karma config to include globals before any of your tests run.
Alternatively you can set systemjs.strictImportSequence
to true, which will chain the System.import()
promises together to preserve their sequence.
Here's a few hints for speeding up your test runs:
- Make sure you're only watching files that you care about.
Instead of specifying just a pattern string, use an object (Karma doco):
{serveFiles: [{pattern: 'node_modules/**/*.js', watched: false}]}
- Make sure you're only preprocessing files that you care about.
eg. If you're usingkarma-coverage
, you'll only want coverage on source code - not node_modules or tests:
{ preprocessors: {'src/!(*spec).js': ['coverage']} }
- angular-seed
- angular-phonecat
- aurelia-typescript-tests: A great example of using Typescript
- v0.13.0: Transpiler is only served, not included, forcing SystemJS to load them.
- v0.12.0:
phantomjs-polyfill
is only included if found in SystemJS config. - v0.11.0:
es6-module-loader
andsystem-polyfills
are only included if found in SystemJS config. - v0.10.0: Changed
require.resolve()
static path for babel'sbrowser.js
- v0.9.0: Arrays in SystemJS config file are overwritten by arrays in karma config, rather than merged. Discussion
- v0.8.0: MAJOR CHANGE!
System.import()
is now used to load every file which would normally be{included: true}
by Karma, withoutkarma-systemjs
. - v0.7.0: Takes over setting
baseURL
to handle SystemJS v0.18.0 restrictions - v0.6.0: Deprecated looking up modules in
node_modules/
usingrequire.resolve()
- v0.5.0: Updated to work with SystemJS v0.17.1, which comes with it's own breaking changes.
- v0.4.0: Looks for babel's browser.js under
babel-core
instead ofbabel
fromrequire.resolve()
.
Better off settingpaths.babel
in your SystemJS config.