Structured spec output
A Hover spec isn't a flat dump of clicks. The deterministic translator shapes a verified session into a small architecture — readable on its own, and ready to grow as you save more flows.
What the translator emits
test.step(...)stages. Each logical step (open the form, fill credentials, verify the result) is wrapped in a namedtest.step, so the Playwright HTML report reads as stages instead of a flat action list.- Visibility-guarded interactions. Every action is wrapped so it asserts the element is visible first — UI drift fails in ~3 s with a named assertion instead of a 30 s actionability timeout.
- Popup / new-tab pairing. A click that opens a payment popup or OAuth tab
crystallises with the
Promise.all([context.waitForEvent('page'), …])pairing Playwright needs, and the subsequent steps are retargeted onto the new page — no race on replay. - A structured sidecar. Alongside
<slug>.spec.ts, Hover writes.hover/<slug>.json— the structuredSpecStep[]plus the signals the run observed. It's the machine-readable record the optimization pass reads, and it keeps the spec file itself clean.
Page Objects from repeated flows
When the same prefix (a login, a setup wizard) recurs across several saved
specs, Hover can lift it into a shared Page Object plus a Playwright
fixture, so the selectors live in one file instead of five. New specs
consume the fixture and call the method (await loginPage.login(...)) instead
of repeating the steps inline.
__vibe_tests__/
├── pages/LoginPage.ts # the lifted Page Object
├── fixtures.ts # exposes it as a fixture
└── login-and-checkout.spec.ts
Run it over your existing specs with npx hover extract.
Still plain Playwright
Everything here is standard @playwright/test — Page Objects, fixtures, and
test.step are Playwright's own primitives. The spec runs in CI with
npx playwright test, no agent and no Hover runtime in the loop.