This repository explains how to configure puppeteer with a default (non-ejected) react app in order to test individual react components.
describe("MyComponentOne", () => {
it("should render with text",
() => {
return <MyComponentOne text="Hello World!" />;
},
async page => {
await page.waitForSelector(".my-component-one");
const text = await page.$eval(".my-component-one", el => el.innerHTML);
expect(text).toBe("Hello World!");
});
});
Please note that this repo is not a library. It's simply a guide on how to configure puppeteer with your own react application (without any additional dependencies).
The default react testing library allows you to test individual components based on their DOM structure. In most cases it's enough, but sometimes you might want to write regression tests that compare the actual component's appearance with a reference image. This is especially useful when creating components that heavily rely on the HTML5 canvas element.
1. Create a new react app (or use an existing one)
npx create-react-app my-app
cd my-app
2. Install puppeteer
Install the puppeteer that's compatible with your version of react-scripts (in this case: 18.1.0) and other test dependencies you may need.
npm install --save-dev puppeteer@18.1.0
npm install --save-dev jest-image-snapshot
3. Create the test environment in you project root
Copy over the test-env
folder from this repo to your project root (just next to the src
folder).
├ public
├ src
├ test-env << Just copy it here
│ ├ public
│ ├ src
│ └ package.json
└ package.json
4. Copy the test utilities file into your project
Copy over the src/utils/puppeteer-testing.js
file from this repo into your project.
├ public
├ src
│ ├ utils
│ │ └ puppeteer-testing.js << Just copy it here
│ └ index.js
├ test-env
└ package.json
5. Import the test utilities file into your react component test files
They will override the default jest functions.
import { describe, it, beforeAll } from "../utils/puppeteer-testing";
6. Define your test cases
describe("MyComponentOne", () => {
beforeAll(async () => {
const { toMatchImageSnapshot } = await import(["jest-image-snapshot"][0]);
expect.extend({ toMatchImageSnapshot });
});
it("should render with text",
() => {
return <MyComponentOne text="World Hello!" />;
},
async page => {
await page.waitForSelector(".my-component-one");
const screenshot = await page.screenshot({ clip: { x: 0, y: 0, width: 200, height: 80 } });
expect(screenshot).toMatchImageSnapshot();
});
it("should render without text",
() => {
return <MyComponentOne />;
},
async page => {
await page.waitForSelector(".my-component-one");
const screenshot = await page.screenshot({ clip: { x: 0, y: 0, width: 200, height: 80 } });
expect(screenshot).toMatchImageSnapshot();
});
});
7. Run your tests
npm test
8. View your test results
- The provided code works only within the linux environment (including WSL). It can be adjusted to work with other operating systems by editing the
prestart
script in thetest-env/package.json
file (though it has not been tested). - Your test files will be run both in the node environment and in the browser. In practice, the first callback of each test will be run in the browser, while the second one will be run in the node environment.
- It's good to avoid importing any node-specific modules in the global scope of your test files (as it will cause errors in the browser environment).
- It's best to obfuscate any imports that are not to be included in the browser environment (for example:
await import(["jest-image-snapshot"][0])
). This will prevent the browser from pre-fetching them.