Playwright Expert
Overview
Expert-level mastery of Playwright — Microsoft's end-to-end testing framework for web applications. Covers browser automation, test architecture, CI/CD integration, debugging, and performance testing across Chromium, Firefox, and WebKit.
1. Core Concepts & Setup
- Playwright architecture: browser → context → page hierarchy
- Install:
npm init playwright@latestornpm i -D @playwright/test - Browser installation:
npx playwright install(chromium, firefox, webkit) playwright.config.ts— projects, baseURL, retries, reporter, timeout, workers- Running tests:
npx playwright test,--headed,--debug,--ui - Test sharding:
--shard=1/4for parallel CI runs useoptions: viewport, locale, timezone, geolocation, permissions, storageState
2. Test Authoring
test(),test.describe(),test.beforeEach(),test.afterAll()test.only(),test.skip(),test.fixme(),test.fail()test.extend()for custom fixturesexpect()assertions —toBeVisible,toHaveText,toHaveURL,toHaveValue,toBeChecked,toBeEnabled,toHaveCount,toContainText,toHaveAttribute,toHaveClass,toHaveScreenshot- Soft assertions:
expect.soft()— continue after failure expect.poll()for custom async pollingtest.step()for structured test steps (shown in reports)- Parameterized tests via
test.describe.configure({ mode: 'parallel' })
3. Locators (Modern API)
page.getByRole()— accessible role + name (preferred)page.getByText(),page.getByLabel(),page.getByPlaceholder()page.getByAltText(),page.getByTitle(),page.getByTestId()page.locator('css=...'),page.locator('xpath=...')- Chaining:
page.getByRole('list').getByRole('listitem') - Filtering:
.filter({ hasText: '...' }),.filter({ has: locator }) .first(),.last(),.nth(n),.count()locator.and(),locator.or()for combining locators- Frame locators:
page.frameLocator('iframe').getByRole(...) - Shadow DOM:
locator.locator('pierce/css')
4. Actions & Interactions
click(),dblclick(),rightClick(),tap()fill(),clear(),type(),pressSequentially()press()— keyboard keys (Enter,Tab,Escape,Control+A)hover(),focus(),blur()selectOption()— by value, label, or indexcheck(),uncheck(),setChecked()setInputFiles()— file upload (single, multiple, drag-drop)dragAndDrop(source, target)scrollIntoViewIfNeeded(),scrollTo()evaluate(),evaluateHandle()— run JS in browser contextdispatchEvent()for synthetic events
5. Navigation & Waiting
page.goto(url, { waitUntil: 'networkidle' | 'domcontentloaded' | 'load' | 'commit' })page.reload(),page.goBack(),page.goForward()page.waitForURL(),page.waitForLoadState()page.waitForSelector()(legacy), preferexpect(locator).toBeVisible()page.waitForFunction()— custom JS conditionpage.waitForTimeout()— use sparingly (anti-pattern in most cases)page.waitForResponse(),page.waitForRequest()for networklocator.waitFor({ state: 'visible' | 'hidden' | 'attached' | 'detached' })
6. Network Interception & Mocking
page.route(url, handler)— intercept and modify requestsroute.fulfill({ status, body, json, contentType })— mock responsesroute.abort()— block requestsroute.continue()— pass through with optional modificationspage.routeFromHAR(harFile)— replay recorded network trafficcontext.routeFromHAR()for context-level routingpage.on('request', cb),page.on('response', cb)— event listeners- Glob patterns:
page.route('**/api/**', ...), regex supported page.waitForResponse(urlOrPredicate)— assert specific API calls
7. Authentication & State
storageState— save/load cookies + localStorageawait context.storageState({ path: 'auth.json' }) use: { storageState: 'auth.json' }- Global setup with
globalSetupin config for one-time auth browser.newContext({ httpCredentials: { username, password } })— basic auth- Cookie management:
context.addCookies(),context.clearCookies() page.context().storageState()— extract current session
8. Fixtures & Page Object Model
- Built-in fixtures:
page,browser,context,browserName,request - Custom fixtures via
test.extend<{ myFixture: MyType }>({ ... }) - Scoped fixtures:
{ scope: 'worker' | 'test' }for performance - Page Object Model pattern:
class LoginPage { constructor(private page: Page) {} async login(user: string, pass: string) { await this.page.getByLabel('Email').fill(user) await this.page.getByLabel('Password').fill(pass) await this.page.getByRole('button', { name: 'Sign in' }).click() } } - Fixture composition — inject page objects into tests cleanly
mergeTests()for combining fixture sets across modules
9. Visual Testing & Screenshots
expect(page).toHaveScreenshot('name.png')— pixel diffexpect(locator).toHaveScreenshot()— element screenshottoHaveScreenshot({ maxDiffPixels, threshold, animations: 'disabled' })page.screenshot({ fullPage: true, clip: { x, y, width, height } })- Update snapshots:
npx playwright test --update-snapshots expect(page).toMatchAriaSnapshot()— accessibility tree snapshot
10. API Testing
requestfixture for context-level HTTP requestsconst apiContext = await playwright.request.newContext({ baseURL, extraHTTPHeaders })apiContext.get(),.post(),.put(),.delete(),.patch()await expect(response).toBeOK()response.json(),response.text(),response.body()- Combine UI + API: authenticate via API, test via UI
11. Multi-Tab, Frames & Popups
context.newPage()— open new tabpage.on('popup', popup => ...)— handle popupsPromise.all([page.waitForEvent('popup'), page.click(...)])— race patternpage.frames(),page.frame({ name | url }),page.mainFrame()page.frameLocator('iframe[name="..."]')— modern frame locator- Multiple browser contexts: isolated sessions, different users
page.on('dialog', dialog => dialog.accept())— alert/confirm/prompt
12. Mobile & Device Emulation
devicesfrom@playwright/test— iPhone, Pixel, iPad presetsuse: { ...devices['iPhone 14'] }viewport,userAgent,isMobile,hasTouch,deviceScaleFactorpage.emulateMedia({ colorScheme: 'dark', reducedMotion: 'reduce' })- Geolocation:
context.setGeolocation({ latitude, longitude }) - Permissions:
context.grantPermissions(['geolocation', 'notifications']) - Network throttling via CDP:
client.send('Network.emulateNetworkConditions', ...)
13. Debugging
npx playwright test --debug— Playwright Inspectornpx playwright test --ui— UI mode (watch mode, time travel)await page.pause()— pause in debug modePWDEBUG=1environment variableslowMooption:use: { launchOptions: { slowMo: 500 } }--trace on— record trace filesnpx playwright show-trace trace.zip— Trace Viewerpage.on('console', msg => console.log(msg.text()))— browser logspage.on('pageerror', err => ...)— uncaught exceptionstest.use({ video: 'on' })— record video on failure
14. Reporters & CI/CD
- Built-in reporters:
list,dot,line,html,json,junit,github - HTML report:
npx playwright show-report PLAYWRIGHT_JSON_OUTPUT_NAMEfor CI artifact collection- GitHub Actions:
- uses: microsoft/playwright-github-action@v1 - run: npx playwright test - uses: actions/upload-artifact@v3 with: name: playwright-report path: playwright-report/ - Docker:
mcr.microsoft.com/playwright:v1.x.x-jammy - Sharding:
--shard=1/4across matrix jobs retries: 2in config for flake mitigation
15. Advanced Patterns
test.describe.configure({ mode: 'parallel' })— parallel test suitesexpect.extend()— custom matcherspage.addInitScript()— inject script before page loadcontext.addInitScript()— context-wide script injection- Accessibility testing with
@axe-core/playwright:const accessibilityScanResults = await new AxeBuilder({ page }).analyze() expect(accessibilityScanResults.violations).toEqual([]) - CDP (Chrome DevTools Protocol):
await page.context().newCDPSession(page) browser.newPersistentContext()— persistent user data dirplaywright codegen <url>— record and generate test code- Component testing:
@playwright/experimental-ct-react(React, Vue, Svelte) page.clock.install()— control timers, Date, setTimeout
16. TypeScript Best Practices
- Full TypeScript support out of the box with
@playwright/test - Use
Locator,Page,BrowserContext,Browsertypes from'@playwright/test' PlaywrightTestConfigfor typed config- Strict mode:
use: { strictMode: true }— fail on multiple element matches expectreturn type assertions withtoPass()for polling
Core Competency Summary
- Architect scalable test suites using POM and fixtures
- Write reliable, flake-resistant tests with proper locators and waits
- Mock and intercept network traffic for isolated tests
- Perform visual regression, accessibility, and API testing
- Debug with Trace Viewer, UI mode, and Inspector
- Integrate into CI/CD pipelines with sharding and HTML reports
- Emulate mobile devices, dark mode, and geolocation
- Leverage TypeScript, custom matchers, and advanced CDP features