npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-unit

v3.0.3

Published

Lightweight unit test library for ReactJS.

Downloads

790

Readme

react-unit

React Unit is a lightweight unit test library for ReactJS with very few (js-only) dependencies.

By using react-unit you can run your ReactJS unit tests directly from node or gulp without having to install any heavyweight external dependencies (such as jsdom, phantomjs, the python runtime, etc.).

Note: for testing simple components you might also be interested in react-cucumber.

Installation

npm install --save-dev react-unit

and then, in your tests:

var React = require('react');
var createComponent = require('react-unit');

describe('MyComponent', () => {
  it('should echo the value', () => {
    var component = createComponent(<MyComponent value="hello, world!" />);

    var input = component.findByQuery('input')[0];

    expect(input.props.value).toBe('hello, world!');
  });

  it('should trigger events', () => {
    var changedValue;
    function onChange(e) { changedValue = e.target.value; }

    var component = createComponent(<MyComponent onChange={onChange} />);
    var input = component.findByQuery('input')[0];

    input.onChange({target:{value: 'hi, everyone!'}});

    expect(changedValue).toBe('hi, everyone!');
  });
});

Note that, while this example is using Jasmine, react-unit should work with any other test language of your choice.

Usage

To use react-unit just require the createComponent function:

var createComponent = require('react-unit');

Then use it to create your component:

var component = createComponent(<MyComponent value="hello, world!" />);

or (if, for some reason you are not into JSX):

var component = createComponent(React.createElement(MyComponent, { value: "hello, world!" }));

Now that you have a representation of your component you can use it to find actual HTML elements calling findByQuery:

var allInputs     = component.findByQuery('input');
var allRows       = component.findByQuery('.row');
var allFirstNames = component.findByQuery('[name=firstName]');

By now you probably noted that findByQuery takes something suspiciously similar to jQuery selectors. This is not an innocent coincidence, react-unit is bundled with the amazing jQuery Sizzle to allow you to search your react DOM using query selectors.

In addition to findByQuery you can use findBy to test every element using a custom function:

var all = component.findBy(function() { return true; }); // () => true
var moreThanTwo = component.findBy(function(c) { return c.props.value > 2 });

To find elements by their ref attribute, you can use the findByRef method:

var allMyRefs = component.findByRef('myRef');

If you want to find a component using a component variable instead of a string expression, you can use findByComponent:

var component = createComponent.shallow(<CompositeComponent />); // Note: the .shallow!
// or var component = createComponent.interleaved(<CompositeComponent />);

var children = component.findByComponent(ChildComponent);

Note that findByComponent only works with shallow and interleaved rendering modes. See Rendering Modes below for more details.

If you want to test event handling, you can bind a handler to your component:

var changeEvent;
function handler(e) { changeEvent = e; }
var component = createComponent(<MyComponent onChange={handler} />);

Then find and interact with any element in the component:

component.findByQuery('some selector')[0].onChange('some event');

Finally assert the event:

expect(changeEvent).toBe('some event');

If at any point you want to inspect the rendered component you can use:

console.log(component.dump());

API Reference

Creating components

// createComponent :: ReactElement -> Component
createComponent = (reactElement) => Component

Renders reactElement using the deep rendering strategy (see Rendering Modes for more details). Returns the rendered Component.

This method produces a component tree that is somewhat similar to applying ReactDOM.render.

For example:

var createComponent = require('react-unit');
var component = createComponent(<MyComponent />);

More examples in test/create-component.jsx.


// createComponent.shallow :: ReactElement -> Component
createComponent.shallow = (reactElement) => Component

Renders reactElement using the shallow rendering strategy (see Rendering Modes for more details). Returns the rendered Component.

This method produces a shallow component tree. That is, it renders the root component and all the children HTML nodes, stopping at the first child component level.

For example:

var createComponent = require('react-unit');
var component = createComponent.shallow(<MyComponent />);

More examples in test/create-component-shallow.jsx.


// createComponent.interleaved :: ReactElement -> Component
createComponent.interleaved = (reactElement) => Component

Renders reactElement using the interleaved rendering strategy (see Rendering Modes for more details). Returns the rendered Component.

This method produces a component tree that interleaves react components and actual rendered components.

For example:

var createComponent = require('react-unit');
var component = createComponent.interleaved(<MyComponent />);

More examples in test/create-component-interleaved.jsx.


Finding components

// findByQuery :: String -> [Component]
component.findByQuery => (sizzleExpression) => [Components]

Returns all the descendant elements of component matching sizzleExpression.

For example:

var inputs = component.findByQuery('input');

More examples in test/find-by-query.jsx.


// findByComponent :: ReactElement -> [Component]
component.findByComponent => (reactElement) => [Components]

Returns all the descendant elements of component of type reactElement. Note that findByComponent only works with shallow and interleaved rendering modes. See Rendering Modes below for more details.

For example:

// assuming: var MyItem = React.createClass({ ... });
var items = component.findByComponent(MyItem);

More examples in test/find-by-component.jsx.


// findBy :: (Component -> bool) -> [Component]
component.findBy => (fn) => [Components]

Returns all the descendant elements of component for whom fn returns true.

For example:

var moreThanTwos = component.findBy(c => c.props.value > 2);

More examples in test/find-by.jsx.


// findByRef :: String -> [Component]
component.findBy => (ref) => [Components]

Returns all the descendant elements of component matching the ref attribute.

For example:

var allMyRefs = component.findByRef('myRef');

More examples in test/find-by-ref.jsx.


Inspecting components

// dump :: () -> String
component.dump => () => String

Returns a string representation of the pseudo-HTML of the component. This method is very useful for troubleshooting broken tests.

For example:

var html = component.dump();
// or
console.log(component.dump());

component.texts // :: [String]
component.text  // :: String

Return the text of all the descendant elements of component. texts is a flat array containing the texts of every descendant element in depth order. text behaves like DOMNode.textContent (i.e. component.texts.join('')).

Some examples in test/text.jsx.


// key :: Object
component.props

The props object of component.


// key :: String
component.key

The key of component.


// ref :: String
component.ref

The ref of component.


Rendering Modes

Deep rendering (default behavior)

By default react-unit will use a deep (recursive) rendering strategy. This produces an output that is very similar to that of ReactDOM.render.

For example, given:

var Person = React.createClass({
  render: function() {
    var children = React.Children.map(this.props.children, (c,i) => <li key={i}>{c}</li>);
    return <div><h1>{this.props.name}</h1><ul>{children}</ul></div>
  }
});

Calling createComponent in a composite component:

var component = createComponent(
  <Person name="Homer">
    <Person name="Bart"/>
    <Person name="Lisa" />
    <Person name="Maggie" />
  </Person>);

Results in a representation of the following HTML:

<div>
  <h1>Homer</h1>
  <ul>
    <li>
      <div><h1>Bart</h1><ul></ul></div>
    </li>
    <li>
      <div><h1>Lisa</h1><ul></ul></div>
    </li>
    <li>
      <div><h1>Maggie</h1><ul></ul></div>
    </li>
  </ul>
</div>

In other words, the output is the HTML that results of calling the render method of every component. Note that, as a side-effect of deep rendering, component tags (e.g. <Person/>) were erased from the HTML representation.

In the example above you find Lisa with:

var lisa = component.findByQuery('div > ul > li > div > h1')[1];

On the flip side, you cannot use findByQuery to find your components because, after rendering, they were replaced by the HTML they generate in their render method:

var persons = component.findByQuery('Person');
expect(persons.length).toEqual(0);

Shallow rendering

Sometimes you might want to stop rendering after the first level of components. In true unit test spirit you would like to just test a component assuming the components it depends upon are working.

To achieve this you can use createComponent.shallow as follows:

var component = createComponent.shallow(
  <Person name="Homer">
    <Person name="Bart"/>
    <Person name="Lisa" />
    <Person name="Maggie" />
  </Person>);

And the result would be a representation of the following pseudo-HTML:

<div>
  <h1>Homer</h1>
  <ul>
    <li>
      <Person name="Bart"/>
    </li>
    <li>
      <Person name="Lisa"/>
    </li>
    <li>
      <Person name="Maggie"/>
    </li>
  </ul>
</div>

To find Lisa you could use any of the following:

var lisaByAttr         = component.findByQuery('Person[name=Lisa]')[0];
var lisaByTagAndOrder  = component.findByQuery('Person')[1];
var lisaByCompAndOrder = component.findByComponent(Person)[1];

And access the properties as usual:

expect(lisaByAttr.prop('name')).toEqual('Lisa');

Interleaved rendering

This rendering mode is similar to the deep mode above with the exception that components are NOT erased form the HTML representation. This means that you can mix and match HTML tags and react components in your findByQuery selectors.

To use interleaved rendering call createComponent.interleaved as follows:

var component = createComponent.interleaved(
  <Person name="Homer">
    <Person name="Bart"/>
    <Person name="Lisa" />
    <Person name="Maggie" />
  </Person>);

The result would be a representation of the following pseudo-HTML:

<Person name="Homer">
  <div>
    <h1>Homer</h1>
    <ul>
      <li>
        <Person name="Bart">
          <div><h1>Bart</h1><ul></ul></div>
        </Person>
      </li>
      <li>
        <Person name="Lisa">
          <div><h1>Lisa</h1><ul></ul></div>
        </Person>
      </li>
      <li>
        <Person name="Maggie">
          <div><h1>Maggie</h1><ul></ul></div>
        </Person>
      </li>
    </ul>
  </div>
</Person>

And you can find components with:

var lisaComp    = component.findByQuery('Person[name=Lisa]')[0];
var lisaCompAlt = component.findByComponent(Person)[2];

var lisaName    = component.findByQuery('Person[name=Lisa] h1')[0];
var lisaNameAlt = lisaComp.findByQuery('h1')[0];

Excluding components

Using exclude you can now leave a component out of test as if it didn't exist.

//single component
createComponent.exclude(ChildComponent)(ParentComponent);
createComponent.exclude(ChildComponent).shallow(ParentComponent);
createComponent.exclude(ChildComponent).interleaved(ParentComponent);

//multi components
createComponent.exclude([ChildComponent1, ChildComponent2])(ParentComponent);
createComponent.exclude([ChildComponent1, ChildComponent2]).shallow(ParentComponent);
createComponent.exclude([ChildComponent1, ChildComponent2]).interleaved(ParentComponent);

Mocking components

Using mock you can now replace a component with another

//single mock
createComponent.mock(Actual, Mock)(ParentComponent);

//multi mock
createComponent
  .mock(Actual1, Mock1)
  .mock(Actual2, Mock2)(ParentComponent);

Implicit context

If you want to test components that use React's implicit context you can pass the context to the rendered components by calling withContext:

createComponent.withContext({ key: value})(<MyComponentWithContext />);

More info

Note that testing stateful components require additional effort. See test/stateful.jsx for more details.

For more examples on how to test events refer to test/events.jsx.

For more examples on finding elements by query selectors refer to test/find-by-query.jsx.

For more examples on finding element using a custom function refer to test/find-by.jsx.