Skip to main content

Test Automation Quick Reference

A lookup page for writing and running automated tests with Playwright and TypeScript, plus the equivalent names in other tools.

How to use this page

This page is for looking things up, not for learning from scratch. New to automation? Start with the test automation cheat sheet, which explains each idea with an exercise. For the ordered plan with projects, see the test automation learning path.

Quick Navigation​

Writing tests: Locators Β· Actions Β· Assertions Β· Annotations Β· Hooks Β· Page methods Β· Network

Framework: Folder layout Β· Config options Β· Fixture pattern Β· Environment variables

Running: CLI Β· CI snippets Β· Errors and fixes

Other tools: Selenium / Cypress / WebdriverIO


Locators​

LocatorExampleFinds
getByRolepage.getByRole('button', { name: 'Login' })By ARIA role + accessible name
getByLabelpage.getByLabel('Email')Input by its <label>
getByPlaceholderpage.getByPlaceholder('Username')Input by placeholder
getByTextpage.getByText('Products')By visible text (substring by default)
getByAltTextpage.getByAltText('Sauce Labs Backpack')Image by alt text
getByTitlepage.getByTitle('Close')By title attribute
getByTestIdpage.getByTestId('checkout')data-testid (change with testIdAttribute)
locatorpage.locator('[data-test="error"]')CSS or xpath=…
RefineExample
Exact textgetByText('Products', { exact: true })
Filter by textlocator('.card').filter({ hasText: 'Backpack' })
Filter by childlocator('.card').filter({ has: page.getByRole('button') })
Inside anothercard.getByRole('button', { name: 'Add to cart' })
Nth / first / last.nth(2), .first(), .last()
Either onea.or(b)
Botha.and(b)

Common roles: button, link, textbox, checkbox, radio, combobox (select), heading, listitem, row, cell, dialog, img, tab.

Actions​

ActionExample
Click / double / right.click(), .dblclick(), .click({ button: 'right' })
Type (replace).fill('text')
Type key by key.pressSequentially('text', { delay: 50 })
Key.press('Enter'), .press('Control+A')
Clear.clear()
Select.selectOption('hilo'), .selectOption({ label: 'Price (high to low)' })
Checkbox.check(), .uncheck(), .setChecked(true)
Hover / focus.hover(), .focus()
Upload.setInputFiles('files/photo.jpg')
Drag.dragTo(target)
Read.textContent(), .innerText(), .inputValue(), .getAttribute('href'), .allTextContents(), .count()

Assertions​

Retrying (await expect(locator)…, default timeout 5 s):

AssertionUse
toBeVisible() / toBeHidden()Shown / not shown
toBeEnabled() / toBeDisabled()Can / can't interact
toBeChecked()Checkbox/radio state
toBeFocused()Has keyboard focus
toHaveText(t) / toContainText(t)Exact / partial text (string, regex or array)
toHaveValue(v)Input value
toHaveCount(n)Number of matches
toHaveAttribute(name, v) / toHaveClass(c)Attributes
toHaveURL(u) / toHaveTitle(t)On page
toHaveScreenshot(name)Visual comparison

Non-retrying (plain values): toBe, toEqual, toMatchObject, toContain, toBeGreaterThan, toBeTruthy, toMatch(/regex/), toHaveLength(n).

Modifiers: expect(x).not.toBe…, expect.soft(x)… (keep going after a failure), expect(locator).toBeVisible({ timeout: 15_000 }), await expect.poll(() => fetchCount()).toBe(3) (retry any function).

Annotations​

AnnotationEffect
test.only(...)Run only this test (blocked in CI by forbidOnly)
test.skip(condition, 'reason')Skip, e.g. test.skip(browserName === 'webkit', 'not supported')
test.fixme('reason')Skip and mark "needs fixing"
test.fail(true, 'BUG-101')Expected to fail β€” reported as failure if it passes
test.slow()Triple the timeout
{ tag: '@smoke' } / @smoke in titleFilter with --grep
test.describe.serial(...)Run tests in a group in order (avoid; prefer independent tests)

Hooks​

test.beforeAll(async () => { /* once per worker, before the tests in this file */ });
test.beforeEach(async ({ page }) => { /* before each test */ });
test.afterEach(async ({ page }, testInfo) => { /* after each; testInfo.status tells pass/fail */ });
test.afterAll(async () => { /* once per worker, after */ });

Page methods​

MethodUse
page.goto('/path')Open a URL (relative to baseURL)
page.reload(), page.goBack(), page.goForward()Navigation
page.waitForURL(/checkout/)Wait for navigation
page.waitForResponse('**/api/cart')Wait for a network response
page.screenshot({ path, fullPage: true })Screenshot
page.setViewportSize({ width: 375, height: 812 })Change size
page.on('dialog', d => d.accept())Handle alert/confirm
page.on('console', m => …)Read console messages
page.context().storageState({ path })Save cookies + storage
page.evaluate(() => localStorage.clear())Run code in the page

Network​

await page.route('**/api/v1/fruits', r => r.fulfill({ json: [{ name: 'Mango', id: 1 }] }));   // fake response
await page.route('**/api/v1/fruits', r => r.fulfill({ status: 500, body: 'boom' })); // fake error
await page.route('**/*.{png,jpg}', r => r.abort()); // block images
await page.route('**/api/**', async r => { // change real data
const response = await r.fetch();
const json = await response.json();
await r.fulfill({ response, json: { ...json, extra: true } });
});

Folder layout​

project/
β”œβ”€β”€ playwright.config.ts
β”œβ”€β”€ src/
β”‚ β”œβ”€β”€ config/env.ts # environment values
β”‚ β”œβ”€β”€ fixtures/test.ts # custom fixtures; tests import test from here
β”‚ β”œβ”€β”€ pages/ # page objects
β”‚ β”œβ”€β”€ api/ # API clients
β”‚ └── data/ # users, builders, auth-state paths
β”œβ”€β”€ tests/
β”‚ β”œβ”€β”€ auth.setup.ts # saved login
β”‚ β”œβ”€β”€ ui/ api/ a11y/ visual/ mock/
└── .github/workflows/tests.yml

Config options​

OptionExamplePurpose
testDir'./tests'Where tests live
timeout30_000Per-test timeout (ms)
expect.timeout{ timeout: 5_000 }Web-first assertion timeout
fullyParalleltrueParallel inside files too
workers4 / '50%'Parallel processes
retriesprocess.env.CI ? 2 : 0Retries (a pass on retry = flaky)
forbidOnly!!process.env.CIFail if test.only is left in
grep / grepInvert/@smoke/Filter by title/tag
reporter[['html'], ['junit', { outputFile }]]Reports
use.baseURL'https://www.saucedemo.com'Base for goto('/')
use.trace'on-first-retry'When to record traces
use.screenshot / use.video'only-on-failure' / 'retain-on-failure'Evidence
use.testIdAttribute'data-test'Attribute for getByTestId
use.storageState'.auth/user.json'Start logged in
projects[{ name: 'chromium', use: devices['Desktop Chrome'] }]Browsers/devices/suites
projects[].dependencies['setup']Run another project first
webServer{ command: 'npm start', url: 'http://localhost:3000' }Start the app before tests

Fixture pattern​

import { test as base } from '@playwright/test';

export const test = base.extend<{ thing: Thing }>({
thing: async ({ page }, use) => {
const thing = await createThing(page); // set-up
await use(thing); // the test runs here
await thing.cleanUp(); // clean-up, runs even if the test failed
},
});
export { expect } from '@playwright/test';

Environment variables​

VariableMeaning
CISet by CI systems; used to switch retries, workers, forbidOnly
PWDEBUG=1Run with the inspector (same as --debug)
DEBUG=pw:apiLog every Playwright call
Your own (e.g. UI_BASE_URL)Read in src/config/env.ts

CLI​

CommandDoes
npm init playwright@latestCreate a project
npx playwright install [--with-deps]Download browsers (+ Linux libraries)
npx playwright testRun everything
npx playwright test path/file.spec.ts:12One file / one line
-g "title" / --grep @smoke / --grep-invert @quarantineFilter
--project=chromiumOne project
--headed / --ui / --debugWatch / UI mode / inspector
--workers=1No parallelism
--repeat-each=10Run each test 10 times (find flakiness)
--retries=2Override retries
--shard=1/3Run one third of the suite
--last-failedRe-run only the tests that failed last time
--update-snapshotsAccept new visual baselines
--listList tests without running
npx playwright show-reportOpen HTML report
npx playwright show-trace trace.zipOpen a trace
npx playwright codegen <url>Record actions into code
npx playwright merge-reports --reporter html ./blob-reportMerge sharded reports

CI snippets​

GitHub Actions β€” see the full, tested workflow in the framework guide.

GitLab CI and Jenkins below follow the same four steps (install, install browsers, run, keep the report). They are shown for structure and were not run for this page.

# .gitlab-ci.yml
tests:
image: mcr.microsoft.com/playwright:v1.63.0-noble # browsers pre-installed; match your Playwright version
script:
- npm ci
- npx playwright test --grep @smoke
artifacts:
when: always
paths: [playwright-report/]
// Jenkinsfile
pipeline {
agent { docker { image 'mcr.microsoft.com/playwright:v1.63.0-noble' } }
stages {
stage('Test') {
steps {
sh 'npm ci'
sh 'npx playwright test --grep @smoke'
}
}
}
post { always { archiveArtifacts artifacts: 'playwright-report/**', allowEmptyArchive: true } }
}

Errors and fixes​

ErrorUsual causeFix
strict mode violation: … resolved to 3 elementsLocator matches several elementsMake it specific (name, filter) or use .first() on purpose
Timeout … waiting for getByRole(…)Wrong locator, element not there yet, or wrong roleCheck in --ui / codegen; an <a> without href has no link role
Test timeout of 30000ms exceededWaiting on something that never happensRead which step; raise the timeout only for known-slow steps
Cannot find name 'process' (TypeScript)Node types missingnpm i -D @types/node and "types": ["node"] in tsconfig
test file "a.spec.ts" should not import test file "b.ts"Sharing code between test filesMove shared code to src/
browserType.launch: Executable doesn't existBrowsers not installednpx playwright install
A snapshot doesn't exist … writing actualFirst visual runReview, then --update-snapshots
Passes locally, fails in CITiming, screen size, fonts, data, secrets missingTrace from CI; same viewport; env variables set

Other tools​

TaskPlaywright (TS)Selenium (Java)CypressWebdriverIO
Open pageawait page.goto(url)driver.get(url)cy.visit(url)await browser.url(url)
Find by CSSpage.locator('#id')driver.findElement(By.cssSelector("#id"))cy.get('#id')$('#id')
Find by textpage.getByText('Hi')By.xpath("//*[text()='Hi']")cy.contains('Hi')$('span=Hi') (tag + text)
Type.fill('x').sendKeys("x").type('x').setValue('x')
Click.click().click().click().click()
Wait for visibleawait expect(l).toBeVisible()wait.until(ExpectedConditions.visibilityOf(el)).should('be.visible')await el.waitForDisplayed()
Assert textawait expect(l).toHaveText('x')assertEquals("x", el.getText()).should('have.text', 'x')await expect(el).toHaveText('x')
Screenshotpage.screenshot()((TakesScreenshot) driver).getScreenshotAs(…)cy.screenshot()browser.saveScreenshot(path)
Mock networkpage.routeProxy / DevTools (BiDi)cy.interceptbrowser.mock

Need more detail? Cheat sheet Β· Best practices Β· Learning path Β· Framework guide