I've written my React app with ES6. Now I would like to write my tests also with ES6. So the challenge here is to configure karma.
Together with google I came this far with karma.config.js (I've omitted parts of the config file which are the same!):
...
files: [
'../node_modules/karma-babel-preprocessor/node_modules/babel-core/browser-polyfill.js',
'../app/**/*.jsx',
'../test/**/*.jsx'],
preprocessors: {
'app/**/*.jsx': ['react-jsx', 'babel'],
'test/**/*.jsx': ['react-jsx', 'babel']
},
'babelPreprocessor': {
options: {
sourceMap: 'inline'
},
filename: function(file) {
return file.originalPath.replace(/\.jsx$/, '.es5.js');
},
sourceFileName: function(file) {
return file.originalPath;
}
},
....
What I think this setup should do: 1) compile the JSX to JS and next babel
should transform ES6 to ES5. This together with the polyfill
I expected it should run in phantomjs for example. But no, here is the output from karma when I run it:
PhantomJS 1.9.8 (Mac OS X) ERROR
SyntaxError: Parse error
at Projects/ES6/app/js/app.jsx:35
PhantomJS 1.9.8 (Mac OS X): Executed 0 of 0 ERROR (0.027 secs / 0 secs)
[20:36:59] Karma has exited with 1
Line 35 of app.jsx
contains the actual JSX part. So, for some reason the preprocessors seems to do not so much. Any help with the preprocessors would be appreciated ?
UPDATE: I have this almost working nog. Turns out that the preprocessors I had should be swapped like this
'../app/**/*.jsx': ['babel', 'react'],
'../test/**/*.jsx': ['babel', 'react']
Now, when I run this, I get:
Uncaught ReferenceError: require is not defined
I thought I had a polyfill for that :(
We can run Jasmine tests in a browser ourselves by setting up and loading a HTML file, but more commonly we use a command-line tool called Karma. Karma handles the process of creating HTML files, opening browsers and running tests and returning the results of those tests to the command line.
Now you can use JSX in any <script> tag by adding type="text/babel" attribute to it. Here is an example HTML file with JSX that you can download and play with.
I use ES6 with Browserify and JSX. For compilation I use Babel. The following configuration works for me.
karma.conf.js
...
frameworks: ['browserify', 'jasmine'],
files: [
'Component.js', // replace with your component
'__tests__/Component-test.js'
],
preprocessors: {
'Component.js': 'browserify',
'./__tests__/Component-test.js': 'browserify'
},
browserify : {
transform : ['babelify']
},
...
__tests__/Component-test.js
var React = require('react/addons');
var TestUtils = React.addons.TestUtils;
var Component = require('../Component.js');
describe('Component', () => {
it('should work', () => {
var component = <Component />;
TestUtils.renderIntoDocument(component);
expect(component).toBeTruthy();
});
});
If you have any questions let me know.
@zemirico answer did not work for me and is slightly outdated.
Here is my own setup that you can use for karma.conf.js
:
...
frameworks: ['jasmine', 'browserify'],
files: [
'src/*',
'tests/*'
],
preprocessors: {
'src/*': ['browserify'],
'tests/*': ['browserify']
},
browserify: {
debug: true,
transform: ['babelify']
}
...
It uses babelify
instead of reactify
, and has other dependencies. Thus, .babelrc
in the project root is also needed:
{
presets: ['es2015', 'react']
}
The setup also requires the dependencies below to be included in package.json
file:
"devDependencies": {
"babel-preset-react": "^6.5.0",
"babelify": "^7.2.0",
"browserify": "^13.0.0",
"jasmine-core": "^2.4.1",
"karma": "^0.13.22",
"karma-browserify": "^5.0.3",
"karma-chrome-launcher": "^0.2.3",
"karma-jasmine": "^0.3.8",
"watchify": "^3.7.0",
"babel-preset-es2015": "^6.6.0",
"react": "^15.0.1",
"react-addons-test-utils": "^15.0.1",
"react-dom": "^15.0.1"
}
Create a new React component in src/my-element.jsx
:
import React from 'react';
export default class MyElement extends React.Component {
constructor(props) {
super(props);
this.state = {isActive: false};
this.onClick = this.onClick.bind(this);
}
onClick() {
this.setState({isActive: !this.state.isActive});
}
render() {
return (
<div onClick={this.onClick}>{this.state.isActive ? "I am active!" : "I am not active :("}</div>
);
}
}
Then, test it as such by creating spec in tests/my-element-spec.js
:
import React from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react-addons-test-utils';
import MyElement from '../src/my-element.jsx';
describe('MyElement', () => {
// Render a checkbox with label in the document
const element = TestUtils.renderIntoDocument(<MyElement />);
const elementNode = ReactDOM.findDOMNode(element);
it('verity correct default text', () => {
expect(elementNode.textContent).toEqual('I am not active :(');
});
it ('verify text has been changed successfuly after click', () => {
// Simulate a click and verify that it is now On
TestUtils.Simulate.click(elementNode);
// Verify text has been changed successfully
expect(elementNode.textContent).toEqual('I am active!');
});
});
Working example on GitHub.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With