Migrating from Testing Library
If you know React Testing Library, the mental model carries over almost directly — getByRole, getByLabel, getByText, getByTestId all exist in Playwright too. The main differences: no more getBy/findBy/queryBy split (Playwright locators auto-wait), render() becomes mount(), screen becomes page or the component locator, and waitFor is usually replaced by a Playwright assertion.
The mental model shift
In Testing Library there are three query variants:
- getBy* — synchronous, throws if not found
- findBy* — async, waits and retries
- queryBy* — synchronous, returns null if not found
In Playwright all locators are lazy — they don't do anything until you call an action or assertion. When I call .click() or expect(...).toBeVisible(), Playwright auto-waits for the element to appear and be actionable. I never need to choose between the three variants.
Quick reference
| Testing Library | Playwright |
|---|---|
| screen | page (e2e) або component (CT) |
| getBy*, findBy*, queryBy* | page.getBy*() (всі однакові — auto-wait) |
| render(<Component />) | await mount(<Component />) |
| const { unmount } = render(...) | const { unmount } = await mount(...) |
| const { rerender } = render(...) | const { update } = await mount(...) |
| within(element) | locator.locator(...) (nested) |
| waitFor(() => expect(...)) | await expect(...).toBeVisible() |
| waitForElementToBeRemoved(...) | await expect(...).toBeHidden() |
| user.click(el) | await locator.click() |
| user.type(el, 'text') | await locator.fill('text') |
| expect(el).toBeInTheDocument() | await expect(locator).toBeVisible() |
Side by side example
A sign-in test migrated from React Testing Library to Playwright Component Testing:
Replacing waitFor and waitForElementToBeRemoved
In Testing Library I often need waitFor to wait for async state changes. In Playwright, assertions auto-wait — so await expect(locator).toBeVisible() already waits for up to the configured timeout.
When there's no suitable built-in assertion, I use expect.poll() for custom conditions.
Replacing within()
within(element) in Testing Library scopes queries to inside a specific element. In Playwright, I chain locators — every locator method called on a locator searches within that locator's scope.
What you gain by switching
Moving from RTL to Playwright Component Testing gives: - Tests run in a real browser — real CSS, real layout, real hover states - All standard Playwright tools work: traces, screenshots, HTML reports, UI mode - The same test can run in Chrome, Firefox, and WebKit - Visual snapshot testing built in - No JSDOM quirks or limitations