Getting error while using ES6 in karma - javascript

I made configuration with karma to run my test cases. I'm getting error if use any ES6 code in test file or source file. Below I'm attaching my configuratio. please help me.
module.exports = function (config) {
config.set({
browsers: ['PhantomJS'],
colors: true,
client: {
clearContext: false
},
failOnEmptyTestSuite: false,
frameworks: [
'mocha',
'chai'
],
files: [
'tests/test.js',
//{pattern: 'tests/globals.js'},
'js/**/*.js'
],
preprocessors: {
'tests/test.js': ['webpack', 'sourcemap'],
'js/**/*.js': ['webpack'],
'tests/**/*.js': ['webpack'],
},
reporters:['spec', 'coverage'],
coverageReporter: {
reporters: [
{ type: 'text' },
{ type: 'html', subdir: 'html' }
],
},
webpack: {
cache: true,
devtool: 'inline-source-map',
module: {
loaders: [
{
enforce: 'pre',
test: /.test\.js$/,
include: /tests/,
exclude: /node_modules/,
use: [{ loader: 'babel-loader' }]
},
{
enforce: 'pre',
test: /\.js$/,
include: /js/,
exclude: /node_modules/,
use: [{ loader: 'istanbul-instrumenter-loader', query: { esModules: true } }]
},
{
test: /\.js$/,
include: /js/,
exclude: /node_modules|tests/,
use: [{ loader: 'babel-loader' }]
},
],
},
},
});
};
And my test case file is
import '../js/help/help.js';
describe("CamelCase Function",()=>{
it("the given text should be a string", () =>{
var str = "satya";
testString = Utility.camelCaseConvertion(str);
expect(testString).to.be.a("string");
});
it("Should convert the first letters to Capital",()=>{
expect(Utility.camelCaseConvertion("test 123test test#123 anywhereworks any")).to.equal("Test 123test Test#123 Anywhereworks Any");
});
it("should not convet to camel case",()=>{
expect(Utility.camelCaseConvertion("#anywhereworks")).to.equal("#anywhereworks");
});
it("should convert to camel case after space",()=>{
expect(Utility.camelCaseConvertion("<h1>aw anywhere")).to.equal("<h1>aw Anywhere")
});
});
If I use any ES6 code in help.js then also it throwing error. How I can transpile my source as well as test with above configuration.

You're having Karma run your tests in PhantomJS. PhantomJS does not support much of ES6, and possibly never will since development was indefinitely suspended earlier this year.
If you want to use ES6 (things like let and arrow functions) in Phantom, you'll need to transpile your code with something like Babel. There are some Karma plugins that exist already, I believe, such as this one.

Related

Webpack: include specific file instead of package.json specified?

I have a webpack configuration:
var path = require("path");
module.exports = {
entry: {
app: [
'./src/index.js'
]
},
output: {
path: path.resolve(__dirname + '/dist'),
filename: '[name].js',
},
module: {
rules: [
{
test: /\.(css|scss)$/,
use: [
'style-loader',
'css-loader',
]
},
{
test: /\.js$/,
exclude: /node_modules/,
},
{
test: /\.html$/,
exclude: /node_modules/,
loader: 'file-loader?name=[name].[ext]',
},
{
test: /\.elm$/,
exclude: [/elm-stuff/, /node_modules/],
loader: 'elm-webpack-loader?verbose=true&warn=true',
options: {debug: true, warn: true},
},
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'url-loader?limit=10000&mimetype=application/font-woff',
},
{
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'file-loader',
},
],
noParse: /\.elm$/,
},
devServer: {
inline: true,
stats: { colors: true },
},
};
I have a few questions:
According to me the above config says that it should not be looking
for js files in node_modules. However it is still bundling
./node_modules/dexie/dist/dexie.es.js when I call require ("dexie"). (I am just doing this to experiment and understand webpack).
I would rather like to call dexie.js instead of dexie.es.js. How do
I make this happen. I know I can set the mainFields property.
However how do I do this on a prelibrary basis instead of globally.
Not sure if I understand your requirement fully, but an option is to set up aliases in the webpack resolve
module.exports = {
entry: {
...
},
output: {
...
},
module: {
rules: [
...
],
noParse: /\.elm$/,
},
resolve: {
alias: {
dixie: 'node_modules/dexie/dist/dexie.js'
}
},
devServer: {
...
},
};
To your first question please see here. It has already been answered.
No matter what you exclude in your loaders config, the file will be bundled unless you define it as external in your config.
To your second question, you can just require the other file with
require('dexie/dexie.js')
When you just write require('dexie'), webpack will look in your node_modules folder for a folder named 'dexie', read the package.json and resolve the file described by the module property. This is described here.
For more info, please read the webpack docs. They are excellent.

How to setup webpack for supporting ES6 Modules in Node

I'm using Webpack for bundle client and server code, so my webpack.config.js looks like:
module.exports = [
{ /* client config */ },
{ /* server config */ },
];
I want to write ES6 (modules) in both and transpile code to ES5 using Babel.
For client, this can be done with babel-loader:
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: [
'react',
[
'env',
{
targets: {
'browsers': 'last 2 versions',
},
},
],
],
},
}
Based on this, I wrote babel loader for server:
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: [
'react',
[
'env',
{
targets: {
'node': 'current',
},
},
],
],
},
}
Something tells me that babel-loader will never work for this purpose.
After ran webpack, bundles are right located but server entry point (server.js) aren't transpiled correctly:
SyntaxError: Unexpected token import
Generally when we want to transpile Node code, we would use babel-cli package and add a script in package.json:
"scripts": {
"build": "babel src -d dist"
}
and manually:
npm run build
My question is: How to setup ES6 transpiling with Babel for Node inside webpack.config.js?
+BONUS
webpack.config.js
const path = require('path');
const babelRcClient = {
presets: [
'react',
[
'env',
{
targets: {
'browsers': 'last 2 versions',
},
},
],
],
};
const babelRcServer = {
presets: [
'react',
[
'env',
{
targets: {
'node': 'current',
},
},
],
],
};
const babelLoaderClient = {
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: babelRcClient,
};
const babelLoaderServer = {
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: babelRcServer,
};
module.exports = [
{
context: __dirname,
entry: './shared/index.js',
output: {
path: path.resolve(__dirname, './static'),
filename: 'bundle.js',
},
module: {
loaders: [
babelLoaderClient,
],
},
plugins: [],
},
{
context: __dirname,
entry: './server/server.js',
target: 'node',
output: {
path: path.resolve(__dirname, './build'),
filename: 'server.js',
libraryTarget: 'commonjs',
},
externals: [ /^(?!\.|\/).+/i, ],
module: {
loaders: [
babelLoaderServer,
],
},
plugins: [],
},
]
By specifying
targets: {
'node': 'current',
}
you are telling babel to transpile your code to node version which you are using to transpile the code.
Are you using the same node version on production?
Try specifying numeric node version, e.g. 6.11.2 and then run transpilation.
Another thing you can do is tell babel to leave ES6 modules in ES6 way and don't replace it with commonjs approach (which is default) by setting:
targets: {
'node': ...,
},
modules: false
This thing worked for me. Try and check once.
{
test: /\.(js|jsx)$/,
include: [].concat(
path.resolve('./app') //path to your application
),
use: ['babel-loader']
}

Coverage reports with karma and a mix of javascript and typescript src files

I have a project where I use webpack for development/testing and karma as my test runner. This project has source files written half in js and half in ts/tsx. The test suite is written completely in js. I currently use karma-coverage, which shows coverage reports for all my js source files, but it does not support typescript files. All my tests run, there is no problem there, I just would like coverage reports for all my test files. Can anyone point me in the right direction?
Here is my karma.conf.js if this helps.
'use strict';
const webpackCfg = require('./webpack.config')('test');
module.exports = function karmaConfig(config) {
config.set({
browsers: ['Chrome'],
files: [
'test/loadtests.js'
],
port: 8080,
captureTimeout: 60000,
frameworks: [
'mocha',
'chai',
'sinon'
],
client: {
mocha: {}
},
singleRun: true,
reporters: ['mocha', 'coverage', 'junit'],
mochaReporter: {
output: 'autowatch'
},
preprocessors: {
'test/loadtests.js': ['webpack', 'sourcemap']
},
webpack: webpackCfg,
webpackServer: {
noInfo: true
},
junitReporter: {
outputDir: 'coverage',
outputFile: 'junit-result.xml',
useBrowserName: false
},
coverageReporter: {
dir: 'coverage/',
watermarks: {
statements: [70, 80],
functions: [70, 80],
branches: [70, 80],
lines: [70, 80]
},
reporters: [
{ type: 'text' },
{
type: 'html',
subdir: 'html'
},
{
type: 'cobertura',
subdir: 'cobertura'
},
{
type: 'lcovonly',
subdir: 'lcov'
}
]
}
});
};
And the relevant part of my webpack test config
{
devtool: 'inline-source-map',
externals: {
cheerio: 'window',
'react/lib/ExecutionEnvironment': true,
'react/addons': true,
'react/lib/ReactContext': true,
},
module: {
preLoaders: [
{
test: /\.(js|jsx)$/,
loader: 'isparta-loader',
include: [
this.srcPathAbsolute
]
}
],
loaders: [
{
test: /\.cssmodule\.css$/,
loaders: [
'style',
'css?modules&importLoaders=1&localIdentName=[name]-[local]-[hash:base64:5]'
]
},
{
test: /^.((?!cssmodule).)*\.css$/,
loader: 'null-loader'
},
{
test: /\.(sass|scss|less|styl|png|jpg|gif|mp4|ogg|svg|woff|woff2)$/,
loader: 'null-loader'
},
{
test: /\.json$/,
loader: 'json'
},
{
test: /\.ts(x?)$/,
exclude: /node_modules/,
loader: ['babel', 'ts-loader']
},
{
test: /\.(js|jsx)$/,
loader: 'babel-loader',
query: {
presets: ['airbnb']
},
include: [].concat(
this.includedPackages,
[
this.srcPathAbsolute,
this.testPathAbsolute
]
)
}
]
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': '"test"'
})
]
}
After a couple days of soul and google searching amongst hundreds of browser tabs, I have found a working solution. This is using TypeScript 2.x and Webpack 2.x. test.js is my entry point. It could just as easily be test.ts (and it will be eventually). In that entry point, I load my *.spec.js and *.spec.ts files. And then those files import whichever source they need to test from. I have put all the webpack config in the karma.conf.js so it's easier to see:
let myArgs = require('yargs').argv;
let path = require('path');
let webpack = require('webpack');
module.exports = function(config) {
const REPORTS_PATH = myArgs.reportsPath ? myArgs.reportsPath :path.join(__dirname, 'build');
config.set({
basePath: '',
frameworks: ['jasmine', 'es6-shim'],
files: [
'./test.js'
],
exclude: [],
reporters: ['progress', 'spec', 'coverage', 'junit', 'coverage-istanbul'],
preprocessors: {
'./test.js': ['webpack', 'sourcemap']
},
webpackServer: {
noInfo: true // prevent console spamming when running in Karma!
},
webpack: {
devtool: 'inline-source-map',
resolve: {
modules: [
path.resolve('./node_modules'),
path.resolve('./')
],
extensions: ['.js', '.ts', '.css', '.scss']
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery"
})
],
module: {
rules: [
{
enforce: 'pre',
test: /\.js$/,
use: 'source-map-loader',
exclude: [/node_modules/]
},
{
test: /\.ts$/,
use: [{
loader: 'awesome-typescript-loader',
options: {
module: 'commonjs'
},
}]
},
{
test: /\.js$/,
use: [{
loader: 'awesome-typescript-loader',
options: {
entryFileIsJs: true,
transpileOnly: true
}
}],
exclude: [/node_modules/],
},
{
enforce: 'post',
test: /\.(js|ts)$/,
use: [{
loader: 'istanbul-instrumenter-loader',
options: {
esModules: true
}
}],
exclude: [/node_modules/, /\.spec\.(js|ts)$/, /test/]
},
{ test: /\.html/, use: 'raw-loader' },
{ test: /\.(s)?css$/, use: 'null-loader' },
{ test: /\.(png|jpg|jpeg|gif|svg|pdf)$/, use: 'null-loader' },
{ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, use: 'null-loader' },
{ test: /\.(ttf|eot)(\?v=[0-9]\.[0-9]\.[0-9])?$/, use: 'null-loader' },
{ test: /\.json$/, use: 'null-loader' }
]
}
},
coverageReporter: {
type: 'in-memory'
},
coverageIstanbulReporter: {
//TODO: Figure out why the 'html' reporter blows up with istanbul-reports (something with absolute path copying files)
reports: ['text-summary', 'cobertura'],
// base output directory
dir: REPORTS_PATH,
fixWebpackSourcePaths: true,
'report-config': {
cobertura: {
file: 'coverage.xml'
},
'text-summary': {
file: null
}
}
},
junitReporter: {
outputDir: `${REPORTS_PATH}/junit/`,
outputFile: 'jasmine-results.xml'
},
// Hide webpack build information from output
webpackMiddleware: {
stats: {
chunkModules: false,
colors: true
},
noInfo: 'errors-only'
},
colors: true,
logLevel: config.LOG_ERROR,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
autoWatchBatchDelay: 400
});
};
So, the key pieces here are awesome-typescript-loader, karma-coverage-istanbul-reporter, source-map-loader, and in the tsconfig.json, you want to set these in compilerOptions:
"inlineSourceMap": true,
"sourceMap": false,
I indicated a TODO about the html report. It DOES work but I couldn't get it to output to a custom directory (subdir) with TypeScript files as a part of it. JavaScript only worked fine. Could be a windows-specific problem with istanbul-reports. If you add html to the reports array under coverageIstanbulReporter, you should see it in your project dir but may have problems putting it in REPORTS_PATH.
It's also worth noting that I had a lot of luck using karma-remap-coverage instead of karma-coverage-istanbul-reporter but the former would not correctly generate cobertura reports for coverage which is what I needed for Jenkins.

fetch-mock Response Does Not Have JSON Method

I'm trying to get fetch-mock to work in my testing setup, but the response object looks different than expected.
Specifically, it does not have a json method.
Here's the class I'm calling with the actual call to fetch:
import 'whatwg-fetch';
export class Store {
load() {
return fetch("/api", {
method: "get",
headers: {'Content-Type': 'application/json'}
});
}
}
Here is a snippet from the test code:
import fetchMock from 'fetch-mock';
fetchMock.get("*", {code: "1", name: "cde", image: 'hello.jpeg'})
this.store = new Store;
this.store.load().then(response => console.log(response._bodyInit()));
console.log('hello', this.brandStore.brands[0]);
fetchMock.restore();
The console will print:
Response{
type: 'default',
status: 200,
ok: true,
statusText: 'OK',
headers: Headers{map: Object{content-type: ...}},
url: '/api',
_bodyInit: '{"code":"1","name":"cde","image":"hello.jpeg"}',
_bodyText: '{"code":"1","name":"cde","image":"hello.jpeg"}'
}
This error also gets output:
'Unhandled promise rejection', TypeError{line: 4005, sourceURL: 'http://localhost:9876/base/test/stores/BrandStore.spec.js?572679e0c28b63839a5f5829ef1a60b8d62f8b84', stack: 'http://localhost:9876/base/test/stores/BrandStore.spec.js?572679e0c28b63839a5f5829ef1a60b8d62f8b84:4005:168
run#http://localhost:9876/base/node_modules/babel-polyfill/dist/polyfill.js?00cf5c53ec5ebd52d0521aed551c593eef05a0d6:3911:29
http://localhost:9876/base/node_modules/babel-polyfill/dist/polyfill.js?00cf5c53ec5ebd52d0521aed551c593eef05a0d6:3924:31
flush#http://localhost:9876/base/node_modules/babel-polyfill/dist/polyfill.js?00cf5c53ec5ebd52d0521aed551c593eef05a0d6:1209:11'}
My Karma (with Webpack config) looks like:
const webpack = require('webpack');
var argv = require('yargs').argv;
var path = require('path');
let srcPath = path.join(__dirname, '/../src/');
const webpackConfig = {
devtool: 'inline-source-map',
resolve: {
// allow us to import components in tests like:
// import Example from 'components/Example';
root: path.resolve(__dirname, './src'),
// allow us to avoid including extension name
extensions: ['', '.js', '.jsx', '.css', '.scss', '.json'],
// required for enzyme to work properly
alias: {
'sinon': 'sinon/pkg/sinon',
}
},
module: {
// don't run babel-loader through the sinon module
noParse: [
/node_modules\/sinon\//
],
isparta: {
embedSource: true,
noAutoWrap: true,
// these babel options will be passed only to isparta and not to babel-loader
babel: {
presets: ['es2015', 'stage-0', 'react']
}
},
// run babel loader for our tests
loaders: [
{
test: /\.(js|jsx)$/,
loader: 'babel',
exclude: path.resolve(__dirname, 'node_modules'),
query: {
plugins: ['transform-decorators-legacy'],
presets: ['es2015', 'airbnb', 'stage-1', 'react']
}
},
{
test: /\.json$/, loader: 'json'
},
{
test: /\.scss$/,
exclude: /[\/\\](node_modules|bower_components|public)[\/\\]/,
loaders: [
'style?sourceMap',
'css?modules&importLoaders=1&localIdentName=[local]',
'postcss',
'sass'
]
},
{
test: /\.css$/,
exclude: /[\/\\](node_modules|bower_components|public)[\/\\]/,
loaders: [
'style?sourceMap',
'css?modules&importLoaders=1&localIdentName=[local]'
]
}
],
preLoaders: [ { //delays coverage til after tests are run, fixing transpiled source coverage error
test: /\.(jsx|js)$/,
include: path.resolve('src/'),
loader: 'isparta',
} ]
},
plugins: [
new webpack.IgnorePlugin(/node-fetch/)
],
// required for enzyme to work properly
externals: {
'jsdom': 'window',
'react/lib/ExecutionEnvironment': true,
'react/lib/ReactContext': 'window',
'react/addons': true
},
};
module.exports = function(config) {
config.set({
browsers: ['PhantomJS'],
singleRun: !argv.watch,
frameworks: ['mocha', 'chai'],
reporters: ['spec', 'coverage'],
// include some polyfills for babel and phantomjs
files: [
'node_modules/whatwg-fetch/fetch.js',
'node_modules/babel-polyfill/dist/polyfill.js',
'./node_modules/phantomjs-polyfill/bind-polyfill.js',
'test/**/*.js'
],
preprocessors: {
// add webpack as preprocessor
'src/**/*.js': ['webpack', 'sourcemap'],
'test/**/*.js': ['webpack', 'sourcemap']
},
// A lot of people will reuse the same webpack config that they use
// in development for karma but remove any production plugins like UglifyJS etc.
// I chose to just re-write the config so readers can see what it needs to have
webpack: webpackConfig,
webpackMiddleware: {
noInfo: true
},
coverageReporter: {
dir: 'coverage/',
reporters: [
{ type: 'html' },
{ type: 'text' }
]
},
// tell karma all the plugins we're going to be using to prevent warnings
plugins: [
'karma-mocha',
'karma-chai',
'karma-webpack',
'karma-phantomjs-launcher',
'karma-spec-reporter',
'karma-sourcemap-loader',
'karma-coverage'
]
});
};

How Can I Exclude Spec Files from Code Coverage with Karma using Webpack and Babel?

Problem
I'm working on a small react-redux project configured with webpack, babel, and karma. I added code coverage to karma, but I couldn't find a way to exclude the test files from coverage. So my code coverage has spec files.
How can I exclude these spec files from coverage?
I tried to use a regex expression to exclude the spec files, but since it was being loaded by webpack, it didn't work.
tests.webpack.js
const context = require.context('./src', true, /.+\Spec\.js$/);
context.keys().forEach(context);
module.exports = context;
webpack.config.js
module.exports = {
entry: './src/index.js',
output: {
path: __dirname,
filename: 'dist/bundle.js'
},
devtool: 'source-map',
resolve: {
extensions: ['', '.js', '.scss'],
modulesDirectories: [
'node_modules',
'src'
]
},
module: {
preLoaders: [
{
test: /\.js$/,
loader: 'eslint-loader',
exclude: /node_modules/
}
],
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
],
},
};
karma.config.js
var path = require('path');
module.exports = function (config) {
config.set({
browsers: ['PhantomJS'],
singleRun: true,
frameworks: ['mocha', 'sinon-chai'],
files: [
'tests.webpack.js'
],
preprocessors: {
'tests.webpack.js': ['webpack', 'sourcemap']
},
reporters: ['mocha', 'osx', 'coverage'],
webpack: {
module: {
preLoaders: [
{
test: /\.js$/,
exclude: [
path.resolve('src/'),
path.resolve('node_modules/')
],
loader: 'babel'
},
{
test: /\.js$/,
include: path.resolve('src/'),
loader: 'isparta'
}
]
}
},
webpackServer: {
noInfo: true
},
coverageReporter: {
type: 'html',
dir: 'coverage/'
}
});
};
This is how I do it on my project, where I have all my tests in __test__ folders included with each component. You should be able to change this to a regex something like this /\.spec.js$/.
karmaConfig.webpack.module.preLoaders = [{
test : /\.(js|jsx)$/,
include : new RegExp(config.dir_client),
loader : 'isparta',
exclude : [
/node_modules/,
/__test__/,
],
}];
In your case you need to add exclude to this bit of your config.
{
test: /\.js$/,
include: path.resolve('src/'),
loader: 'isparta'
}
I solved this by filtering out the results I didn't want by placing a .filter() before the .forEach(context).
const includes = require('lodash/includes');
const context = require.context('./src', true, /\.test\.js$/);
context.keys()
.filter(file => includes(file, './api/') === false)
.forEach(context);
You could also write it directly into the .forEach().
const includes = require('lodash/includes');
const context = require.context('./src', true, /\.test\.js$/);
context.keys()
.forEach(file => {
if (includes(file, './api/') === false) {
context(file);
}
});
If you don't use Lodash, you can use:
file.indexOf('./api/') === -1

Categories

Resources