Playwright 脚本
基础导航与交互
import { test, expect } from '@playwright/test';
test('登录流程', async ({ page }) => {
await page.goto('https://example.com/login');
await page.goto('https://example.com', { waitUntil: 'networkidle' });
await page.fill('#email', '[email protected]');
await page.fill('[name="password"]', 'secret123');
await page.selectOption('select#role', 'admin');
await page.check('#rememberMe');
await page.click('button[type="submit"]');
await page.keyboard.press('Enter');
});
选择器
// CSS 选择器
page.locator('#submit-btn');
page.locator('input[type="email"]');
// ARIA 角色(推荐)
page.getByRole('button', { name: '提交' });
page.getByRole('textbox', { name: '邮箱' });
page.getByLabel('密码');
page.getByTestId('submit-button');
// 链式过滤
page.locator('.card').filter({ hasText: '张三' });
page.locator('li').nth(2);
等待策略
// 自动等待 — 大多数操作自动等待元素可用
await page.click('#submit');
await page.waitForSelector('.modal', { state: 'visible' });
await page.waitForURL('**/dashboard');
await page.waitForLoadState('networkidle');
// expect 自动等待
await expect(page.locator('.success')).toBeVisible({ timeout: 5000 });
await expect(page.locator('#count')).toHaveText('3');
截图与录制视频
// 手动截图
await page.screenshot({ path: 'screenshot.png' });
await page.screenshot({ path: 'full.png', fullPage: true });
// playwright.config.ts — 失败时自动保留
export default {
use: {
screenshot: 'only-on-failure',
video: 'retain-on-failure',
trace: 'on-first-retry',
},
};
// 查看追踪文件
// npx playwright show-trace trace.zip
测试 Fixtures
import { test as base } from '@playwright/test';
export const test = base.extend({
loggedInPage: async ({ page }, use) => {
await page.goto('/login');
await page.fill('#email', '[email protected]');
await page.fill('#password', 'testpass');
await page.click('[type="submit"]');
await page.waitForURL('**/dashboard');
await use(page);
},
});
// 使用
test('管理员查看用户', async ({ loggedInPage }) => {
await loggedInPage.goto('/admin/users');
await expect(loggedInPage.getByRole('table')).toBeVisible();
});
playwright.config.ts 概览
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
timeout: 30_000,
retries: process.env.CI ? 2 : 0,
use: {
baseURL: 'http://localhost:3000',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'mobile', use: { ...devices['iPhone 13'] } },
],
});