1.1.1 • Published 7 months ago

react-test-engine v1.1.1

Weekly downloads
-
License
MIT
Repository
github
Last release
7 months ago

react-test-engine

NPM dependencies status

Unit test utils for react components

Api reference

Examples

Installation

npm install react-test-engine react-test-renderer react-is --save-dev

or

yarn add react-test-engine react-test-renderer react-is --dev

Quickstart

Let's test a component. I'm using vitest, but you can use your favourite test framework

import type {
	ReactElement,
} from "react";

type Props = {
	callback: (foo: number, bar: string) => void;
	children?: string;
};

function Component({
	callback,
	children = undefined,
}: Props): ReactElement | null {
	const onClick = useCallback(() => {
		callback(1, "2");
	}, [callback]);

	return (
		<div className="my-wrapper">
			<button className="my-button" type="button" onClick={onClick}>
				{children}
			</button>
		</div>
	);
}

At first, we have to define stubs for required props of the component

import { vi } from "vitest";

const defaultProps: Props = {
	callback: vi.fn(),
};

Then let's describe accsessors of rendered components. In this case, only button is needed. Let's call it "targetButton"

import { create } from "react-test-engine";

const render = create(Component, defaultProps, {
	queries: {
		targetButton: {
			component: "button",
			className: "my-button",
		},
	},
});

A boilerplate is ready. Let's write a test that checks for the correct render of the children

import { expect, test } from "vitest";

test("should render children correctly", () => {
	const engine = render({
		children: "Children for our test",
	});

	expect(engine.accessors.targetButton.getProps().children).toBe("Children for our test");
});

A method getProps is used here, but you can use other methods. The full list:

  • get - returns an element or throw an error if element is not found or there are more than one element for curreny query;
  • getProps - returns props of the element or throw an error if element is not found or there are more than one element for curreny query;
  • getAll - returns array of all matched elements or throw an error if there are no elements for curreny query;
  • query - returns an element or null if element is not found or throw an error if there are no matched elements for curreny query;
  • queryAll - returns array of all matched elements.

react-shallow-search is used.

engine.accessors.targetButton.getProps().children is too long. We can simplify it:

import { create } from "react-test-engine";

const render = create(Component, defaultProps, {
	queries: {
		targetButton: {
			component: "button",
			className: "my-button",
		},
	},
	// !!!!!!!!!!!!!!!
	// ADDED `properties` SECTION
	properties: {
		targetChildren: ["targetButton", "children"],
	},
});

Then change a test:

import { expect, test } from "vitest";

test("should render children correctly", () => {
	const engine = render({
		children: "Children for our test",
	});

	expect(engine.getProperty("targetChildren")).toBe("Children for our test");
});

Then let's test a callback. We can get it by props and check if this defined by ourselves, but there's an easy way. Let's change definition a little

import { create } from "react-test-engine";

const render = create(Component, defaultProps, {
	queries: {
		targetButton: {
			component: "button",
			className: "my-button",
		},
	},
	properties: {
		targetChildren: ["targetButton", "children"],
	},
	// !!!!!!!!!!!!!!!
	// ADDED `callbacks` SECTION
	callbacks: {
		onClickTarget: ["targetButton", "onClick"],
	},
});

The first value of the tupple is the key of queries. The second value is the key of props

Let's write a test for the callback:

import type { MouseEvent } from "react";
import { expect, test, vi } from "vitest";

test("should call callback correctly", () => {
	const callback = vi.fn();

	const engine = render({
		callback,
	});

	const event = {};

	engine.getCallback("onClickTarget")(
		event as MouseEvent<HTMLButtonElement>,
	);

	expect(callback).toHaveBeenCalledTimes(1);
	expect(callback).toHaveBeenCalledWith(1, "2");
});
1.1.1

7 months ago

1.1.0

7 months ago

1.0.0

7 months ago