[Playwright] Tips
Run playwright
A basic playwright code example:
import {test, expect} from "@playwright/test"
test("Math works", () => {
expect(1+2).toBe(2);
});
// Only run one test suit
test.only('Page demo', async ({page}) => {
await page.goto("gttps://google.com");
const searchInput = page.locator('input[title=Search]');
await searchInput.type('Hello World');
await searchInput.press('Enter');
...
})
If you run npx playwright test tests/basics.spec.ts --project=chromium --reporter=list --headed
It will
- only run basics.spec.ts file
- use chrome browser by `--project=chromium`
- open browser as well by `--headed`
It will generates report as well, to see the report:
npx playwright show-report
This is useful command, you can download the artifacts from github CI, then run the command, it will open playwright UI which you can access all kinds of information such as network, console, Before / after snapshot;
You can also run playwright in debug mode, so that you can go through each line of code one by one
npx playwright test --debug
You can also use playwright to auto generate testing code for you:
npx playwright codegen -o tests/demo.spec.ts
It open browser, you can performan testing actions, the testing code will be auto generated.
You can enable screenshot:
use: {
..
screenshot: 'only-on-failure',
video: 'on-first-retry' | 'retain-on-failure'
}
Expect
import { test, expect } from '@playwright/test';
test.beforeEach(async ({ page }) => {
await page.goto('http://localhost:3000');
});
test.describe('App', () => {
test('Logo is visible', async ({ page }) => {
const logo = page.locator('img[alt=logo]');
await expect(logo).toBeVisible();
});
test('Link should be valid', async ({ page }) => {
const link = page.locator('a', { hasText: 'Learn React' });
await expect(link).toBeVisible();
await expect(link).toHaveAttribute('href', 'https://reactjs.org');
});
});
page.locator('a', {hasText: 'Learn React'})
// hasText is useful helper methodtoBeVisible()
Visual Regression Testing
import { test, expect } from '@playwright/test';
test.beforeEach(async ({ page }) => {
await page.goto('http://localhost:3000');
});
test('Button Base', async ({ page }) => {
expect(await page.screenshot()).toMatchSnapshot('button-base.png');
});
Add threshold to config:
// playwright.config.ts
{
...
toMatchSnapshot: { threshold: 0.2 },
...
}
Update snapshot, run:
npx playwright test --update-snapshots
Selector
Page:
import type { NextPage } from 'next';
const Home: NextPage = () => {
return (
<div style={{ padding: '10px' }}>
<button data-test="submit" className='primary' type='submit'>Submit</button> <button className='secondary' type='reset'>Reset</button>
</div>
);
}
export default Home;
Test:
import { test } from '@playwright/test';
test.beforeEach(async ({ page }) => {
await page.goto('http://localhost:3000');
});
test('selectors', async ({ page }) => {
/** CSS Selector */
await page.locator('button.primary').click();
/** Explicit CSS Selector */
await page.locator('css=button.primary').click();
/** Text Selector */
await page.locator('text=submit').click();
/** Chain Selectors */
await page.locator('button >> text=Submit').click();
/** nth */
await page.locator('button >> nth=0').click();
/** data-test */
await page.locator('data-test=submit').click();
});
Page Object Model Pattern
This is the code which doesn't use page object model pattern:
As you can see, it is not so easy to understand the code.
Create a page model:
// TodoPage.ts
import { expect, Locator, Page } from '@playwright/test';
export class TodoPage {
readonly newTodoInput: Locator;
readonly todoLabels: Locator;
constructor(readonly page: Page) {
this.newTodoInput = page.locator('.new-todo');
this.todoLabels = page.locator('.view label');
}
async goto() {
await this.page.goto('https://demo.playwright.dev/todomvc');
}
async addTodo(todo: string) {
await this.newTodoInput.fill(todo);
await this.newTodoInput.press('Enter');
}
async expectTodos(todos: string[]) {
await expect(this.todoLabels).toHaveText(todos);
}
}
Testing code
import { test, expect } from '@playwright/test';
import { TodoPage } from './TodoPage';
test.beforeEach(async ({ page }) => {
await new TodoPage(page).goto();
});
test('should allow me to add todo items', async ({ page }) => {
const todoPage = new TodoPage(page);
// Create a todo
await todoPage.addTodo('buy some cheese');
// Make sure the list has the todo item
await todoPage.expectTodos(['buy some cheese']);
// Create 2nd todo.
await todoPage.addTodo('feed the cat');
// Make sure the list now has two todo items.
await todoPage.expectTodos([
'buy some cheese',
'feed the cat',
]);
});
Playwright Test Fixtures, Browser Context and Page
test('demo fixtures', async ({page, browser, browserName, context}) => {})
Use those variable, you can get more information.
Playwright Library for Browser Automation
import playwright from 'playwright';
async function main() {
/** Launch browser */
const browser = await playwright.chromium.launch({ headless: false });
/** Create a context, session */
const context = await browser.newContext();
/** Create a page, a new tab */
const page = await context.newPage();
/** Carry out actions */
await page.goto('https://google.com');
await page.locator('[title="Search"]').fill('Microsoft Playwright');
await page.locator('[title="Search"]').press('Enter');
await page.locator('#result-stats').waitFor({ state: 'visible' });
await page.screenshot({ path: './screenshots/page.png' });
/** Close the browser */
await browser.close();
}
main();
Har file
Save har file for api request:
npx playwright open --save-har=network-requests.har --save-har-glob="**/api**" http://localhost:3000
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2022-08-22 [Unit Testing Express] Test Express Mongoose model
2022-08-22 [Node.js] mongoose schema
2022-08-22 [Unit testing Express] Test Express route
2022-08-22 [VSCode] REST Client Extension
2022-08-22 [TypesScript V4] ${X | Y} - ${W | Z}
2022-08-22 [Typescript] Recursive types (JSONValue)
2022-08-22 [TypeScript] Labelled tuple type