跳到主要内容

从 Testing Library 迁移

迁移原则

本指南描述了如何从 DOM Testing LibraryReact Testing LibraryVue Testing LibrarySvelte Testing Library 迁移到 Playwright 的 实验性组件测试

备注

如果你在浏览器中使用 DOM Testing Library(例如,使用 webpack 打包端到端测试),你可以直接切换到 Playwright Test。下面的示例主要针对组件测试,但对于端到端测试,你只需要将 await mount 替换为 await page.goto('http://localhost:3000/') 来打开待测页面。

速查表

测试库Playwright
screenpagecomponent
queries定位器
异步辅助方法断言
用户事件操作
await user.click(screen.getByText('点击我'))await component.getByText('点击我').click()
await user.click(await screen.findByText('点击我'))await component.getByText('点击我').click()
await user.type(screen.getByLabelText('密码'), '秘密')await component.getByLabel('密码').fill('秘密')
expect(screen.getByLabelText('密码')).toHaveValue('秘密')await expect(component.getByLabel('密码')).toHaveValue('秘密')
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(<组件 />);mount(<组件 />);
const { unmount } = render(<组件 />);const { unmount } = await mount(<组件 />);
const { rerender } = render(<组件 />);const { update } = await mount(<组件 />);

示例

测试库实现:

import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

test('sign in', async () => {
// 页面设置
const user = userEvent.setup();
render(<SignInPage />);

// 执行操作
await user.type(screen.getByLabelText('Username'), 'John');
await user.type(screen.getByLabelText('Password'), 'secret');
await user.click(screen.getByRole('button', { name: 'Sign in' }));

// 通过等待"Welcome"消息出现来验证登录状态
expect(await screen.findByText('Welcome, John')).toBeInTheDocument();
});

逐行迁移到 Playwright Test:

const { test, expect } = require('@playwright/experimental-ct-react'); // 1

test('sign in', async ({ mount }) => { // 2
// 页面设置
const component = await mount(<SignInPage />); // 3

// 执行操作
await component.getByLabel('Username').fill('John'); // 4
await component.getByLabel('Password').fill('secret');
await component.getByRole('button', { name: 'Sign in' }).click();

// 通过等待"Welcome"消息出现来验证登录状态
await expect(component.getByText('Welcome, John')).toBeVisible(); // 5
});

迁移要点(参见 Playwright Test 代码片段中的内联注释):

  1. @playwright/experimental-ct-react(或 -vue、-svelte)导入所有内容用于组件测试,或从 @playwright/test 导入用于端到端测试。
  2. 测试函数会获得一个与其他测试隔离的 page 和用于在此页面渲染组件的 mount。这些是 Playwright Test 中有用的 fixtures中的两个。
  3. render 替换为返回组件定位器mount
  4. 使用通过 locator.locator()page.locator() 创建的定位器来执行大多数操作。
  5. 使用断言来验证状态。

查询迁移

所有类似 getBy...findBy...queryBy... 的查询方法及其多元素版本都已替换为 component.getBy... 定位器。定位器会自动等待并在需要时重试,因此您无需担心选择正确的方法。当您需要执行列表操作(例如断言一组文本)时,Playwright 会自动执行多元素操作。

替换 waitFor

Playwright 内置了断言功能,这些断言会自动等待条件满足,因此通常不需要显式调用 waitFor/waitForElementToBeRemoved

// 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 替代。

await expect.poll(async () => {
const response = await page.request.get('https://api.example.com');
return response.status();
}).toBe(200);

替换 within

您可以通过 locator.locator() 方法在一个定位器内部创建另一个定位器。

// Testing Library
const messages = document.getElementById('messages');
const helloMessage = within(messages).getByText('hello');

// Playwright
const messages = component.getByTestId('messages');
const helloMessage = messages.getByText('hello');

Playwright Test 的超能力

一旦开始使用 Playwright Test,你将获得诸多强大功能:

  • 开箱即用的 TypeScript 零配置支持
  • 可在所有主流操作系统(Windows、macOS、Ubuntu)上运行所有浏览器引擎(Chrome、Firefox、Safari)的测试
  • 完整支持多源站、(i)frames 以及 多标签页和上下文
  • 支持多浏览器并行隔离运行测试
  • 内置测试 产物收集 功能

你还将获得这些与 Playwright Test 捆绑的 ✨ 强大工具 ✨:

延伸阅读

了解更多关于 Playwright Test 运行器的信息: