はじめに
普段Capybaraでのメールのテストは主にopen_email
を使っているのですが、他にメソッドがあるのか気になってコードを読んだところ、想像していたよりも色々なケースを想定した便利なメソッドがあったのでまとめてみました。(古いからかまとめている記事がなかったので、、、)
読んだコードは下記
メソッド一覧
各メソッドの説明に「メールを取得する」と記載していますが、正確にはMail::Message
クラスのインスタンスを取得するという意味です。
※コードだけでは理解が怪しい処理は動かして挙動確認もしていますが、もし処理に関して間違ったことを書いている場合はコメントでご指摘いただけるとありがたいです。
find_email(address, opts={})
-
address
を設定している場合- 設定したメールアドレスに1番最初に届いたメールを取得する。
-
opts
も設定している場合- hashには
with_subject
、with_text
、from
のkeyから1つを設定し、設定したkeyによってそれぞれ正規表現によるマッチング(=~
)でメールを取得する。 - 複数条件による絞り込みはできないようなので注意が必要。
-
address
に設定されたメールアドレスのメールボックスからマッチングされる。-
with_subject
- メールのタイトルでマッチング
-
with_text
- メールの本文でマッチング
-
from
- 送信者のメールアドレスでマッチング
-
- hashには
open_email(address, opts = {})
address
に指定したメールアドレスの最初のメールを取得する。
ops
にはfind_email
同様にタイトル(with_subject
)、本文に含む文字列(with_text
)、送信元のアドレス(from
)が指定できる。
メールを取得できなかった場合、find_email
とは異なり例外を発生させる。
エイリアスメソッドにopen_email_for
がある。
open_last_email()
全てのアドレスから1番最後に送信されたメールを取得する。
メールを取得できない場合は例外を発生させる。
open_last_email_for(address)
address
に指定したメールアドレスに1番最後に送信されたメールを取得する。
current_email(address=nil)
open_email
,open_ast_email
, open_last_mail_for
によって取得したメールを取得する。これらのopen_***
メソッドが実行されていない場合、例外を発生させる。
address
を設定する場合、設定したメールアドレスでopen_***
メソッドを実行していないと例外が発生する。
なぜopen_***
メソッドを実行していないとエラーが発生するかと言うと、current_email
ではemail_spec_hash
というプライベートメソッドを呼んでいる。
https://github.com/email-spec/email-spec/blob/main/lib/email_spec/helpers.rb#L48
email = address ? email_spec_hash[:current_emails][address] : email_spec_hash[:current_email]
email_spec_hash
では下記のようにメモ化をおこなっており、このメソッドはopen_***
メソッドから呼ばれるset_current_email
メソッドから呼ばれているため。
https://github.com/email-spec/email-spec/blob/main/lib/email_spec/helpers.rb#L94
def email_spec_hash
@email_spec_hash ||= {:read_emails => {}, :unread_emails => {}, :current_emails => {}, :current_email => nil}
end
メモ化されているのでopen_***
を使用後に同じメールを参照する場合、current_email
を使った方がおそらくパフォーマンスは良くなるはず。
visit_in_email(link_text, address = '')
link_textに指定したリンク先に遷移する。
addressが指定されている場合、find_email
を使用して1番最初に届いたメールを取得する。指定されていない場合はcurrent_email
でメールを取得する。
既にcurrent_email
の項目で説明済みですが、先にopen_***
メソッドが先に実行されていないと例外が発生する。visit_in_email
の場合もcurrent_email
を使用していて同様なので、address
を設定しない場合は注意が必要。
links_in_email(email) => Array
引数に設定したMail::Message
の本文に含まれるリンクのurlの重複なしの配列を返す。
click_email_link_matching(regex, email = current_email)
regex
に設定した正規表現に最初にマッチしたリンク先に遷移する。
email
を設定しない場合はcurrent_email
が実行されるので先にopen_***
の実行が必要。マッチするurlがない場合、例外が発生する。
下記のようにlinks_in_email
メソッドを使用して最初にtrueになったurlを取得している。
links_in_email(email).detect { |link| link =~ regex }
click_first_link_in_email(email = current_email)
email
に設定したメール本文に含まれる最初のリンク先に遷移する。
このメソッドも同様にemail
を設定しないとcurrent_email
が実行されます。
current_email_attachments(address=nil)
adress
を設定した場合、設定したメールアドレスに最初に送信されたメールの添付ファイルを取得する。設定しなかった場合は全てのメールアドレスの最初に送信されたメールの添付ファイルを取得する。添付ファイルを取得できない場合は空の配列を返す。
メソッド名にあるようにcurrent_email
が実行されるので同様に先にopen_***
メソッドの実行が必要です。
read_emails_for(address)
open_***
メソッドで既に取得されたメールの配列を取得します。取得されたメールがない場合、空の配列を返します。
unread_emails_for(address)
まだ取得されていないメールの配列を取得します。取得されていないメールがない場合、空の配列を返します。