Skip to main content

Scoping Eyes Configuration

In larger projects, a single global configuration is rarely enough. Different teams may use different API keys, full-page tests may need different settings than component tests, and mobile-focused tests may need extra viewports. Because eyesConfig is a standard Playwright option fixture, you can set it at several levels of granularity and combine them.

This guide walks through each level, from the broadest to the most specific, and then explains how settings from different levels are resolved.


Global configuration​

Settings in the use section of playwright.config.ts apply to every test in the project. This is the right place for account-wide defaults such as the batch name, match level, and runner type.

playwright.config.ts
import { defineConfig } from '@playwright/test';
import type { EyesFixture } from '@applitools/eyes-playwright/fixture';

export default defineConfig<EyesFixture>({
use: {
eyesConfig: {
appName: 'My App',
type: 'ufg',
matchLevel: 'Strict',
batch: { name: 'Regression Tests' },
},
},
});

See Configuration Options for the full list of available settings.

Per Playwright project​

Playwright projects let you group tests — by file name pattern, directory, or browser — and give each group its own eyesConfig. Project settings override the global ones, key by key.

For example, you can capture full-page screenshots only in tests whose file name matches a pattern:

playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
import type { EyesFixture } from '@applitools/eyes-playwright/fixture';

export default defineConfig<EyesFixture>({
use: {
eyesConfig: {
fully: true, // global default
},
},
projects: [
{
name: 'viewport tests',
testMatch: /.*\.viewport\.spec\.ts/,
use: {
...devices['Desktop Chrome'],
eyesConfig: {
fully: false, // overrides the global default for this project only
},
},
},
],
});

Per folder or team​

To give a set of test files — for example, all tests owned by one team — their own settings, create a shared fixture file that extends the Eyes test object with its own eyesConfig:

teams/team-a/fixtures.ts
import { test as base, expect } from '@applitools/eyes-playwright/fixture';

export const test = base.extend({
eyesConfig: {
apiKey: process.env.TEAM_A_API_KEY,
batch: { name: 'Team A' },
},
});

export { expect };

Test files that import test from this fixture file instead of @applitools/eyes-playwright/fixture get these settings automatically:

teams/team-a/login.spec.ts
import { test, expect } from './fixtures';

test('login page', async ({ page, eyes }) => {
await page.goto('https://example.com/login');
await eyes.check('Login page');
});

Per file or describe block​

Use test.use() to override settings for a single spec file, or nest it inside a describe block to target only the tests in that block:

import { test } from '@applitools/eyes-playwright/fixture';

test.use({
eyesConfig: {
testName: (testInfo) => `Checkout - ${testInfo.title}`,
browsersInfo: [
{ name: 'chrome', width: 800, height: 600 },
{ name: 'firefox', width: 800, height: 600 },
],
},
});

test.describe('mobile layout', () => {
// Applies only to tests inside this describe block
test.use({
eyesConfig: {
browsersInfo: [{ name: 'chrome', width: 375, height: 667 }],
},
});

test('menu drawer', async ({ page, eyes }) => {
// ...
});
});

Dynamic configuration per test​

For settings that depend on the individual test, override eyesConfig with a fixture function. The function can read testInfo — including test tags — and other fixtures, so a single fixture file can configure each test based on how it is declared:

fixtures.ts
import { test as base, expect } from '@applitools/eyes-playwright/fixture';
import type { EyesConfig } from '@applitools/eyes-playwright/fixture';
import type { TestInfo } from '@playwright/test';

export const test = base.extend({
eyesConfig: ({ baseURL }, use, testInfo: TestInfo) =>
use({
// Capture the full page only for tests tagged @fully
fully: testInfo.tags.includes('@fully'),
browsersInfo: [
{ name: 'chrome', width: 800, height: 600 },
// Add mobile viewports for tests tagged @mobile
...(testInfo.tags.includes('@mobile')
? [
{ name: 'chrome', width: 375, height: 667 },
{ name: 'chrome', width: 768, height: 1024 },
]
: []),
],
properties: [{ name: 'baseUrl', value: String(baseURL) }],
} satisfies EyesConfig),
});

export { expect };
import { test } from './fixtures';

test('full product page', { tag: ['@fully', '@mobile'] }, async ({ page, eyes }) => {
// Runs with fully: true and the extra mobile viewports
});

How settings are resolved​

Eyes merges the configuration levels key by key, from the least to the most specific:

  1. Global eyesConfig in playwright.config.ts
  2. Project-level eyesConfig
  3. The fixture value — whatever a custom fixture (base.extend) or test.use() resolved to for the test

A key set at a more specific level wins; keys it does not set fall back to the broader levels. Setting a key to undefined does not override a value from a broader level.

Keep these details in mind:

  • The merge is per top-level key. Nested objects and arrays such as batch or browsersInfo are replaced as a whole, not merged item by item. If a project overrides batch, it replaces the entire global batch object.
  • Custom fixtures and test.use() share the third level. test.use() replaces the entire eyesConfig object a custom fixture provided — the two are not merged with each other, although both still merge on top of the global and project levels.
  • Some settings only work at the global or project level. Options that control worker-scoped behavior are read from playwright.config.ts only, and setting them with test.use() has no effect. This includes removeDuplicateTests and nlpOptions.enabled.
  • eyes.check settings win over all of them. Settings passed to an individual eyes.check call (for example matchLevel or fully) apply to that checkpoint regardless of configuration level.