@assertkit/cypress
v0.4.0
Published
Cypress commands for AssertKit — wait for OTP / magic-link / verification-URL email flows without flake.
Downloads
1,128
Maintainers
Readme
@assertkit/cypress
Cypress commands for AssertKit — wait for OTP, magic-link, and verification-URL email flows without flake.
// cypress/e2e/signup.cy.ts
describe("signup", () => {
it("verifies via emailed OTP", () => {
cy.uniqueInbox().then((inbox) => {
cy.visit("/signup");
cy.get('input[name="email"]').type(inbox.address);
cy.get('button[type="submit"]').click();
cy.contains("Check your email").should("be.visible");
cy.waitForOtp(inbox.local, { from: "noreply" }).then((otp) => {
cy.get('input[name="otp"]').type(otp);
cy.get('button[name="verify"]').click();
cy.url().should("include", "/dashboard");
});
});
});
});Why
Most Cypress suites have a flaky cy.wait(5000) + manual API polling helper for OTP flows. This package replaces it with a single cy.waitForOtp(local) command that long-polls the AssertKit wait endpoint and resolves the moment a matching message arrives.
- No polling glue. One HTTP call returns when the email lands, up to 25s.
- No body parsing. OTPs, magic links, and verification URLs are extracted server-side. Your test gets the value.
- Parallel-safe by default.
cy.uniqueInbox()generates per-test addresses so Cypress shards never collide. - Free to try. No signup required — the commands work out of the box against
assertkit.com's free public surface.
Install
npm install --save-dev @assertkit/cypress
# or
pnpm add -D @assertkit/cypress
# or
yarn add -D @assertkit/cypressRegister the commands in your Cypress support file:
// cypress/support/commands.ts (or cypress/support/e2e.ts)
import "@assertkit/cypress";That's the entire setup. Every spec now has cy.waitForOtp, cy.waitForMagicLink, cy.waitForVerificationUrl, cy.waitForMessage, and cy.uniqueInbox.
Commands
cy.uniqueInbox(prefix?)
Generates a fresh disposable inbox for the current test. Returns { local, address }.
cy.uniqueInbox().then((inbox) => {
// inbox.local → "test-1717340000000-a1b2"
// inbox.address → "[email protected]"
});
// optional prefix
cy.uniqueInbox("signup").then((inbox) => {
// inbox.local → "signup-1717340000000-a1b2"
});cy.waitForOtp(local, opts?)
Long-polls for the next OTP-style code. Returns the extracted code value as a string.
cy.waitForOtp("test-user").then((otp) => {
cy.get('input[name="otp"]').type(otp);
});
// with filters
cy.waitForOtp("test-user", {
from: "[email protected]",
subjectContains: "verify",
timeoutMs: 30_000,
});Throws if no message arrives before the timeout (default 25s), or if a message arrives but no OTP could be extracted.
cy.waitForMagicLink(local, opts?)
Same shape as waitForOtp but resolves to the full magic-link URL.
cy.waitForMagicLink("test-user").then((url) => cy.visit(url));cy.waitForVerificationUrl(local, opts?)
Broader than waitForMagicLink — matches any link the parser tagged as a verification surface (button links, "confirm" links, etc.).
cy.waitForMessage(local, opts?)
Returns the full message metadata when you want to assert on the email itself:
cy.waitForMessage("test-user", { from: "noreply" }).then((msg) => {
expect(msg.subject).to.include("Verify your email");
expect(msg.from_addr).to.equal("[email protected]");
});Configuration
Set these in your cypress.config.ts env block (all optional):
import { defineConfig } from "cypress";
export default defineConfig({
env: {
ASSERTKIT_API_KEY: process.env.ASSERTKIT_API_KEY, // higher rate limits + webhooks
ASSERTKIT_BASE_URL: process.env.ASSERTKIT_BASE_URL, // self-hosted override
ASSERTKIT_DOMAIN: process.env.ASSERTKIT_DOMAIN, // BYO custom domain
},
});Defaults: hosted https://assertkit.com on the free public API.
TypeScript
Fully typed. The cy.waitForOtp etc. commands appear in autocomplete after import. Helper types are exported:
import type { WaitMessage, WaitFilters, AssertKitInbox } from "@assertkit/cypress";License
MIT — see LICENSE.
