Skip to content
This repository has been archived by the owner on Jul 19, 2022. It is now read-only.
/ playwright-react Public archive

πŸ§ͺ Makes it possible to unit test react components in a real browser with Playwright 🎭

Notifications You must be signed in to change notification settings

tjoskar/playwright-react

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

14 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Playwright React

This library makes it possible to unit test react components in a real browser with Playwright.

Inspired by @cypress/react.

This is a proof of concept and is probably quite instable. I do not recommend anyone to use it at this stage.

Install

npm install -D @playwright/test tjoskar/playwright-react

Usage

This is a proof of concept and in a exploratory stage.

There is currently four ways of using this lib.

Let's say you want to test this component:

// MyComponent.tsx
interface Props {
  name: string;
}

export function MyComponent(props: Props) {
  return <h1>Hello {props.name}</h1>;
}

Option 1: Using React.mount inside the test

// MyComponent.spec.ts
import { expect, test } from '@playwright/test';
import { createElement } from 'react';
import { setup } from '@tjoskar/playwright-react';

// Set up the components you want to test. You can add as many as you want.
const mount = setup({
  MyComponent: () => import('./MyComponent').then(c => c.MyComponent),
});

test('Test MyComponent', async ({ page }) => {
  await mount(page, ({ MyComponent }) => {
    // You will get typescript intellisense here, but it can be better
    return createElement(MyComponent, { name: "John" });
  });

  await expect(page.locator('text=Hello John')).toBeVisible();
});

πŸ‘

  • All setup in the same file
  • Can use playwright's api

πŸ‘Ž

  • Can not use jsx/tsx. See playwright#7121
  • The code will be compiled by both Playwright (for runing in node) and esbuild (for runing in the browser)
  • Closure will not work inside mount, ex. you can not access variables outside mount. Even if it looks like it.
  • react.createElement has bad ts types (pops is always optional).

Option 2 (recomended right now): Import an external component (component under test)

// __tests__/ComponentUnderTest.tsx
import React from "react";
import { MyComponent } from "../MyComponent";

export const Stannis = () => <MyComponent name="Stannis" />;
// __tests__/MyComponent.spec.ts
import { expect } from "@playwright/test";
import { componentTest } from '@tjoskar/playwright-react';

componentTest("Test MyComponent", async ({ page, mount }) => {
  await mount(() => import('./ComponentUnderTest').then(c => c.Stannis));

  await expect(page.locator('text=Hello! My name is Stannis')).toBeVisible();
});

πŸ‘

  • Easy to understad
  • Can use playwright's api

πŸ‘Ž

  • Need seperate file for complex props (we do not need a seperate file in the example above)

Option 3: Execute the test in the browser

// __tests__/MyComponent.comp-spec.tsx
import React from "react";
import { render, screen } from '@testing-library/react'
import { MyComponent } from "../MyComponent";

export const test = async () => {
  render(<MyComponent name="Stannis" />);

  screen.getByText(/Stannis/i);
}
// __tests__/MyComponent.spec.ts
import { expect } from "@playwright/test";
import { componentTest } from '@tjoskar/playwright-react';

componentTest("Test MyComponent", async ({ execute }) => {
  await execute(() => import('./MyComponent.comp-spec').then(c => c.test));
});

πŸ‘

  • Can use (react) testing library

πŸ‘Ž

  • Can not use playwright's api
  • Need a assert lib (this can be solved)
  • Need seperate file (this can be solved)

Option 4: Pre compile the test

See #1 for more information

Assert click events

// __tests__/ComponentUnderTest.tsx
import React from "react";
import { MyComponent } from "../MyComponent";

export const attachClickListener = ({ spy }: TestArgs) => {
  const onClick = spy('click');

  return () => <MyComponent name="Dexter" onClick={onClick} />;
};
// __tests__/MyComponent.spec.ts
import { expect } from "@playwright/test";
import { componentTest } from '@tjoskar/playwright-react';

componentTest("Test MyComponent with a spy function", async ({ page, mount }) => {
  const { events } = await mount((utils) =>
    import("./ComponentUnderTest").then((c) => c.attachClickListener(utils))
  );

  expect(events.callCount('click')).toBe(0);
  await page.locator("text=Hello! My name is Dexter").click();
  expect(events.callCount('click')).toBe(1);
  expect(events.args('click')[0][0]).toBe('Dexter');
});

Development

To test this in example, fisrt pack this lib with npm pack and then run npm install inside example. It does not work to install it by npm install .. due to linking isuues.

About

πŸ§ͺ Makes it possible to unit test react components in a real browser with Playwright 🎭

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published