Custom Steps
Letsrunit ships with built-in steps from @letsrunit/cucumber, but you can add your own step definitions for project-specific behavior.
Using custom steps
Create a file such as features/support/custom-steps.js. Cucumber loads files in features/support/**/*.js automatically, so you do not need to register the file anywhere.
import { Then, When } from '@letsrunit/cucumber';
When('I open the profile menu', async function () {
await this.page.getByRole('button', { name: 'Profile' }).click();
});
Then('I should see the signed-in email {string}', async function (email) {
await this.page.getByText(email, { exact: true }).waitFor();
});
this.page is the Playwright page provided by Letsrunit's world setup.
Use the step in your feature:
Scenario: Open account menu
Given I'm on page "/dashboard"
When I open the profile menu
Then I should see the signed-in email "user@example.com"
Playwright helper functions
Importing @letsrunit/playwright gives you access to robust helpers used by the built-in steps.
fuzzyLocator(page, selector)
Finds an element using Playwright selectors with built-in fallbacks. It's more resilient than page.locator() as it attempts to relax role/name filters if a direct match isn't found.
import { fuzzyLocator } from '@letsrunit/playwright';
const button = await fuzzyLocator(this.page, 'button[name="Submit"]');
await button.click();
setFieldValue(el, value, options?)
A powerful helper that sets the value of an input element. It automatically detects the type of field (native input, checkbox, radio group, select, or custom ARIA components) and applies the correct interaction.
import { fuzzyLocator, setFieldValue } from '@letsrunit/playwright';
const input = await fuzzyLocator(this.page, 'field="Email"');
await setFieldValue(input, 'user@example.com');
waitForIdle(page) and waitForDomIdle(page)
Use these to wait for the application to settle.
waitForIdle: Waits for bothdomcontentloadedandnetworkidle.waitForDomIdle: Waits until the DOM hasn't changed for a short period (default 500ms). Useful for SPAs with ongoing background network activity wherenetworkidlemight never trigger.
import { waitForDomIdle } from '@letsrunit/playwright';
await this.page.click('.save-button');
await waitForDomIdle(this.page);
scrollToCenter(locator)
Scrolls an element into the center of the viewport.
import { fuzzyLocator, scrollToCenter } from '@letsrunit/playwright';
const footer = await fuzzyLocator(this.page, 'footer');
await scrollToCenter(footer);
Tips
- Keep custom steps domain-specific. Reuse built-in Letsrunit steps for common actions.
- Prefer clear, business-readable wording over implementation details.
- If several scenarios share the same setup, move it to
Background.