Guide

Cucumber without step definitions

Gherkin is supposed to be the test. In Cucumber it is only the outline: every step needs a step definition in code, and that code is a second test suite to maintain. Saffron keeps the feature file and removes that layer.

The layer people keep asking about

A feature file reads like a specification. To run it, Cucumber (and Playwright-based runners like playwright-bdd) matches each step to a function you write, usually with selectors inside. When the page changes, the step text is still right, but the code under it breaks, and someone updates it by hand.

Feature: Booking
 
Scenario: Book a room for two nights
Given I am on the rooms page
When I book the sea view room for 2 nights
Then the booking is confirmed
// steps/booking.steps.ts
Given('I am on the rooms page', async function () {
await this.page.goto('/rooms');
});
 
When('I book the sea view room for {int} nights', async function (nights) {
await this.page.getByRole('link', { name: 'Sea view' }).click();
await this.page.getByLabel('Nights').fill(String(nights));
await this.page.getByRole('button', { name: 'Book now' }).click();
});
 
Then('the booking is confirmed', async function () {
await expect(this.page.getByText('Booking confirmed')).toBeVisible();
});

The first block is what your team reads. The second is what your team maintains. Rename a button and only the second one breaks.

In Saffron, the step text is the test

You write only the first block. The first time a scenario runs, an AI agent (Claude, Codex, Antigravity or Cursor, on your own subscription) performs each step in a real browser and Saffron records what it did: the clicks, the fields, the checks, with targets by role, name and label.

  • The recording is a JSON file in git, beside your features. You review it like code; it is not hidden in a vendor's cloud.
  • Every later run replays the recording with zero AI calls and zero tokens. The AI is not in the loop on a normal run.
  • Steps you already recorded are reused. A new scenario that starts with the same steps replays them; only the new steps need the agent.
  • Plain .feature files run as they are. The .saffron format adds StepSets for shared flows, and more, when you want them.

When the page changes

A replay that no longer matches the page heals: the agent picks up from the step that failed, in the same browser, and Saffron files the repair as a proposal. A replay with no AI checks the proposal, and nothing changes until you accept it. Then steps, the assertions, are never healed by default, so a heal cannot turn a real bug green. More on that in self-healing tests that never heal assertions.

What it costs you

  • The first recording of each scenario uses your AI subscription. Replays do not.
  • Recordings are reviewed, the same way you would review step definition code, only shorter.
  • If you ever leave, saffron eject (beta) writes your recordings as Playwright Test specs you own.

Comparing options? See Saffron vs playwright-bdd, including when playwright-bdd is the better choice.

Try it on your app

npm i -D saffron-ai, then npx saffron init --examples installs a small example suite to run. Free to use, including commercially. Read the docs or watch the short videos.