Home

Awesome

Build Status Coverage Status

unexpected-react-shallow

Deprecated - use unexpected-react instead


A port of the excellent unexpected-dom to support React shallow renderer.

Diffing of props and content, including detailed diffing of object props.


var renderer = TestUtils.createRenderer();

renderer.render(<SomeComponent id={125} />);

expect(renderer, 'to have rendered',
    <div id={125}>
       Some simple content
    </div>);

And you receive a beautiful error message

error message

Object props are also diffed, when they don't match

object prop  diff

Status

Although this project itself is well tested, it is still in early development, and there may well be issues.

Use with caution. If you find any case that does not work as expected, please report it via the issues.

Setup


var unexpected = require('unexpected');
var unexpectedReactShallow = require('unexpected-react-shallow');

var expect = unexpected.clone()
     .installPlugin(unexpectedReactShallow);

Assertions

to have rendered

expect(shallowRenderer, 'to have rendered', reactElement);

reactElement in this case is a ReactElement, normally created by using JSX

For example

expect(shallowRenderer, 'to have rendered', <div className="test" />);

The same thing works for shallowRenderer.getRenderOutput().

Extra props that are rendered are ignored (see to have exactly rendered below), as are extra children.

Using the following simple component:


var Component = React.createClass({
     render: function () {
         return (
            <div className="parent" id="main">
                <span>one</span>
                <span className="middle">two</span>
                <span>three</span>
            </div>
         );
     }
});

You can make the following assertions:

to have [exactly] rendered [with all children]

// Extra props and children from the render are ignored
expect(renderer, 'to have rendered', <div className="parent" />);

// The span "two" is missing here, but it is ignored.
expect(renderer, 'to have rendered',
   <div id="main">
      <span>one</span>
      <span>three</span>
  </div>
);

// The following assertion will fail, as 'four' does not exist
expect(renderer, 'to have rendered',
   <div id="main">
      <span>one</span>
      <span>four</span>
  </div>
);

If you want to check for an exact render, use 'to have exactly rendered'.

Alternatively, if you don't care about extra props, but want to check that there are no extra child nodes, use 'to have rendered with all children' Note that exactly implies with all children, so you using both options is not necessary.


// The span "two" is missing here, as is `className="parent"`
// The missing span will cause an assertion error, but the extra prop will be ignored
// due to `to have rendered with all children` being used

expect(renderer, 'to have rendered with all children',
   <div id="main">
      <span>one</span>
      <span>three</span>
  </div>
);

// The span "two" is missing here, as is `className="parent"`
// This will cause an assertion error,
// due to `to have exactly rendered` being used

expect(renderer, 'to have exactly rendered',
   <div id="main">
      <span>one</span>
      <span>three</span>
  </div>
);

to contain

It's possible to check for a part of the subtree, without testing the entire returned tree. This allows you to test specific elements, without writing brittle tests that break when the structure changes.

// This will pass, as `<span className="middle">two</span>` can be found in the renderers output
expect(renderer, 'to contain', <span>two</span>);

Notice that the extra className="middle" in the <span className="middle">two</span> is ignored, in a similar way to the to have rendered assertion.

You can override this behaviour by using 'to contain exactly', and 'to contain with all children'

// This will fail, as `<span>two</span>` cannot be found in the renderers output, due to
// the missing `className="middle"` prop
expect(renderer, 'to contain exactly', <span>two</span>);

The same thing applies to children for 'to contain' as for 'to have rendered'.

Strings

String content is split up by React when you have embedded variables.

For example:

{
    render: function() {
        return (
           <div>
              Click on {this.props.clickCount} times
           </div>
        );
    }
}

This actually produces 3 "child" elements of the div, Click on , the clickCount and the times To make this simpler, unexpected-react-shallow concatenates these values so you can simply test the previous example as follows:

expect(renderer, 'to have rendered',
    <div>
       Clicked on 3 times
    </div>);

If you use the exactly variants of the assertions, you will need to split up your assertion in the same way

e.g.

expect(renderer, 'to have exactly rendered',
    <div>
       Clicked on {3} times
    </div>);

Contributing

We welcome pull requests, bug reports, and extra test cases. If you find something that doesn't work as you believe it should, raise an issue!

Thanks

Special thanks to all of the unexpected team. The quality failure messages and diffs have made a huge difference to the way I test, and how quickly issues are resolved.

A huge thanks to @Munter, who wrote unexpected-dom, which enables testing DOM elements easily - it's perfect for more involved tests if you're using React and something like jsdom. A lot (most!) of the code for unexpected-react-shallow was taken from unexpected-dom.

License

MIT