MoeMail
返回部落格

Cypress Email 測試:在 E2E 測試裡驗證 email

Cypress 很擅長操控瀏覽器,但驗證信是落在瀏覽器之外的。這篇指南替你補上 Cypress email 測試,用一個自訂指令開出拋棄式收件匣、再透過 API 讀它——它是我們開發者 email 測試指南的一部分,與 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 文件,就能把它接起來。