Client steps
Your own cucumber step definitions run next to Decisium. A line one of them matches runs your code; every other line goes to Jev. Use them for setup the page cannot do (cookies, API login, mocks), for anything out of scope for Steps, and as the fallback when no wording works.
// steps/campaigns.steps.ts
import { Given } from "@cucumber/cucumber";
import type { BrowserContext } from "playwright";
Given("the campaigns API returns {string}", async function (this: { context: BrowserContext }, name: string) {
await this.context.route("**/api/campaigns", route => route.fulfill({ json: [{ id: 1, name, status: "Draft" }] }));
});
Scenario: The list shows what the API returns
Given the campaigns API returns "Mocked Sale"
When I click Load campaigns
Then "Mocked Sale" should be shown
Load them with --import (repeatable) or import in your configuration:
decisium run features/campaigns.feature --import steps/campaigns.steps.ts
A client step makes no model call and is not recorded in the cassette.
The World
| Property | What it is |
|---|---|
this.page |
The current tab, a Playwright Page. A popup the app opens becomes the current tab. |
this.context |
The scenario's Playwright BrowserContext. |
Client steps run after the start page has opened, so a mock covers requests made from then on (for example, by the next click).
Recipes
| Need | Code |
|---|---|
| Mock a request | this.context.route(glob, route => route.fulfill({ json })) |
| Cookies | this.context.addCookies([{ name, value, url }]), then this.page.reload() if the page already read them |
| Local storage | this.page.evaluate(([k, v]) => localStorage.setItem(k, v), [key, value]), then this.page.reload() |
| Log in through the API | await this.context.request.post(url, { data }) shares cookies with the page; then reload. Faster than the form. |
| Permissions | this.context.grantPermissions(["clipboard-read"]) |
| A second user | const other = await this.context.browser()!.newContext(), then await other.newPage(). Steps act on this.page only; drive and check the other user's page in code. |
| Wait for a request | Nothing to write: a live action waits for the requests it started (up to 5 s); on replay the next action waits for its element and a check retries until it passes. |
Hooks (Before, After, …) and anything else cucumber offers work too.