12 Playwright Tips and Tricks

Playwright is exceptional for end-to-end testing. It can do so much, from interacting with forms to mocking server requests and a heap of other things. In this article, we’ll go over 12 tips and tricks (some you might already be aware of).

1. Parallel Testing

Playwright makes it easy to run multiple tests in parallel. This is done by creating multiple context objects, which are isolated and can run in parallel without interfering with each other. Here’s an example:

const context1 = await browser.newContext();
const context2 = await browser.newContext();

// Use Promise.all to run these operations in parallel
await Promise.all([
  context1.newPage().then(page => page.goto('https://example1.com')),
  context2.newPage().then(page => page.goto('https://example2.com'))
]);

2. Auto-Waiting

Playwright automatically waits for elements to be ready before performing actions on them. This removes the need for arbitrary sleeps or waits in your tests and makes your tests more reliable. Playwright can wait for elements to become visible, to become hidden, to contain certain text, and more:

// Click the button once it becomes visible
await page.click('text="Submit"', { state: 'visible' });

// Wait for the button to hide before proceeding with the test
await page.waitForSelector('text="Submit"', { state: 'hidden' });

// Wait for the button to contain certain text before clicking it
await page.waitForSelector('text="Submit"', { state: 'attached' });
await page.click('text="Ready to Submit"');

3. Context Options for Configurations

With Playwright, you can create multiple browser contexts with different configurations. This is useful for simulating different testing scenarios. For example, you could simulate a scenario where a user is accessing your site from a mobile device in incognito mode:

const iPhone = playwright.devices['iPhone 12'];
const context = await browser.newContext({
  ...iPhone,
  isMobile: true,
  hasTouch: true,
  colorScheme: 'dark',
  acceptDownloads: true
});
const page = await context.newPage();

4. Cross-Browser Testing

Playwright supports multiple browsers, including Chromium, Firefox, and WebKit. You can easily run your tests across all these browsers to ensure your website works correctly on each of them:

const browsers = ['chromium', 'firefox', 'webkit'];

for (let browserType of browsers) {
  const browser = await playwright[browserType].launch();
  const context = await browser.newContext();
  const page = await context.newPage();

  await page.goto('https://example.com');
  // Insert your test here

  await browser.close();
}

5. Network Interception

Playwright’s network interception feature lets you control the network traffic in your tests. You can block certain requests, stub responses, or monitor network activity. Here’s an example where we stub a response:

await page.route('\*\*/api/user', (route, request) => {
  route.fulfill({
    status: 200,
    contentType: 'application/json',
    body: JSON.stringify({ name: 'John Doe' })
  });
});

// Now when the page makes a request to '/api/user', Playwright will return the stubbed response
await page.goto('https://example.com');

6. Handling Authentication

Playwright can handle different types of authentication, including JWT tokens, cookies, or even basic HTTP authentication. Here’s an example of how to set a JWT token:

const context = await browser.newContext();

// Imagine we logged in and received a JWT token
const jwtToken = 'your-jwt-token';

// Set the JWT token in localStorage or cookies
await context.addInitScript((token) => {
  localStorage.setItem('jwt-token', token);
}, jwtToken);

// Now all pages created in this context will have the JWT token
const page = await context.newPage();

7. Tracing for Advanced Debugging

Playwright’s tracing feature gives you a detailed trace of all actions taken during a test, including network requests, JavaScript execution, and more. The trace can be viewed in Playwright’s Trace Viewer for a visual debugging experience:

await context.tracing.start({ screenshots: true, snapshots: true });
// Execute actions
await context.tracing.stop({ path: 'trace.zip' });

8. Accessibility Testing

Playwright offers built-in support for accessibility testing. You can retrieve the accessibility tree and ARIA attributes of any element on the page:

const snapshot = await page.accessibility.snapshot();
console.log(snapshot);

// You can also target a specific element
const buttonSnapshot = await page.accessibility.snapshot({ interestingOnly: false, root: await page.$('button') });
console.log(buttonSnapshot);

9. Keyboard and Mouse Actions

Playwright allows you to simulate complex user interactions, such as keyboard input, mouse movements, clicks, and scroll events:

// Type into an input field
await page.fill('.search', 'Playwright');

// Press the Enter key
await page.keyboard.press('Enter');

// Drag an element
const element = await page.$('.draggable');
const box = await element.boundingBox();
await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2);
await page.mouse.down();
await page.mouse.move(100, 0);
await page.mouse.up();

10. Evaluate Scripts in the Page Context

Playwright can execute scripts in the context of the page, which is useful for manipulating the DOM, extracting data, or testing the behaviour of your JavaScript code:

// Extract the text content of an element
const textContent = await page.$eval('.my-element', el => el.textContent);
console.log(textContent);

// Run a script in the context of the page
await page.evaluate(() => {
  // This will run in the browser context
  const element = document.querySelector('.my-element');
  element.style.backgroundColor = 'red';
});

11. Geolocation and Timezone Testing

Playwright allows you to emulate different geolocations and timezones. This can be useful for testing location- and time-specific features:

// Set geolocation
await context.setGeolocation({ latitude: 52.5200, longitude: 13.4050 });

// Set timezone
await context.setTimezoneId('Europe/Berlin');

12. Emulating Different Network Conditions

Playwright lets you emulate different network conditions, which can be useful for testing your application’s behaviour under different network conditions:

// Offline mode
await context.setOffline(true);
await page.reload();
// Check if the correct offline message is displayed

// Slow network
await page.route('\*\*', (route, request) => {
  // Add a delay before fulfilling the request
  setTimeout(() => route.continue(), 5000);
});
await page.reload();
// Check if loading indicators are displayed correctly

I hope these expanded tips and tricks provide a more comprehensive guide to the capabilities of Playwright. With these techniques, you should be able to write more robust and comprehensive tests for your web applications.