Saturday, May 24, 2025

Fixtures (Built-in Fixtures) in Playwright with basic example

In this example we will explore how to use built in fixture in playwright with simple example. When writing end-to-end tests with Playwright, maintaining clean, reusable, and organized code is critical. That's where fixtures come in. Fixtures in Playwright provide a powerful mechanism to manage setup and teardown logic for your tests, whether it’s launching a browser, creating a test user, or handling login. Let’s break it down.

Fixtures (Built-in Fixtures) in Playwright with basic example


What Are Fixtures in Playwright?

Fixtures are reusable components that are automatically set up before your test runs and torn down after it finishes. They can provide things like:
  • A browser or browser context
  • A logged-in state
  • Page objects
  • Custom test data
In simpler terms, fixtures are like helpers that make sure everything your test needs is ready to go — and cleaned up afterward.


Built-in Fixtures in Playwright

Playwright comes with several built-in fixtures, including:
  1. page : A new browser tab for each test. Most used fixture.
  2. browser : Provides access to the browser instance.
  3. context : An isolated browser context for each test (like a new browser profile).
  4. request : Used for API testing. Sends HTTP requests without launching a browser.
  5. testInfo : Contains metadata like test title, timeout, retries, etc.

1. page fixture

Let’s start with taking an example of page fixture, Here’s the code to explain the page fixture:

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

test('basic test', async ({ page }) => { 
  await page.goto('https://playwright.dev/'); 
  await expect(page).toHaveTitle(/Playwright/); 
});

  • The page object is a fixture provided by Playwright.
  • It’s automatically created for your test, and it represents a browser page (like a tab in Chrome or Firefox) that you can use to interact with a website.
  • { page }: Playwright gives this fixture to you inside the curly braces {}. It’s like saying, “Hey, give me a browser page to work with!”
  • You didn’t have to write code to open a browser or create a page — Playwright does that for you automatically using the page fixture.

2. browser Fixture

The browser fixture gives you access to the entire browser instance (e.g., Chrome, Firefox). You can use it to control the browser or launch multiple pages.

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

test('check browser type', async ({ browser }) => {  
  // Open a new page manually using the browser fixture
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await expect(page).toHaveTitle(/Example/);
});
If you need to control the browser directly or create multiple pages in one test.


3. context Fixture

The context fixture provides a browser context, which is like a fresh browsing session (e.g., with its own cookies, storage, etc.). It’s useful for testing things like logins or isolated sessions.

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

test('check cookies in context', async ({ context }) => {
  // "context" fixture gives you a fresh browser session
  const page = await context.newPage();
  await page.goto('https://example.com');
  
  // Add a cookie to the context
  await context.addCookies([{ name: 'myCookie', value: 'hello', domain: '.example.com', path: '/' }]);
  console.log('Cookies:', await context.cookies()); // Prints the cookies
});
To manage cookies, local storage, or test multiple user sessions without interference.


4. request Fixture

The request fixture lets you make HTTP requests (like GET or POST) directly, which is great for testing APIs alongside your webpage tests.

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

test('test an API', async ({ request }) => {
  // "request" fixture lets you send HTTP requests
  const response = await request.get('https://api.example.com/data');
  
  // Check if the API returns a successful status
  expect(response.ok()).toBe(true);
  
  // Check the response body
  const data = await response.json();
  console.log('API Response:', data);
});
To test backend APIs or mock responses without needing a browser page.


5. browserName Fixture

The browserName fixture tells you which browser your test is running in (e.g., “chromium”, “firefox”, or “webkit”). It’s handy for writing browser-specific tests.

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

test('check browser name', async ({ browserName }) => {
  // "browserName" fixture tells you the browser being used
  console.log('Running in:', browserName);
  
  if (browserName === 'chromium') {
    console.log('This is Chrome or Edge!');
  } else if (browserName === 'firefox') {
    console.log('This is Firefox!');
  }
});


Best Practices of Using Fixtures in Playwright

Using fixtures in Playwright effectively can make your tests cleaner, more maintainable, and easier to scale. Below are some best practices for using fixtures in Playwright, explained with simple examples and reasoning. These practices will help you avoid common pitfalls and get the most out of Playwright’s powerful fixture system.


Use Fixtures Only When Needed
Don’t include unused fixtures in your test signature — it keeps your code cleaner and avoids unnecessary overhead.

// Bad: Including unused fixtures
test('simple test', async ({ page, browser, context, request }) => {
  await page.goto('https://example.com'); // Only "page" is used
});

// Good: Only include what you need
test('simple test', async ({ page }) => {
  await page.goto('https://example.com');
});

Use context for Isolation
The context fixture provides a fresh browser context (e.g., separate cookies, storage). Use it when you need isolated sessions, like testing multiple users.

test('test two users', async ({ context }) => {
  const page1 = await context.newPage();
  await page1.goto('https://example.com/login');
  await page1.fill('#user', 'user1');

  // New context for a second user
  const newContext = await context.browser().newContext();
  const page2 = await newContext.newPage();
  await page2.goto('https://example.com/login');
  await page2.fill('#user', 'user2');
});
context ensures each test or user session is independent, avoiding interference (e.g., shared cookies).

Create Custom Fixtures for Reusable Setup
If you have repeated setup logic (e.g., logging in), create a custom fixture to keep your tests DRY (Don’t Repeat Yourself).

// Define a custom fixture
const { test: base } = require('@playwright/test');
const test = base.extend({
  loggedInPage: async ({ page }, use) => {
    await page.goto('https://example.com/login');
    await page.fill('#username', 'testuser');
    await page.fill('#password', 'password123');
    await page.click('button[type="submit"]');
    await use(page); // Pass the logged-in page to the test
  },
});

// Use the custom fixture
test('use logged-in page', async ({ loggedInPage }) => {
  await loggedInPage.goto('https://example.com/dashboard');
  await expect(loggedInPage).toHaveURL(/dashboard/);
});
Custom fixtures reduce duplication and make tests more readable and maintainable.

This is all about built in fixture in playwright with basic and simple example.


No comments:

Post a Comment