6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

CypressでMailhog上のメールを取得したい

Last updated at Posted at 2023-02-28

やりたいこと

  • E2EテストツールであるCypress上でメールフォーム等からメールを送信
  • MailHogを使ってメールの受信を確認
  • さらにメール本文内のURLを取得したい

Mailhog本体の導入は省略します。

package version
cypress 10.0.7
cypress-mailhog ^1.6.0
cypress-wait-until 1.7.2

導入

パッケージをインストール

install
npm install cypress-mailhog

Cypress内のcommand.jsで読み込む

cypress/support/commands
import 'cypress-mailhog';

mailHogUrlをCypressConfigで設定

cypress.config.ts
export default defineConfig({
    env: { 
        mailHogUrl: "http://localhost:8025/"
    },
    e2e: {
        baseUrl: 'http://localhost:8080'
    }
})

実装

例:「パスワード再設定画面で、メールアドレスを入力し送信ボタンを押すと手続きを進めるURLが記載されたメールが届く」 という流れ。

reset-sample.png
まずはコーディング。

例: /reset-password.html
<form>
  <input type="text" name="email">
  <button type="submit" data-test="btn-reset-password">送信</button>
</form>

次はE2Eテスト。画面遷移とform入力、ボタンクリック。

reset-password.cy.js
// reset-password.htmlに遷移
cy.visit('/reset-password');

// メールアドレスを入力
cy.get('input[name="email"]').type('test@aaa.com');

//再設定ボタンを押す
cy.get('[data-test="btn-reset-password"]').click();

reset-mailhog-sample.png
そしてcypress上でメールを取得。
cypress-mailhogにはコマンドが用意されており、今回は主に以下を使用する。

コマンド一例

cypress-mailhog - commands
// 全件取得(最大50)
cy.mhGetAllMails()

// 取得したうちの最新のメールを取得
cy.mhGetAllMails().mhFirst()

// MailHog上のメールを全件削除
cy.mhDeleteAll()

// 最新のメールの本文を取得
cy.mhGetAllMails().mhFirst().mhGetBody()

実際に使ってみる

Cypressでmailhog上のメールを取得する
// 取得した一覧のうち、1件目(最新)のメール本文を取得
cy.mhGetAllMails().mhFirst().mhGetBody().then((body) => {})

mailparser が使えるのを後から知る。
参考: https://github.com/SMenigat/cypress-mailhog/issues/25

mailparser でメール本文を取得

インストール
npm install mailparser -D
plugins/index.js
const parser = require('mailparser').simpleParser;
module.exports = (on, config) => {
    on('task', {
        'parse-mail': ({ mail }) => parser(mail),
    })
}

command.jsに登録

command.js
Cypress.Commands.add('mhParseMail', { prevSubject: true }, (mail) => {
  return cy.task('parse-mail', { mail: mail.Raw.Data })
})
test.cy.js
cy.mhGetAllMails().mhFirst().mhParseMail().then((res) => {
    //本文を取得しデコード
    const mailText = decodeURIComponent(escape(window.atob(_body)))

    //URLを抽出
    const urlArr = mailText.match(/((h?)(ttps?:\/\/[a-zA-Z0-9.\-_@:/~?%&;=+#',()*!]+))/g)})
})

cypress-wait-until

また、mailhogはメールが届くまでタイムラグがある可能性があるので cypress-wait-until を合わせて使用することに。
30秒間、1秒ごとに sender 宛のメールを確認し、届いていたら true が返る。(タイムアウトしたらエラーメッセージが返される。)

npm install cypress-wait-until -D

これもcommand.jsに登録

mhGetMailsBySender
Cypress.Commands.add('mhGetMailsBySender', (sender, wait=true) => {
  if(wait) {
    //Wait until there is at least one email from sender
    cy.waitUntil(() => cy.mhGetAllMails(10).then((mails) =>
      mails.filter((mail) => mail.Raw.From === sender).length > 0
    ), {
      errorMsg: `${sender} からのメールはありませんでした`,
      timeout: 30000,
      interval: 1000
    })
  }
  cy.mhGetAllMails().then((mails) => {
    return mails.filter((mail) => mail.Raw.From === sender);
  })
})

参考:https://github.com/SMenigat/cypress-mailhog/issues/11


mailparserとwait-utilを組み合わせると、こう。

test.cy.js
const userEmail = "test@aaa.com"
cy.mhGetMailsBySender(userEmail).mhFirst().then((res) => {
    const fromEmail = res.Raw.From

    //メールアドレスが一致しているかチェック
    expect(fromEmail).to.eq(_userEmail)

    //本文からURLを抽出
    const _body = res.Content.Body
    if(!_body) return
    let mailText = decodeURIComponent(escape(window.atob(_body)))
    const urlArr = mailText.match(/((h?)(ttps?:\/\/[a-zA-Z0-9.\-_@:/~?%&;=+#',()*!]+))/g)

    //以下略
  })
})

終わり

Cypressに苦戦を強いられ続けていますが、もっと効率よく上手に調べて使う力をつけなくてはと反省する日々です。先人方に圧倒的感謝。

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?