Q25 of 42 · Playwright

Explain test.use() and when to override fixtures at the file level.

PlaywrightMidplaywrightfixturestest-useconfigmid

Short answer

Short answer: `test.use({ ... })` overrides fixture values for all tests in the current file or describe block. Use it for per-file viewport, locale, storage state, base URL, or custom fixture parameters — anywhere a whole file's tests share a setting that differs from the project default.

Detail

Fixture configuration normally comes from playwright.config.ts's use block. test.use({ ... }) lets a single spec override that for its scope:

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

test.use({
  viewport: { width: 375, height: 667 },   // mobile-sized for this file
  locale: 'fr-FR',
  storageState: 'auth-fr-user.json',
});

test('mobile + French user sees localised header', async ({ page }) => {
  await page.goto('/');
  await expect(page.getByRole('heading')).toHaveText('Bienvenue');
});

Scope: test.use() at file top affects all tests in the file. Inside a test.describe, it affects only that describe block. Inside a single test callback, you can't change fixtures — they're already injected.

Common per-file overrides:

  • Viewport for mobile-specific specs.
  • Locale for i18n testing.
  • Storage state for tests as a different user.
  • Base URL for cross-environment specs (rare; usually projects handle this).
  • Custom fixtures' parameters — a test.use({ apiKey: 'staging-key' }) to alter your fixtures' inputs.

Vs project-level overrides: a project's use block applies to every spec in the project. A spec-level test.use() overrides for that spec only. The project-level setting is the right tool for "all tests in this matrix entry"; the file-level is the right tool for "this single file is special".

Watch-out: fixtures resolved before the test starts can't be overridden mid-test. test.use must be at the file or describe top.

// EXAMPLE

mobile-checkout.spec.ts

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

// Whole-file mobile config
test.use({ ...devices['iPhone 14 Pro'] });

test('mobile checkout shows compact summary', async ({ page }) => {
  await page.goto('/checkout');
  await expect(page.getByTestId('summary-compact')).toBeVisible();
  await expect(page.getByTestId('summary-full')).not.toBeVisible();
});

test.describe('FR locale', () => {
  test.use({ locale: 'fr-FR' });

  test('shows French totals', async ({ page }) => {
    await page.goto('/checkout');
    await expect(page.getByTestId('total-label')).toHaveText('Total');
  });
});

// WHAT INTERVIEWERS LOOK FOR

Knowing the file vs describe vs test scope, common override targets (viewport, locale, storageState), and that fixtures can't change mid-test.

// COMMON PITFALL

Trying to call `test.use()` inside a `test()` callback — too late, fixtures are already resolved.