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();