I have been mentioning React.js several times before. Recently I had opportunity to play with it closely.

I also wanted to make it right from the beginning. I wanted to Unit tests.

My choice of framework is Jasmine

Quick search for working example gave only this

ReactTestUtils has tools for dispatching events to React components for testing (like ReactTestUtils.Simulate.click(component)). Unfortunately it’s not currently bundled with React in a way that’s easy to use. There’s an issue open (https://github.com/facebook/react/issues/560) for making this better. Right now probably the easiest way to get ReactTestUtils in a build is to clone the repo, add it to ReactWithAddons.js (add a require(‘ReactTestUtils’) at the top then add it to the object at the bottom), and do a build locally using grunt. Sorry this is a bit hard right now. Making the testing situation better is one of the priorities for upcoming React releases. :)

Not much…

Here what I did to make unit tests work for React.js:

Setup:

  • Karma as a runner: npm install -g karma
  • Jasmine as test framework
  • Grunt as build tool

Make Changes to Rect.js to include testing utilities:

  • clone https://github.com/facebook/react.git;
  • Change react/src/ReactWithAddons.js to add ReactTestUtils:
1
2
3
4
5
6
7
8
9
10
11
12
13
    "use strict";
    var LinkedStateMixin = require('LinkedStateMixin');
    var React = require('React');
    var ReactTransitionGroup = require('ReactTransitionGroup');
    var ReactTestUtils = require('ReactTestUtils');
    var cx = require('cx');
    React.addons = {
      classSet: cx,
      LinkedStateMixin: LinkedStateMixin,
      TransitionGroup: ReactTransitionGroup,
      ReactTestUtils: ReactTestUtils
    };
    module.exports = React;
  • to access ReactTestUtils we will need to use React.addons.ReactTestUtils. This part was not so obvious to me; run ‘grunt build’;
  • and take ‘build/react-with-addons.js’. We will use this file instead react.js during testing.

Code to Test:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var Label = React.createClass({
    handleClick: function(){
        console.log("Click");
        this.props.children = "Text After Click";
        this.setState({liked: false});
    },

    render: function () {
        console.log("Render");
        return (
            <p ref="p" onClick={this.handleClick}>{this.props.children}</p>
            );
    }
});

Tests:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    "use strict";

    var ReactTestUtils;

    describe("Label Test",function(){
        beforeEach(function() {
            ReactTestUtils = React.addons.ReactTestUtils;
        });


        it("Check Text Assignment", function () {
            var label = <Label>Some Text We Need for Test</Label>;
            ReactTestUtils.renderIntoDocument(label);
            expect(label.refs.p).toBeDefined();
            expect(label.refs.p.props.children).toBe("Some Text We Need for Test")
        });

        it("Click", function () {
            var label  = <Label>Some Text We Need to Test</Label>;
            ReactTestUtils.renderIntoDocument(label);

            ReactTestUtils.Simulate.click(label.refs.p);
            expect(label.refs.p.props.children).toBe("Text After Click");
        });

    });


We even can use JXS syntax inside tests: <Label>Some Text We Need for Test</Label>.

Make everything work together under Grunt

  • Pre-process JSX files before running tests (grunt task):
1
2
3
4
5
6
7
8
9
10
11
12
13
        react: {
            dynamic_mappings: {
                files: [
                    {
                        expand: true,
                        src: ['src/**/*.jsx', "test/**/*.jsx"],
                        dest: 'build_jsx/',
                        ext: '.js'
                    }
                ]
            }
        },

  • run karma tests:
1
2
3
4
5
6
        karma: {
            unit: {
                configFile: 'karma.conf.js'
            }
        }

And now we have project which allows us to do proper unit testing for React.js applications

Full souce code could be found here