Testing Magic-Link / Passwordless Login
Passwordless (magic-link) login is lovely for users and awkward for tests: there's no password to type, just a one-time link delivered by email. The good news — it's the same inbox-read pattern as everything else in email testing for developers, and a near-twin of password-reset testing.
The flow
- Provision a fresh disposable inbox and request a magic link for it.
- Read the email and pull out the sign-in URL.
- Open the URL and assert you land in an authenticated session.
Example (Playwright)
const inbox = await createInbox()
await page.goto('/login')
await page.getByLabel('Email').fill(inbox.address)
await page.getByRole('button', { name: 'Send magic link' }).click()
const msg = await waitForMessage(inbox.id, 30000)
// first http(s) URL in the email body
const link = (msg.links && msg.links[0])
|| msg.text.split(/\s+/).find(w => w.indexOf('http') === 0)
await page.goto(link)
await expect(page.getByText('Signed in')).toBeVisible()
The createInbox / waitForMessage helpers come from the Playwright tutorial; the Cypress custom commands work the same way.
Edge cases
Expired links, single-use enforcement (a second click should fail), and requesting a link for an unknown address (respond identically to avoid user enumeration). Each is a small variant of the flow above. Compare with OTP and 2FA testing when a second factor is also involved.
Get started
Create a mailbox and read the OpenAPI docs to wire the inbox calls into your suite.