Skip to content

Cypress

Setup

Add a custom Cypress command for email polling:

typescript
// cypress/support/mailoven.ts
const API_KEY = Cypress.env("MAILOVEN_API_KEY");
const BASE = "https://mailoven.com/api/v1";

Cypress.Commands.add(
  "waitForEmail",
  (to: string, options: { subject?: string; timeout?: number } = {}) => {
    const { subject, timeout = 10_000 } = options;
    const since = Math.floor(Date.now() / 1000);

    const poll = (deadline: number): Cypress.Chainable => {
      if (Date.now() > deadline) {
        throw new Error(`Timed out waiting for email to "${to}"`);
      }

      const params = new URLSearchParams({ to, since: String(since) });
      if (subject) {
        params.set("subject", subject);
      }

      return cy
        .request({
          url: `${BASE}/emails?${params}`,
          headers: { Authorization: `Bearer ${API_KEY}` },
        })
        .then((res) => {
          if (res.body.length > 0) {
            return res.body[0];
          }
          return cy.wait(500).then(() => poll(deadline));
        });
    };

    return poll(Date.now() + timeout);
  },
);

Cypress.Commands.add("clearMailovenInbox", (to: string) => {
  return cy.request({
    method: "DELETE",
    url: `${BASE}/inbox?to=${to}`,
    headers: { Authorization: `Bearer ${API_KEY}` },
  });
});

Add the types:

typescript
// cypress/support/index.d.ts
declare namespace Cypress {
  interface Chainable {
    waitForEmail(
      to: string,
      options?: { subject?: string; timeout?: number },
    ): Chainable<{
      id: string;
      subject: string;
      body: string;
      fromAddress: string;
    }>;
    clearMailovenInbox(to: string): Chainable;
  }
}

Import in your support file:

typescript
// cypress/support/e2e.ts
import "./mailoven";

Example

typescript
// cypress/e2e/signup.cy.ts
describe("Signup flow", () => {
  const inbox = "signup-test";

  beforeEach(() => {
    cy.clearMailovenInbox(inbox);
  });

  it("sends verification email", () => {
    cy.visit("/signup");
    cy.get('input[name="email"]').type(`${inbox}@acme.mailoven.com`);
    cy.get('input[name="password"]').type("securepassword123");
    cy.get("button[type=submit]").click();

    cy.waitForEmail(inbox, { subject: "Verify" }).then((email) => {
      expect(email.subject).to.contain("Verify");

      // Extract verification link
      const match = email.body.match(/href="([^"]*verify[^"]*)"/);
      cy.visit(match![1]);
      cy.url().should("include", "/inbox");
    });
  });
});

Disposable email inboxes for every teams