I have a more-or-less vanilla Laravel + Vue.js app and I am trying to do some JS testing with Karma and Jasmine. If I try to use () => {}
style functions or keywords like const
in my tests, they fail with Unexpected token errors, however, I do not have a problem using the import
keyword and I am able to transpile and work with .vue
files without issue.
A trivial assertion like
expect(true).toBe(true);
Seems to work fine (see last line)
$ ./node_modules/karma/bin/karma start
22 11 2016 11:09:23.250:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/
22 11 2016 11:09:23.254:INFO [launcher]: Launching browser PhantomJS with unlimited concurrency
22 11 2016 11:09:23.263:INFO [launcher]: Starting browser PhantomJS
22 11 2016 11:09:24.025:INFO [PhantomJS 2.1.1 (Mac OS X 0.0.0)]: Connected on socket /#U1dCZ7i3UtsC-M3_AAAA with id 84458811
PhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 1 of 1 SUCCESS (0.004 secs / 0.002 secs)
Then, if I add a trivial const
declaration to my test function
const myVar = 1
expect(true).toBe(true);
I get an error:
$ ./node_modules/karma/bin/karma start
22 11 2016 11:10:00.741:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/
22 11 2016 11:10:00.745:INFO [launcher]: Launching browser PhantomJS with unlimited concurrency
22 11 2016 11:10:00.752:INFO [launcher]: Starting browser PhantomJS
22 11 2016 11:10:01.659:INFO [PhantomJS 2.1.1 (Mac OS X 0.0.0)]: Connected on socket /#Gwh8ywcLStrKf-ljAAAA with id 78654911
PhantomJS 2.1.1 (Mac OS X 0.0.0) ERROR
SyntaxError: Unexpected token 'const'
at tests/unit/Example.spec.js:165
Instead, if I try to cause a syntax error
const = 1 // syntax error
expect(true).toBe(true);
then Babel complains (on the first line, before Karma or PhantomJS boots up)
22 11 2016 11:07:00.079:ERROR [preprocessor.babel]: /Users/crcarter/Software/CropPlanning/cps-php/resources/assets/js/tests/unit/Example.spec.js: Unexpected token (8:15)
at /Users/crcarter/Software/CropPlanning/cps-php/resources/assets/js/tests/unit/Example.spec.js
22 11 2016 11:07:00.090:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/
22 11 2016 11:07:00.091:INFO [launcher]: Launching browser PhantomJS with unlimited concurrency
22 11 2016 11:07:00.101:INFO [launcher]: Starting browser PhantomJS
22 11 2016 11:07:00.986:INFO [PhantomJS 2.1.1 (Mac OS X 0.0.0)]: Connected on socket /#9Y6QLVxtJ57qRrgDAAAA with id 56249014
PhantomJS 2.1.1 (Mac OS X 0.0.0) ERROR
You need to include some adapter that implements __karma__.start method!
This seems to imply that the Example.spec.js
file is being parsed/transpiled by Babel, but that the transpiled version is not being delivered to the browser properly, even though the Example.vue
file seems to be delivered properly.
What can I do to be able to get things like const
and () => {}
to work in my tests? Thank you.
Here are the relevant files:
resources/assets/js/components/Example.vue
resources/assets/js/tests/unit/Example.spec.js
karma.conf.js
package.json
// Example.vue
<template>
<div class="container">
</div>
</template>
<script>
export default {
mounted() {
console.log('Component ready.')
},
data() {
return { input: '# Hello!' }
}
}
</script>
// Example.spec.js
import Example from '../../components/Example.vue';
describe('Example', function () {
it('should set correct default data', function () {
const myVar = 1
// trivial assertions
expect(true).toBe(true);
});
});
// karma.conf.js
var path = require('path')
var basePath = './resources/assets/js/';
module.exports = function(config) {
config.set({
frameworks: ['jasmine'],
port: 9876,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['PhantomJS'],
singleRun: true,
basePath: basePath,
webpack: {
resolve: {
extensions: ['', '.js', '.vue'],
fallback: [path.join(__dirname, 'node_modules')],
},
resolveLoader: {
fallback: [path.join(__dirname, 'node_modules')]
},
module: {
loaders: [
{ test: /\.vue$/, loader: 'vue' },
{ test: /\.js$/, loader: 'babel',
include: basePath,
}
]
}
},
webpackMiddleware: {
noInfo: true,
stats: 'errors-only'
},
files: [
{ pattern: 'tests/**/*.spec.js', watched: false },
],
exclude: [],
preprocessors: {
'app.js': ['webpack', 'babel'],
'tests/**/*.spec.js': [ 'babel', 'webpack' ]
},
})
}
And package.json
{
"private": true,
"scripts": {
"prod": "gulp --production",
"dev": "gulp watch"
},
"devDependencies": {
"bootstrap-sass": "^3.3.7",
"gulp": "^3.9.1",
"jquery": "^3.1.0",
"laravel-elixir": "^6.0.0-11",
"laravel-elixir-vue-2": "^0.2.0",
"laravel-elixir-webpack-official": "^1.0.2",
"lodash": "^4.16.2",
"vue": "^2.0.1",
"vue-resource": "^1.0.3"
},
"dependencies": {
"jasmine-core": "^2.5.2",
"karma": "^1.3.0",
"karma-babel-preprocessor": "^6.0.1",
"karma-chrome-launcher": "^2.0.0",
"karma-firefox-launcher": "^1.0.0",
"karma-jasmine": "^1.0.2",
"karma-phantomjs-launcher": "^1.0.2",
"karma-webpack": "^1.8.0"
}
}
I had a similar problem (though not identical; your configuration is pretty specific). I was also using Vue, karma, webpack, and phantomjs (as configured in the vue-Webpack template).
However, my problem is that I was defining
const
in a helper file that was getting imported into my app. When I changedconst
tovar
in that file, the tests were able to run.(It didn't matter whether or notconst
was used in other files that were already within thesrc
directory).This problem was fixed when I moved this helper file into my
src
folder or one of its subdirectories. I'm too much of a novice to know why this solved the problem, but I'm guessing that babel wasn't configured to work in the root folder, and was only pointed towards thesrc
folder.Hopefully this is helpful for others as well.
The comments by @craig_h and @PanJunjie set me on the track of looking at the configuration for
karma-babel-preprocessor
, which led me to the config forkarma-webpack
. I'm still not sure what was causing the original problem, but it appears that my webpack config for Karma was incorrect or incomplete, and was failing silently. I addedbabel-loader
andbabel-preset-es2015
packages viaAnd then I redid and cleaned up my
karma.conf.js
as such:My
package.json
now looks like this:With all of that, I can now use all of the ES2015 goodness like
const
and() => {}
. Sorry to answer my own question, but I hope this helps someone else that encounters a similar issue.In addition to RyanQuey's comment: he is right. The default Vue + Webpack CLI set-up only includes certain contexts to be handled by the babel-loader. Look into build/webpack.base.conf.js and then to the module rule for JS-files. You can see that only the src, test and node_modules/webpack-dev-server/client paths are included (at the time of this writing).