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.
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:
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:
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:
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:
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:
- Global
eyesConfiginplaywright.config.ts - Project-level
eyesConfig - The fixture value — whatever a custom fixture (
base.extend) ortest.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
batchorbrowsersInfoare replaced as a whole, not merged item by item. If a project overridesbatch, it replaces the entire globalbatchobject. - Custom fixtures and
test.use()share the third level.test.use()replaces the entireeyesConfigobject 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.tsonly, and setting them withtest.use()has no effect. This includesremoveDuplicateTestsandnlpOptions.enabled. eyes.checksettings win over all of them. Settings passed to an individualeyes.checkcall (for examplematchLevelorfully) apply to that checkpoint regardless of configuration level.