Playwright Cheat Sheet (TypeScript): Commands, Locators, Assertions and Config

Everything you use daily in Playwright with TypeScript, on one page: commands, locators, actions, assertions, waits, config, fixtures, API testing, debugging and CI. Bookmark it and keep it open while you code.

Advertisement

๐Ÿ“– What You’ll Learn: CLI commands, test structure and annotations, locators, actions, assertions, waits, playwright.config.ts essentials, fixtures and page objects, API testing and network mocking, debugging and reports, a minimal CI workflow, AI tools, and the top 10 mistakes to avoid.


๐Ÿ“Œ How to Use This Cheat Sheet

A one-page reference for Playwright Test with TypeScript. Each section links to the full lesson in the Playwright Tutorial with TypeScript. To keep a copy, use your browser’s Print, Save as PDF.


โš™๏ธ Setup and CLI

npm init playwright@latest                 # new project (choose TypeScript)
npx playwright install --with-deps         # browsers + Linux dependencies
npx playwright test                        # run all tests
npx playwright test login.spec.ts:12       # one test by line
npx playwright test -g "checkout"          # by title
npx playwright test --grep @smoke          # by tag
npx playwright test --project=firefox      # one browser project
npx playwright test --headed               # visible browser
npx playwright test --ui                   # UI mode
npx playwright test --debug                # Inspector
npx playwright test --workers=4 --retries=2
npx playwright test --repeat-each=10       # find flaky tests
npx playwright test --last-failed
npx playwright test --shard=1/3 --reporter=blob
npx playwright merge-reports --reporter html ./all-blob-reports
npx playwright show-report
npx playwright show-trace trace.zip
npx playwright codegen https://example.com
npx playwright test --update-snapshots

Lessons: install, CLI commands, codegen


๐Ÿงช Test Structure

import { test, expect } from '@playwright/test';

test.describe('Cart', { tag: '@regression' }, () => {
  test.beforeEach(async ({ page }) => { await page.goto('/'); });

  test('adds an item', { tag: '@smoke' }, async ({ page }, testInfo) => {
    await test.step('add backpack', async () => { /* ... */ });
  });
});

test.only(...);  test.skip(...);  test.fixme(...);  test.slow();
test.describe.configure({ mode: 'parallel' });   // or 'serial'
test.use({ viewport: { width: 390, height: 844 } });

Lessons: first test, hooks, tags, annotations


๐ŸŽฏ Locators

LocatorExample
Rolepage.getByRole('button', { name: 'Login' })
Labelpage.getByLabel('Email')
Placeholderpage.getByPlaceholder('Username')
Textpage.getByText('Products', { exact: true })
Alt text / titlepage.getByAltText('logo'), page.getByTitle('Close')
Test idpage.getByTestId('checkout')
CSSpage.locator('#user-name'), page.locator('[data-test="error"]')
XPathpage.locator("//td[text()='Jason']/following-sibling::td[2]")
Filterpage.locator('tr').filter({ hasText: 'Jason' })
Chainpage.locator('form').getByRole('button')
Pick one.first(), .last(), .nth(2)
iFramepage.frameLocator('#frame').getByRole('button')

Lessons: locators, CSS and XPath


๐Ÿ–ฑ๏ธ Actions

await page.goto('/inventory.html');
await locator.click();                     // { button: 'right' }, { clickCount: 2 }, { modifiers: ['Shift'] }
await locator.dblclick();
await locator.fill('text');                // clear + set value
await locator.pressSequentially('abc', { delay: 100 });
await locator.press('Enter');              // 'Control+A', 'ArrowDown', 'Tab'
await locator.check();  await locator.uncheck();  await locator.setChecked(true);
await locator.selectOption({ label: 'Option 2' });
await locator.setInputFiles('data/file.pdf');
await locator.hover();
await locator.dragTo(target);
await locator.scrollIntoViewIfNeeded();
await page.keyboard.press('Escape');

Lessons: actions, alerts, popups, iframes, tabs


โœ… Assertions

AssertionUse
await expect(page).toHaveURL(/inventory/)Current URL
await expect(page).toHaveTitle('Swag Labs')Page title
await expect(locator).toBeVisible() / toBeHidden()Visibility
await expect(locator).toHaveText('Products')Exact text
await expect(locator).toContainText('locked')Partial text
await expect(locator).toHaveValue('42')Input value
await expect(locator).toHaveCount(6)Number of elements
await expect(locator).toBeChecked() / toBeEnabled() / toBeDisabled()State
await expect(locator).toHaveAttribute('href', '/cart')Attribute
await expect(locator).toHaveClass(/active/)CSS class
await expect(page).toHaveScreenshot('home.png')Visual comparison
await expect(response).toBeOK()API response 2xx
expect.soft(...)Continue after a failure
expect(value).toEqual(obj) / toMatchObject(obj)Plain values (no await)

Lessons: assertions, visual testing


โณ Waits

await expect(locator).toBeVisible({ timeout: 10_000 });   // preferred
await locator.waitFor({ state: 'hidden' });
await page.waitForURL('**/inventory.html');
await page.waitForLoadState('domcontentloaded');
const resp = page.waitForResponse(r => r.url().includes('/api/') && r.ok());
await button.click(); await resp;                        // start waiting BEFORE the action
const popup = page.waitForEvent('popup');  await link.click();  const newTab = await popup;
await expect.poll(async () => getStatus()).toBe('DONE');
// Avoid: page.waitForTimeout(5000)

Lesson: Playwright waits


๐Ÿ› ๏ธ playwright.config.ts Essentials

import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests',
  timeout: 30_000,
  expect: { timeout: 5_000 },
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 2 : undefined,
  reporter: [['list'], ['html', { open: 'never' }], ['junit', { outputFile: 'results/junit.xml' }]],
  use: {
    baseURL: process.env.BASE_URL ?? 'https://www.saucedemo.com',
    testIdAttribute: 'data-test',
    trace: 'on-first-retry',
    screenshot: 'only-on-failure',
    video: 'retain-on-failure',
  },
  projects: [
    { name: 'setup', testMatch: /.*\.setup\.ts/ },
    { name: 'chromium', use: { ...devices['Desktop Chrome'], storageState: 'playwright/.auth/user.json' }, dependencies: ['setup'] },
    { name: 'mobile', use: { ...devices['iPhone 13'] } },
  ],
});

Lessons: config file, cross-browser, mobile, login sessions


๐Ÿงฉ Fixtures and Page Objects

// Page object
export class LoginPage {
  readonly username: Locator;
  constructor(private readonly page: Page) {
    this.username = page.getByPlaceholder('Username');
  }
  async login(u: string, p: string) { /* fill + click */ }
}

// Custom fixtures
export const test = base.extend<{ loginPage: LoginPage }>({
  loginPage: async ({ page }, use) => { await use(new LoginPage(page)); },
});

// Worker-scoped fixture
account: [async ({}, use, workerInfo) => { await use('user_' + workerInfo.workerIndex); }, { scope: 'worker' }],

Lessons: POM, fixtures, custom fixtures, framework structure


๐Ÿ”Œ API Testing and Network

const res = await request.get('/posts', { params: { userId: 1 } });
await request.post('/posts', { data: { title: 'x' } });       // JSON body
await request.post('/login', { form: { email, password } });    // form body
await request.put('/posts/1', { data });  await request.patch('/posts/1', { data });
await request.delete('/posts/1');
expect(res.status()).toBe(200);  const body = await res.json();

await page.route('**/api/items', r => r.fulfill({ json: [] }));              // mock
await page.route('**/api/items', async r => { const resp = await r.fetch(); await r.fulfill({ response: resp, json: { ...(await resp.json()), extra: 1 } }); });
await page.route('**/*.{png,jpg}', r => r.abort());                            // block
page.on('console', m => console.log(m.text()));

Lessons: API testing, network mocking


๐Ÿ“ธ Debugging, Screenshots and Reports

await page.pause();                                        // open Inspector (headed)
await page.screenshot({ path: 'shot.png', fullPage: true, mask: [locator] });
await locator.screenshot({ path: 'element.png' });
await testInfo.attach('data', { body: JSON.stringify(obj), contentType: 'application/json' });
console.log(testInfo.retry, testInfo.workerIndex, testInfo.tags);

Lessons: debugging, Trace Viewer, screenshots and videos, reporters


๐Ÿš€ CI in One Minute (GitHub Actions)

- uses: actions/checkout@v4
- uses: actions/setup-node@v4
  with: { node-version: lts/* }
- run: npm ci
- run: npx playwright install --with-deps
- run: npx playwright test
- uses: actions/upload-artifact@v4
  if: always()
  with: { name: playwright-report, path: playwright-report/ }

Lessons: parallel and sharding, GitHub Actions, Jenkins, Docker


๐Ÿค– AI Tools

claude mcp add playwright npx @playwright/mcp@latest     # Playwright MCP in Claude Code
npx playwright init-agents --loop=vscode                 # planner, generator, healer agents

Lessons: Playwright MCP, Test Agents


๐Ÿšซ Top 10 Mistakes to Avoid

  1. Missing await before actions and web-first assertions.
  2. page.waitForTimeout() instead of waiting for a condition.
  3. expect(await locator.textContent()) instead of await expect(locator).toHaveText().
  4. force: true to “fix” covered elements.
  5. Long CSS or absolute XPath selectors.
  6. Tests that depend on each other or share data.
  7. Logging in through the UI in every test instead of storageState.
  8. Selectors and URLs hard-coded inside tests.
  9. Committing test.only, page.pause() or secrets.
  10. Raising retries instead of fixing flaky tests.

โ“ FAQ

๐Ÿค” Is there a Playwright cheat sheet PDF?

Use your browser’s Print, Save as PDF on this page to keep an offline copy. The page is updated as Playwright evolves.

๐Ÿค” What are the most important Playwright commands to remember?

npx playwright test with -g, --grep, --project, --headed, --ui and --debug, plus show-report, show-trace and codegen.

๐Ÿค” Which Playwright locators should I memorize first?

getByRole, getByLabel, getByPlaceholder, getByText, getByTestId, and locator() with filter for everything else.


๐ŸŽฏ Next Steps

๐ŸŽฌ Watch the full Playwright tutorial series on YouTube!

Subscribe to SqaToolsByDY • Practice on sqatools.in

Leave a Comment