MailFlatDocs
Documentation/Test frameworks & CI/Cucumber

Using MailFlat with Cucumber

Keep the mailbox out of the feature file: the scenario says a user signs up and enters the code, the step definitions do the work.

How it fits together

A feature file should read like the business rule, not like an API client. Open the inbox in a Before hook, keep the address on the world object, and let each step use it.

The feature

No mention of MailFlat: the scenario describes what a person does.
Gherkin
Feature: Signup
 
Scenario: A new user verifies their email
Given I am on the signup page
When I sign up with a fresh email address
And I enter the verification code from my inbox
Then I land on the dashboard

The step definitions

Hooks own the lifecycle so no step has to remember to clean up.
JavaScript
// features/steps/signup.steps.js
const { Before, After, When, Then } = require("@cucumber/cucumber");
const { MailFlat } = require("@mailflat/sdk");
 
const mf = new MailFlat({ apiKey: process.env.MAILFLAT_API_KEY });
 
Before(async function () {
this.inbox = await mf.create({
prefix: `cuke-${Date.now().toString(36)}`,
retentionHours: 2,
});
});
 
After(async function () {
await this.inbox?.delete();
});
 
When("I sign up with a fresh email address", async function () {
await this.page.fill("#email", this.inbox.address);
await this.page.click("#submit");
});
 
When("I enter the verification code from my inbox", async function () {
await this.page.fill("#code", await this.inbox.waitForOtp({ timeout: 60000 }));
});

Worth knowing

Cucumber's default step timeout is 5 seconds — raise it with setDefaultTimeout(70000) or the waiting step is killed early.