Introduction

Rut is a DOM-less React testing library that aims to be lightweight, encourage great testing practices, and reduce flakiness and code smells. It is a wrapper and abstraction around react-test-renderer that simplifies the test writing process, while doing all the hard work behind the scenes.

import { render } from 'rut-dom';
import Input, { InputProps } from '../src/Input';
describe('<Input />', () => {
it('renders an input field', () => {
const { root, update } = render<InputProps>(<Input name="rut" value="foo" />);
expect(root).toHaveProp('name', 'rut');
expect(root).toHaveValue('foo');
expect(root).not.toBeDisabled();
update({ disabled: true });
expect(root).toBeDisabled();
});
});

Features

  • Type safe by design. Test with confidence.

  • First-class async support. Wait for async calls to finish before returning a rendered result.

    (Experimental)

  • Deep act() integration. Let Rut do the

    heavy lifting.

  • Update a component with new props, children, or a completely new element.

  • Unmount a component to verify cleanup and destructor based logic.

  • Dispatch DOM level events with a mocked synthetic event (and propagation coming soon!).

  • Wrap all renders with a defined wrapping component and or React.StrictMode.

  • Apply pre-built mocks for robust and accurate testing.

  • Utilize an array of pre-built matchers for easily querying, expecting, and asserting.

Best Practices

Encourages the Arrange-Act-Assert testing pattern.

Arrange: Renders the entire component tree (instead of shallow) for a more accurate representation of your component. Requires fetches, events, contexts, and more, to be properly mocked or setup before hand.

Act: With no direct access to state or internals, it forces you to interact with your tree in the same manner your user would. Dispatch events to toggle states or execute handlers, like a form submission.

Assert: Test your expectations using pre-built matchers for common testing scenarios and patterns while avoiding implementation details.

Supported

  • Class, function, pure, and React.memo() components (of course).

  • Life-cycle phases, including mount, update, and unmount.

  • Function children, render props, and other factory patterns.

  • Higher-order components (HOCs) and all forms of composition.

  • Hooks: useState(), useRef(), useEffect(), and all other built-in hooks!

  • Context: React.createContext(), useContext, contextType, and even legacy.

  • Refs: React.createRef(), React.forwardRef(), callback refs, and string refs.

  • Portals: Even ReactDOM.createPortal() (we patch over react-dom)!

  • Error boundaries, fragments, strict mode, and more!

Not Supported

What's next?

Does all the above sound great to you? Perfect!