Releases: Vardot/varbase-e2e
Release list
2.0.6
What's changed
One fix: smartSettle can no longer wait forever, plus a packaging fix so both CLI commands ship.
Each smartSettle stage gets its own share of the budget (#57, #58)
On any page whose network never goes idle (analytics, a chat widget, a carousel that reschedules a
timer), a step could die with cucumber's bare
Error: function timed out, ensure the promise resolves within 45000 milliseconds.
networkidle spent the whole budget, the remaining time floored to 0, and Playwright reads
timeout: 0 as "no timeout at all", so the final probe waited forever and nothing ever threw.
What it does now
- No zero timeouts. Below a 25ms floor a stage is skipped, not started, so no Playwright call
is ever handed a zero or negative timeout. - No starved stages. Each stage draws a share of the original budget (25% / 25% / 50% / 50%)
and never more than what is left, sonetworkidlecan no longer consume the AJAX / pending-timer /
DOM-quiet probe that actually decides the answer on a client-rendered page. Time a stage does not
use passes to the stages after it. - Same behaviour when a page settles. What the stages check, the signature, and "a stage timing
out is not a failure" are unchanged.
Measured with a 10s budget:
| Page | Before | After |
|---|---|---|
| A never-idle live site | still waiting at 60s (hard kill) | returned after 10.0s |
never-settles.html (new fixture) |
still waiting at 45s (hard kill) | returned after 10.0s |
element.html (settles) |
492ms | 489ms |
Both CLI commands are in the package (#60)
The bin paths lost their ./ prefix. npm 11 removes a ./bin/… entry at publish time, so 2.0.6
would otherwise have shipped without init-varbase-e2e and generate-reports.
Install: npm install --save-dev @vardot/varbase-e2e@2.0.6
2.0.5
What's changed
One fix: the Canvas editor open step no longer outlasts its own timeout under load.
The Canvas editor open step keeps to one deadline budget (#53, #54)
When I open the "<name>" Canvas page in the editor could be killed by cucumber with a bare
Error: function timed out, ensure the promise resolves within 180000 milliseconds instead of
reporting what was not ready. Its retry loop ran up to three attempts of an unbounded
page.goto plus a 45s wait for the Library toolbar, so on a slow runner the attempts outlasted
the step's own 180s timeout and the loop's error was never reached.
Observed on drupal/varbase_project CI, job varbase-e2e: [09-drupal-canvas-d], where the same
commit passed on one pipeline in 821s and failed on another whose job ran 1615s.
What the step does now
- One budget. The step timeout (now 240s) is the whole budget, with a 10s reserve kept back so
the step can always raise its own error. An attempt starts only while enough budget remains for
a useful one, so the loop can never be cut off mid-attempt. - Navigation through
gotoUrl. The shared helper gives the friendly "is the dev server up",
DNS and empty-response messages, and it is bounded by this attempt's slice of the budget. smartSettleas the readiness wait. The page is settled — DOM ready, network idle, no
pending AJAX or timers, no DOM mutation for 250ms — before the Library toolbar is probed,
rather than polling a React app that is still booting. The retry path settles too, instead of
sleeping blind.- A failure now says so. The error names the attempt count, the seconds spent and the
underlying Playwright message.
gotoUrl takes an optional third argument, {timeout, waitUntil}. Defaults are unchanged and
all six existing call sites pass two arguments, so nothing else behaves differently.
Not covered
No test was added for this, and the fix has not yet been proven against a slow CI runner — the
failure it addresses only appears under load.
2.0.4
What's changed
17 new built-in steps and one behaviour fix. 512 built-in steps across 45 step files; the bundled suite is 299 scenarios / 1,456 step executions, green on chromium.
Drimage Improved step pack (#43, #44)
A new drupal-* pack, tests/step-definitions/drupal-drimage-improved.steps.js, for the dynamic responsive images the Drimage Improved module renders — the module Varbase's default theme uses for every image. Ported out of the module's own local step file so every QA suite gets it from the package instead of copying it per project.
The steps carry no CSS selectors. The pack knows the module's formatter markup (a wrapper carrying data-drimage_improved, a <picture> with an optional WebP <source>, the <img> on an SVG placeholder, a <noscript> fallback) and its swap to a derivative under /styles/drimage_improved_*, so a tester writes the sentence and nothing else:
Then the drimage images should be rendered
And the drimage images should offer webp
And the drimage images should have a noscript fallback
And the drimage images should use lazy loading
And the drimage images should be loaded
And no drimage image should be broken
And the drimage images should be sized for the viewportThe default budget is 2 seconds, because the module exists to make images fast — a step that waits 15 or 20 seconds is hiding a problem, not tolerating one. Every step first settles the page with the harness's own BBR smart wait (networkidle plus the AJAX, pending-timer and DOM-quiet counters), so the module's setTimeout swap has fired before the assertion looks. No static sleeps anywhere.
One image is named the way a person would — by alt text, title, caption, order or number, never a class or an id:
Then the drimage image "Hero banner" should be loaded
Then the drimage image captioned "Our team in 2026" should be in a figure
Then the first drimage image should have the alt text "Hero banner"
Then the last drimage image should still be a placeholderThe qualifier is interchangeable: drimage, drimage improved, dynamic, dynamic responsive, responsive, or none.
Two things the pack learnt from running against the live demos, and now handles:
- The SVG placeholder itself decodes, so a
naturalWidthcheck alone cannot tell a placeholder from a loaded image. "Loaded" requires a real derivative URL and a decoded bitmap. - The module sets
loading="lazy"only on images it has already rendered near the viewport; deferred images and hidden slider slides carry no attribute at all. That deferral is the lazy loading, so it is not counted against the page.
Ships examples/drimage.html (the vartheme_bs5 markup, with IntersectionObserver deferral and width rounding), its derivative fixtures, a feature file, and docs/steps/drupal-drimage-improved.md.
Access assertions (#47, #48)
Three steps in navigation.steps.js replacing the five different phrasings five consuming projects had each invented for themselves:
Then I am denied access to "/admin/config" # = I should be refused "/admin/config"
Then I should be allowed "/admin/content" # = I am granted access to "/admin/content"
Then I should be denied access # = the page should be access restrictedOne notion of a refusal, four shapes — HTTP 403, HTTP 404 (used to keep a route unguessable), HTTP 200 with an access-denied page, or a redirect to the log-in form — with a failure message naming which one it saw. A scenario now asserts who the user is rather than how the site happens to be configured. The allowed half earns its place: a role that can reach nothing passes every refusal assertion on its own.
Page title assertions (#45, #46)
Then the page title should be "About Us"
Then the page title should not contain "Access denied"The <title> is the browser tab text, the bookmark name, the search-result heading and the first thing a screen reader announces — and on a Drupal site it is the head title pattern. should contain is the form for a real site, where the title carries a site name and separator a test has no business hardcoding.
HTTP status: new phrasing, and a fix (#49, #50)
Then the page should return HTTP status 404The same assertion as the response status code should be N, in the phrasing that reads as a sentence about a page. The existing step was also wrong in two ways and is fixed here: it re-requested the URL with axios outside the browser, so it carried no session cookies (an admin page the browser rendered fine answered 403, making every status assertion after a log-in unreliable) and it followed redirects (should be 301 could never pass). Both phrasings now share one handler using the browser's own context with maxRedirects: 0.
Documentation
- The Varbase E2E logo on
README.mdand the docs index (#39, #40). - The stale "DDEV Varbase E2E" subsection pointer removed from
docs/install-varbase-e2e.md, which linked outside the repository (#41, #42). - New
docs/steps/drupal-drimage-improved.md;docs/steps/navigation.mdanddocs/steps/assertion.mdextended; step counts and the bundled-suite figures refreshed acrossdocs/,AGENTS.mdandCLAUDE.md.
Verified
- CI green on the released tree.
- Full suite: 299 scenarios / 1,456 steps passed, 9m41s, chromium, against the bundled fixture server.
npx cucumber-js --dry-runclean — nothing undefined, nothing ambiguous. A separate audit matched all 2,716 JSDoc examples against all 517 registered patterns: zero examples match more than one step.- The Drimage pack run live as an anonymous visitor: demo.varbase.vardot.com 14 steps green in 5.0s; the Educare sandbox 18 steps green in 8.3s; the Horizon Aid client demo 14 of 18, where
the last drimage image should be loadedfails correctly because four images sit in hidden tab panes and the last two are carousel slides the module never renders — documented, with the advice to name images by alt text on pages with tabs or sliders.
Upgrading
npm install --save-dev @vardot/varbase-e2e@2.0.4Nothing to change in a consumer project. One thing to check: if your project defines its own the image "<selector>" should be loaded step (the drimage_improved module did), delete it — it is now ambiguous with the pack, and the pack's version takes an alt text rather than a selector.
Full changelog: 2.0.3...2.0.4
2.0.3
What's changed
- Removed the site-specific
working header/working footersteps from the package (#36, #37). Their assertions were one site's content — the varbase.com main menu, Vardot's social profile URLs and the footer logos — so they failed everywhere else and made every consumer project's own site-specific pair ambiguous. Site templates keep their own implementations (the Educare site template already does). - Step catalogue and counts updated: 493 built-in steps across 44 step files.
Full changelog: 2.0.2...2.0.3
2.0.2
Robustness fixes proven green on the Varbase Project 9.2.x pipeline (#34): the media library open verifies the dialog is really visible and re-opens once when a stacked dialog's late close tears it down; adding a basic Layout Builder section clicks the newest section's Configure link when the settings did not open by themselves; saving a section matches the submit by exact value or text ("Add section" / "Update"), off-canvas first; and pressing a button prefers the visible candidate when sticky action bars clone controls.
2.0.1
Native-click fallbacks for three actionability-starved cases seen on Varbase 9.2.x — an overlay-blocked press, visually-hidden Layout Builder container-type labels, and the media-library open button behind a stale jQuery UI overlay. Real Playwright click first so Drupal AJAX behaviors fire on the happy path; in-page native click only when actionability already failed. (#32)
2.0.0
First release of @vardot/varbase-e2e — the Vardot QA/QC team's BDD browser-automation harness, built on Playwright + Cucumber-js.
Install
npm install @vardot/varbase-e2ePostinstall scaffolds a ready-to-run test project: cucumber.js, playwright.config.ts, a sample feature and the folder layout.
What ships
- 495 built-in steps across 44 categories — plain-English Gherkin over Playwright, with smart edge-waits instead of sleeps, a named-selector registry with 26 CMS/framework presets, tester-friendly error messages, and HTML/PDF reporting.
- The Drupal and Varbase step packs (82 steps), ported from the Varbase Project suites and deduplicated across three branches: Drupal core form controls and admin surfaces, CKEditor 5, the media library, content moderation, Layout Builder sections with their form controls, Paragraphs, the Drupal Canvas editor and authoring API, and Varbase's own screens.
- A generated step catalogue under
docs/steps/— one page per category, generated from the step definitions themselves, five valid phrasings per step. - GitHub Actions CI that gates pull requests and uploads the report and failure screenshots on every run.
Verified
282 scenarios / 1,372 steps green against the bundled fixture suite. 0 duplicate patterns, 0 ambiguous pairs, every step carries its five documented examples.
Visual regression lives in the separate diffy-steps plugin, unchanged.