MoeMail
返回博客

Cypress 邮件测试:在 E2E 测试里验证邮件

Cypress 驱动浏览器很在行,可那封验证邮件偏偏在它的视野之外。这篇指南用一条自定义命令补上 Cypress 邮件测试:开一个一次性收件箱,再通过 API 读它——它是开发者邮件测试指南的一部分,与 PlaywrightSelenium 两个版本并列。

思路

每个用例开一个收件箱,驱动流程,再轮询收件箱 API 直到邮件到来。把它包进自定义命令,测试脚本就能读得很干净。

自定义命令

// cypress/support/commands.js
Cypress.Commands.add('createInbox', () => {
  return cy.request({
    method: 'POST',
    url: API + '/emails/generate',
    headers: { 'X-API-Key': Cypress.env('MAIL_KEY') },
  }).its('body')
})

Cypress.Commands.add('waitForEmail', (id, tries = 20) => {
  const poll = (n) => cy.request({
    url: API + '/emails/' + id + '/messages',
    headers: { 'X-API-Key': Cypress.env('MAIL_KEY') },
  }).then((res) => {
    if (res.body.messages.length) return res.body.messages[0]
    if (n === 0) throw new Error('no email arrived')
    cy.wait(1500)
    return poll(n - 1)
  })
  return poll(tries)
})

测试本体

it('verifies the signup email', () => {
  cy.createInbox().then((inbox) => {
    cy.visit('/signup')
    cy.get('#email').type(inbox.address)
    cy.contains('Sign up').click()
    cy.waitForEmail(inbox.id).then((msg) => {
      const code = msg.text.match(/[0-9]{6}/)[0]
      cy.get('#code').type(code)
    })
    cy.contains('Welcome').should('be.visible')
  })
})

这个递归式的 poll 既让 Cypress 的命令队列乖乖配合,又不必在固定计时器上硬等 cy.wait。同一条命令也能测找回密码邮件——只要把匹配验证码换成匹配链接就行。

小贴士

给每个用例分配自己的地址,能用 Webhook 就用,并把 CI 超时设紧。创建一个邮箱、读一读 OpenAPI 文档,就能把它接好。