Pillar steps
Use VisualQ's accessibility, performance, VRT, and tracking checks directly inside Gherkin scenarios.
Pillar steps are system step definitions that bridge a Gherkin scenario
with VisualQ's quality engines. Instead of writing a custom assertion to
check accessibility or VRT, you write a natural-language Then line.
Available pillar steps
Accessibility (axe)
Then the page should pass accessibility (axe) with score >= 90
Then the page should have no critical accessibility violations
Then the element "main" should be accessibleThe bridge runs @axe-core/playwright, computes a 0-100 score, and records
the result in the scenario's pillarMetrics.
Visual regression (VRT)
Then the visual diff with baseline "checkout" should be below 0.1%
Then the visible region should match the baseline "homepage"Re-uses VisualQ's existing VRT engine. Baselines are managed in the project's VRT tab — pillar steps just consume them.
Performance (Lighthouse / Web Vitals)
Then the page should load within 2500ms (LCP)
Then the CLS should be below 0.1
Then the INP should be below 200msPerformance metrics are captured live during the scenario via injected PerformanceObservers — no extra navigation required.
Tracking / analytics
Then the analytics event "checkout_started" should fire
Then the GTM tag "GA4 - Pageview" should fire on this page
Then the tracking call should include {"event":"add_to_cart"}The bridge listens on dataLayer pushes and gtag calls during the scenario
and matches them against the Gherkin assertion.
Console
Then no console errors should be present
Then no console warnings should be present matching "deprecated"Security headers
Then the page should send a strict CSP header
Then the page should not expose "X-Powered-By"Writing your own pillar steps
If your team needs a domain-specific check (e.g. "the OneTrust banner should
disappear in under 500ms"), wrap the logic into a custom step definition with
pillarHook: 'tracking' (or another pillar) — it will appear in the library
under the same group.
// Body excerpt — has access to ctx.pillar.tracking
await ctx.pillar.tracking.assertEvent({ event: 'cookie_banner_closed' })
ctx.recordPillarMetric('cookieBannerCloseMs', closeMs)recordPillarMetric() values bubble up to the run timeline and are graphed
across runs so you can spot regressions over time.