How to test ajax calls with webpack - javascript

I'm using webpack to build lib written in EcmaScript6. It triggers ajax calls so I need to check if everything is working as expected in tests. I'm using karma + mocha setup. I tried to lift express server for testing and to use tools like fetchmock, mocked-backend, nock. Each of them throws error when I try to require it. I've expected error with express, cause it's designed to work on backend, but the rest should work in the browser.
So I wonder if I'm doing something wrong or this libs isn't compatible with webpack. What's the best way to test ajax with karma and webpack.
My karma.conf.js:
module.exports = function (config) {
config.set({
basePath: '',
files: [
'test/main/*.test.js'
],
frameworks: ['mocha'],
preprocessors: {
'test/main/*.test.js': ['webpack']
},
reporters: ['mocha'],
webpack: {
debug: true,
module: {
loaders: [{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader?experimental'
}]
}
},
webpackMiddleware: {
stats: false
},
autoWatch: true,
browsers: ['PhantomJS']
});
};

Related

Show correct stacktrace in karma tests

Prerequisites
Typescript
Karma / Jasmine
Webpack
Application
I have simple TypeScript application. Also set of *.ts tests and karma framework to run this tests. Transpiling with Webpack.
Here is part of karma configuration:
...
basePath: '',
frameworks: ['jasmine','sinon'],
files: [
'src/test/spec/**/*.ts'
],
preprocessors: {
'src/**/*.ts': ['webpack', 'sourcemap']
},
webpack: {
debug: true,
devtool: 'inline-source-map',
module: webpackConfig.module,
resolve: webpackConfig.resolve
},
webpackMiddleware: {
quiet: true,
stats: {
colors: true
}
}
...
And webpack configuration
...
resolve: {
extensions: ['.ts', '.js', '.tsx', '.jsx', '']
},
module: {
loaders: [{
test: /\.tsx?$/,
exclude: /node_modules/,
loader: 'ts-loader'
}
]
}
...
Everything works fine, tests are written using TypeScript, PhantomJS is used as headless browser. It works.
Problem
But I experiencing problems with investigating failed tests, because stack trace written to console is incorrect - it always points to the test source file even problem occurred in other place(s).
As an example - I'm sharing my console output after karma launcher
TypeError: 'undefined' is not a constructor (evaluating 'new vRef(this)')
at src/test/spec/validations/required.ts:1764
at DataBase (src/test/spec/validations/required.ts:1690)
at src/test/spec/validations/required.ts:50
at http://localhost:9880/context.js:151
where 'src/test/spec/validations/required.ts' - it's my test file, but stacktrace truly goes through 3 different files.
How to fix output data to point correctly to failed place? Would be very appreciated if anyone can share with me my config or setup problems.

Sourcemap + istanbul/isparta code coverage for a webpack + babel (for es6) + mocha (+karma)

I have a test project at https://github.com/danielbush/webpack-babel-karma-sourcemap-coverage.
It consists of two simple source files in src/, one with a deliberate error (src/lib2.js).
I want to webpack and transpile using babel from ES6 to ES5 and run the Mocha tests on this bundle using Karma.
I've already added source mapping and tested this so that I can see the line number of the original file.
For me, the stack trace looks like this:
21 02 2016 16:03:15.445:INFO [karma]: Karma v0.13.21 server started at http://localhost:9876/
21 02 2016 16:03:15.451:INFO [launcher]: Starting browser Chrome
21 02 2016 16:03:16.551:INFO [Chrome 48.0.2564 (Linux 0.0.0)]: Connected on socket /#yRS32ons0_2HGhrwAAAA with id 3072946
START:
lib1
✖ should return 1
Finished in 0.015 secs / 0.001 secs
SUMMARY:
✔ 0 tests completed
✖ 1 test failed
FAILED TESTS:
lib1
✖ should return 1
Chrome 48.0.2564 (Linux 0.0.0)
Error: SIMULATED ERROR
at foo (/home/danb/projects/so-test-project/tests.webpack.js:135:10 <- webpack:///src/lib2.js:13:8)
at Context.<anonymous> (/home/danb/projects/so-test-project/tests.webpack.js:93:31 <- webpack:///test/index.js:7:11)
On the 2nd last line above, it shows webpack:///src/lib2.js:13 which is the correct location in the original source.
To get that mapping, I did this: https://github.com/danielbush/webpack-babel-karma-sourcemap-coverage/commit/6ea992cae499dccc68488bcb3eaca642ae4ed24e
What I want to do is add coverage using something like istanbul (or isparta which uses istanbul) so that I can generate an HTML coverage report in coverage/ that shows me lines that aren't covered (potentially) -- as well as overall coverage percentages.
But I want to ensure that my stack traces are still source mapped correctly like the above.
I've tried isparta-loader and isparta-instrumenter-loader to transpile and instrument the files in question in webpack, but my line numbers are slightly wrong in the stacktrace (above). There seems to be a number of isparta-like things floating around and the documentation is not super-friendly.
To express all of this a bit more generally: I'm bundling files and tests and then testing this in the browser (karma or by more manual means), and I want my source maps (in the browser) to point to the original lines of code and at the same time I want a coverage report to refer to the original lines and files that haven't been covered.
I don't have a solution for a single karma/webpack configuration. My workaround is to have 2 karma confs - which I'm quite happy with atm. (I have other non-karma setups for running tests as well.)
One conf runs the tests in the background with accurate stack traces for my es6 code, and the other runs coverage using isparta-loader to transpile and instrument my source code. (isparta-loader uses isparta, which uses istanbul).
So my "running tests" karma conf looks a bit like this:
var webpack = require('webpack');
module.exports = function (config) {
config.set({
browsers: [ 'PhantomJS' ],
singleRun: false,
frameworks: [ 'mocha' ], // Use the mocha test framework
files: [
'tests.webpack.js'
],
preprocessors: {
'tests.webpack.js': [ 'webpack', 'sourcemap' ]
},
reporters: [ 'mocha' ],
webpack: {
devtool: 'inline-source-map',
module: {
loaders: [
// Use imports loader to hack webpacking sinon.
// https://github.com/webpack/webpack/issues/177
{
test: /sinon\.js/,
loader: "imports?define=>false,require=>false"
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: { presets: ['es2015'] }
}
]
}
},
webpackServer: {
noInfo: true
}
});
}
and my coverage karma conf looks a bit like this:
var webpack = require('webpack'),
path = require('path');
module.exports = function (config) {
config.set({
browsers: [ 'PhantomJS' ],
singleRun: true,
frameworks: [ 'mocha' ],
files: [
'tests.webpack.js'
],
preprocessors: {
'tests.webpack.js': [ 'webpack' ]
},
reporters: [ 'coverage' ],
webpack: {
// *optional* babel options: isparta will use it as well as babel-loader
babel: {
presets: ['es2015']
},
// *optional* isparta options: istanbul behind isparta will use it
isparta: {
embedSource: true,
noAutoWrap: true,
// these babel options will be passed only to isparta and not to babel-loader
babel: {
presets: ['es2015']
}
},
module: {
loaders: [
{
test: /sinon\.js/,
loader: "imports?define=>false,require=>false"
},
// Perform babel transpiling on all non-source, test files.
{
test: /\.js$/,
exclude: [
path.resolve('node_modules/'),
path.resolve('lib/')
],
loader: 'babel-loader',
query: { presets: ['es2015'] }
},
// Instrument source files with isparta-loader (will perform babel transpiling).
{
test: /\.js$/,
include: [
path.resolve('lib/')
],
loader: 'isparta'
}
]
}
},
webpackServer: {
noInfo: true
},
coverageReporter: {
reporters: [
{ type: 'html', dir: 'coverage/' },
{ type: 'text' }
]
}
});
}
This 2nd conf provides a text report that gives immediate coverage summary in the terminal, and the html report which gives nice source file highlighting of untested code. (There's a hack in both for sinon, which isn't related to this issue.) tests.webpack.js uses webpack's require.context to pull in my browser tests written in mocha. And various karma-* plugins are required.
You may have better luck using Istanbul's new official Babel Plugin to instrument your sources for code coverage.
In my experience, compared to isparta, it provided more accurate coverage reports and required basically no configuration apart from adding it to the list of plugins in my Babel configuration.
Sourcemaps appeared to work correctly "out of the box" when I used it on my project.

Karma, webpack, emblem-loader compiled is not defined

We use coffee-script and emblem for templates in project. Webpack is used for bundling and Karma to run tests. I've tried to use emblem-loader for emblem processing with webpack. Here is the repository I created with simple example how to reproduce it.
karma webpack config (coffee-script):
webpack:
module:
loaders: [
{ test: /\.coffee$/, loader: "coffee-loader" },
{ test: /\.emblem$/, loader: "emblem-loader"}
],
resolve:
extensions: ["", ".emblem"]
webpackMiddleware:
noInfo: true
Template is imported via emblemTemplate = require 'template_path.emblem', then trying to do emblemTemplate(context).
Resulting Errors:
in PhantomJS: Can't find variable: compiled
in Chrome: ReferenceError: compiled is not defined
Definitely the problem is with processing the template and not template itself for loader returns function that check if (!compiled) {...}.

Karma/systemjs not looking in node_modules directory when trying to run tests

I'm trying to run tests using karma/jasmine/systemjs with Angular 2 and typescript. I previously had it working without systemjs/typescript using babel.
I also got it working transpiling typescript to es6 and using the same karma setup without using systemjs.
I want to use systemjs, and I don't want to have to do transpile twice, so now I'm trying to use systemjs with karma. (using karma-system.js).
The error I'm getting is:
Error: XHR error (404 Not Found) loading /path/to/project/angular2/core.js
For whatever reason, karma/systemjs is not looking in the node_modules directory for angular, and I don't want to hard code that into my project files.
karma.conf.js:
module.exports = function(config) {
config.set({
basePath: '',
plugins: ['karma-systemjs', 'karma-jasmine', 'karma-chrome-launcher'],
frameworks: ['systemjs', 'jasmine'],
files: [
'client/**/*.spec.js',
'client/**/**/*.spec.js',
'server/**/*.spec.js',
'server/**/**/*.spec.js'
],
exclude: [
'node_modules/',
'client/node_modules/*',
'client/node_modules/**/*.spec.js',
'server/node_modules/*'
],
preprocessors: {},
systemjs: {
configFile: 'system.conf.js',
serveFiles: [
'client/**/*.js',
'server/**/*.js',
],
config: {
defaultJSExtensions: true
}
},
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_DEBUG,
autoWatch: false,
browsers: ['Chrome'],
singleRun: false,
concurrency: Infinity
})
}
system.conf.js
System.config({
paths: {
'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'
}
});
In my typescript file, I'm loading angular core like this.
import { Component, View } from 'angular2/core';
and it gets transpiled to:
System.register(['angular2/core'], function(exports_1) {
I have tried adding a baseUrl to my systemjs config, it does not seem to do anything.
I have been "googling" and searching stack for a few hours now. I've looked at How to configure karma and systemjs to run tests for angular ES6 transpiled by traceur into amd format ES5 modules and Angular and ES6: Karma Testing with SystemJS and still have not fixed the issue.
in your system.conf.js file you should define a path for all angular modules like this:
System.config({
paths: {
'angular2/*': 'node_modules/angular2/bundles/*.js',
}
});

How do I make Webpack exit with an error when jshint emits warnings?

Using jshint-loader with Webpack, how do I make the webpack command fail when JSHint emits warnings?
The context being that I wish to fail the CI build if linting detects issues.
Currently, I've simply configured Webpack to run jshint-loader on preload of JS files:
// webpack.config.js
module.exports = {
module: {
preLoaders: [
{
test: /\.js/,
exclude: /node_modules/,
loader: 'jshint-loader',
},
],
},
};
First, jshint-loader must be configured to fail in case issues are found (failOnHint: true), optionally one can also choose to emit warnings as Webpack errors (emitErrors: true).
// webpack.config.js
module.exports = {
module: {
preLoaders: [
{
test: /\.js/,
exclude: /node_modules/,
loader: 'jshint-loader',
},
],
},
jshint: {
emitErrors: true,
failOnHint: true,
},
};
Second, Webpack must be told to fail hard, by supplying the --bail option: webpack --bail.
Update:
webpack --bail still doesn't emit a non-zero exit code, argh.

Categories