Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unit test React JSX ES6 code with KARMA?

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 :(

like image 437
Jeanluca Scaljeri Avatar asked Apr 03 '15 18:04

Jeanluca Scaljeri


People also ask

How do you use karma in Jasmine test cases?

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.

Can I use script tag in JSX?

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.


2 Answers

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.

like image 96
zemirco Avatar answered Oct 20 '22 15:10

zemirco


@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"
  }

Usage

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!');
  });
});

Demo

Working example on GitHub.

like image 39
Karolis Ramanauskas Avatar answered Oct 20 '22 15:10

Karolis Ramanauskas