Configuration file: applitools.config.js
Overview
applitools.config.js is the source of truth for project defaults.
Keep this small, explicit, and versioned. Env/CLI can override, story files can special‑case.
Link back to Integration with Storybook for a starter config.
Create this file at your repo root (or pass with --conf). Export a CommonJS object.
// applitools.config.js
/**
* @type {import('@applitools/eyes-storybook').ApplitoolsConfig}
**/
module.exports = {
apiKey: '...',
};
Core
-
apiKey: string— Your Eyes API key:module.exports = { apiKey: '...' }; -
serverUrl: string— Eyes server URL (public cloud if omitted). -
showLogs: boolean— Show SDK logs (default: false). -
exitcode: boolean— Non‑zero exit code on diffs/failures (default: true).
Startup & discovery (how Eyes finds and launches Storybook)
-
storybookUrl: string— Use a running/static SB instead of launching:module.exports = { storybookUrl: 'http://localhost:6006' };Use in CI for deterministic ports/URLs.
-
storybookPort: number,storybookHost: string— When Eyes launches SB for you:module.exports = { storybookPort: 9000, storybookHost: 'localhost' }; -
storybookConfigDir: string— Non‑default.storybookpath:module.exports = { storybookConfigDir: 'apps/docs/.storybook' }; -
storybookStaticDir: string | string[]— Mount extra static assets:module.exports = { storybookStaticDir: ['public', '../shared-assets'] }; -
showStorybookOutput: boolean— Pipe SB logs to the terminal (falseby default). -
readStoriesTimeout: number ms— Abort discovery if SB is too slow:module.exports = { readStoriesTimeout: 120000 }; -
include: string | RegExp | function— Limit which stories run (see Per‑Story → include for details):module.exports = {
include: ({ kind }) => kind.startsWith('Components/'),
}; -
variations: Array<{ queryParams?: object; properties?: Array<{name,value}> }>— Run stories with extra query params/properties (e.g., RTL vs LTR):module.exports = {
variations: [
{
queryParams: { 'eyes-variation': 'RTL' },
properties: [{ name: 'rtl', value: 'true' }],
},
],
};
Rendering & timing (how snapshots are captured & rendered)
-
viewportSize: { width, height }— Puppeteer window used to snapshot DOM (default ~{1024,600}):module.exports = { viewportSize: { width: 1280, height: 720 } }; -
browser: Target | Target[]— UFG targets (see Browsers & Devices):module.exports = {
browser: [
{ name: 'chrome', width: 1440, height: 900 },
{ name: 'firefox', width: 1024, height: 768 },
{
iosDeviceInfo: {
deviceName: 'iPhone 16',
screenOrientation: 'portrait',
},
},
],
}; -
testConcurrency: number— Parallel renders on UFG (default often50or100depending on license tier).- This is an optional setting. Set this to override your company concurrency limit, if needed.
-
navigationWaitUntil: 'load'|'domcontentloaded'|'networkidle0'|'networkidle2'— When to consider navigation done. Heavy async UI → trynetworkidle2. -
browserCacheRequests: boolean— Cache requests across stories (speed). -
sendDom: boolean— Attach DOM/CSS for rendering (defaulttrue). Rare to disable. -
visualGridOptions: object— Extra UFG flags (e.g.,polyfillAdoptedStyleSheets). -
runInDocker: boolean— Add stable Chrome flags in containerized envs. -
puppeteerOptions: object— Pass topuppeteer.launch(e.g.,executablePath). -
puppeteerExtraHTTPHeaders: object— Set extra headers before capture.
Baselines, branches & batches (how results are organized)
-
appName: string— Baseline application key. Defaults topackage.json#name:module.exports = { appName: 'ui-library' }; -
batch: { id?, name?, sequenceName?, notifyOnCompletion?, properties? }— Name/ID your run and tag it:module.exports = {
batch: {
name: process.env.CI ? `PR #${process.env.PR_NUMBER}` : 'Local run',
properties: [{ name: 'team', value: 'design-systems' }],
},
}; -
baselineEnvName: string— Name of the baseline environment. -
envName: string— Name of the execution environment. -
properties: Array<{name,value}>— Adds custom properties for each test. These show up in Test Manager, and tests can be grouped by custom properties. By default, Eyes-Storybook adds 2 custom properties for each test: the Component name and State of each component. Adding more properties via this config param will not override these two properties.. -
Branching — Control where baselines come from and compare to:
module.exports = {
branchName: 'feature/datepicker',
baselineBranchName: 'main',
parentBranchName: 'main',
compareWithParentBranch: false,
}; -
Save policy — New tests & diffs:
module.exports = {
saveNewTests: true,
saveDiffs: true,
ignoreBaseline: false,
}; -
dontCloseBatches: boolean— Keep batch open across multi‑job pipelines.
Matching & regions (what differences are considered important)
-
matchLevel: 'Strict'|'Layout'|'Content'|'IgnoreColors'— Global sensitivity.
See: Core Concepts → Match Levels. -
ignoreCaret: boolean— Ignore blinking text cursors. -
ignoreDisplacements: boolean— Treat pure movement leniently in initial view. -
Region lists — Show intent to Visual AI per area (selectors or rects):
module.exports = {
ignoreRegions: [
{ selector: '.ad' },
{ left: 10, top: 20, width: 200, height: 60 },
],
floatingRegions: [
{
selector: '.toast',
maxUpOffset: 10,
maxDownOffset: 10,
maxLeftOffset: 30,
maxRightOffset: 30,
},
],
layoutRegions: [{ selector: '.grid' }], // focus on layout/structure
strictRegions: [{ selector: '.cta' }], // highest scrutiny
contentRegions: [{ selector: '.article' }], // prefer content changes
accessibilityRegions: [
{ selector: '.a11y', accessibilityType: 'RegularText' },
],
accessibilityValidation: { level: 'AA', guidelinesVersion: 'WCAG_2_1' },
};
Responsive snapshots
layoutBreakpoints: true | number[]— Capture per width:module.exports = { layoutBreakpoints: [480, 768, 1200] };
Results output & Root Cause Analysis
-
jsonFilePath/tapFilePath/xmlFilePath— Emit results for CI parsers:module.exports = { jsonFilePath: 'artifacts/eyes-results.json' }; -
domMapping— Map hashed DOM/CSS tokens to readable names for Root Cause Analysis:module.exports = { domMapping: './dom-mapping.json' };
Hooks
runBefore({ rootEl, story })— Prep state pre‑capture (open dropdowns, etc.).runAfter({ rootEl, story })— Cleanup side‑effects post‑capture.
Practical notes
- Docker/Alpine: If Chrome won’t launch, set
runInDocker: trueor supply a knownexecutablePath. - Deterministic data: Story iframes include
?eyes-storybook=true; branch on it to freeze dates/seeds. - Interactions (
play): Eyes captures afterplaycompletes;waitBeforeCapturestarts post‑play.