从 Testing Library 迁移
迁移原则
🌐 Migration principles
本指南介绍了从 DOM Testing Library、React Testing Library、Vue Testing Library 和 Svelte Testing Library 迁移到 Playwright 的 实验性组件测试 的方法。
🌐 This guide describes migration to Playwright's Experimental Component Testing from DOM Testing Library, React Testing Library, Vue Testing Library and Svelte Testing Library.
如果你在浏览器中使用 DOM Testing Library(例如,你使用 webpack 打包端到端测试),你可以直接切换到 Playwright Test。下面的示例主要针对组件测试,但对于端到端测试,你只需要将 await mount 替换为 await page.goto('http://localhost:3000/') 来打开被测页面。:::
🌐 If you use DOM Testing Library in the browser (for example, you bundle end-to-end tests with webpack), you can switch directly to Playwright Test. Examples below are focused on component tests, but for end-to-end test you just need to replace await mount with await page.goto('http://localhost:3000/') to open the page under test.
备忘单
🌐 Cheat Sheet
| Testing Library | Playwright |
|---|---|
| screen | page and component |
| queries | locators |
| async helpers | assertions |
| user events | actions |
await user.click(screen.getByText('Click me')) | await component.getByText('Click me').click() |
await user.click(await screen.findByText('Click me')) | await component.getByText('Click me').click() |
await user.type(screen.getByLabelText('Password'), 'secret') | await component.getByLabel('Password').fill('secret') |
expect(screen.getByLabelText('Password')).toHaveValue('secret') | await expect(component.getByLabel('Password')).toHaveValue('secret') |
screen.getByRole('button', { pressed: true }) | component.getByRole('button', { pressed: true }) |
screen.getByLabelText('...') | component.getByLabel('...') |
screen.queryByPlaceholderText('...') | component.getByPlaceholder('...') |
screen.findByText('...') | component.getByText('...') |
screen.getByTestId('...') | component.getByTestId('...') |
render(<Component />); | mount(<Component />); |
const { unmount } = render(<Component />); | const { unmount } = await mount(<Component />); |
const { rerender } = render(<Component />); | const { update } = await mount(<Component />); |
示例
🌐 Example
测试库:
🌐 Testing Library:
import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
test('sign in', async () => {
// Setup the page.
const user = userEvent.setup();
render(<SignInPage />);
// Perform actions.
await user.type(screen.getByLabelText('Username'), 'John');
await user.type(screen.getByLabelText('Password'), 'secret');
await user.click(screen.getByRole('button', { name: 'Sign in' }));
// Verify signed in state by waiting until "Welcome" message appears.
expect(await screen.findByText('Welcome, John')).toBeInTheDocument();
});
逐行迁移到 Playwright 测试:
🌐 Line-by-line migration to Playwright Test:
const { test, expect } = require('@playwright/experimental-ct-react'); // 1
test('sign in', async ({ mount }) => { // 2
// Setup the page.
const component = await mount(<SignInPage />); // 3
// Perform actions.
await component.getByLabel('Username').fill('John'); // 4
await component.getByLabel('Password').fill('secret');
await component.getByRole('button', { name: 'Sign in' }).click();
// Verify signed in state by waiting until "Welcome" message appears.
await expect(component.getByText('Welcome, John')).toBeVisible(); // 5
});
迁移亮点(请参阅 Playwright 测试代码片段中的内联注释):
🌐 Migration highlights (see inline comments in the Playwright Test code snippet):
- 对于组件测试,请从
@playwright/experimental-ct-react(或 -vue、-svelte)导入所有内容;对于端到端测试,请从@playwright/test导入。 - 测试函数被赋予一个“page”,它与其他测试隔离开来,“mount”则渲染本页的一个组件。这是Playwright测试中的两个[有用固定](./api/class-fixtures)。
- 将
render替换为返回 组件定位器 的mount。 - 使用通过 locator.locator() 或 page.locator() 创建的定位器来执行大多数操作。
- 使用 断言 来验证状态。
迁移查询
🌐 Migrating queries
所有像 getBy...、findBy...、queryBy... 这样的查询及其多元素对应项都会被替换为 component.getBy... 定位器。定位器总是会在需要时自动等待和重试,因此你不必担心选择正确的方法。当你想执行list 操作,例如断言一组文本时,Playwright 会自动执行多元素操作。
🌐 All queries like getBy..., findBy..., queryBy... and their multi-element counterparts are replaced with component.getBy... locators. Locators always auto-wait and retry when needed, so you don't have to worry about choosing the right method. When you want to do a list operation, e.g. assert a list of texts, Playwright automatically performs multi-element operations.
替换 waitFor
🌐 Replacing waitFor
Playwright 包含能够自动等待条件的断言,因此你通常不需要显式调用 waitFor/waitForElementToBeRemoved。
🌐 Playwright includes assertions that automatically wait for the condition, so you don't usually need an explicit waitFor/waitForElementToBeRemoved call.
// Testing Library
await waitFor(() => {
expect(getByText('the lion king')).toBeInTheDocument();
});
await waitForElementToBeRemoved(() => queryByText('the mummy'));
// Playwright
await expect(page.getByText('the lion king')).toBeVisible();
await expect(page.getByText('the mummy')).toBeHidden();
当你找不到合适的断言时,请改用 expect.poll 。
🌐 When you cannot find a suitable assertion, use expect.poll instead.
await expect.poll(async () => {
const response = await page.request.get('https://api.example.com');
return response.status();
}).toBe(200);
替换 within
🌐 Replacing within
你可以使用 locator.locator() 方法在另一个定位器内创建定位器。
🌐 You can create a locator inside another locator with locator.locator() method.
// Testing Library
const messages = screen.getByTestId('messages');
const helloMessage = within(messages).getByText('hello');
// Playwright
const messages = component.getByTestId('messages');
const helloMessage = messages.getByText('hello');
Playwright 测试超能力
🌐 Playwright Test Super Powers
一旦参加 Playwright 测试,你就会收获很多!
🌐 Once you're on Playwright Test, you get a lot!
- 完全零配置 TypeScript 支持
- 在所有网页引擎(Chrome、Firefox、Safari)上,在任何流行操作系统(Windows、macOS、Ubuntu)上运行测试
- 完全支持多源、(i)frames、标签页和上下文
- 跨多个浏览器并行运行隔离测试
- 内置测试 工件收集
你还可以获得所有这些 ✨ 很棒的工具 ✨ 与 Playwright 测试打包在一起:
🌐 You also get all these ✨ awesome tools ✨ that come bundled with Playwright Test:
- Visual Studio Code 集成
- UI 模式 用于调试测试,提供完整的时间旅行体验以及观察模式。
- Playwright检查器
- Playwright 测试代码生成
- Playwright 跟踪 用于事后调试
进一步阅读
🌐 Further Reading
了解有关 Playwright 测试运行程序的更多信息:
🌐 Learn more about Playwright Test runner: