CodeceptJSとPuppeteerでE2Eテスト（MailSlurp）

#初めに
[前回の記事](https://qiita.com/abe_n/items/117bd257519054050889)の続きです。今回はメールのテストをしてみました。
公式を参考にMailSlurpヘルパーを用いて動かします。
未解決な部分も残っていますが一旦まとめました。

#目次
- MailSlurpとは
- MailSlurpヘルパーの導入
    - わかってないけどとりあえず公式の通りに
- コードを書く
    - コード
    - 詳細
    - 疑問
- 終わり
- 参考

##MailSlurpとは
MailSlurpとは（[MailSlurp公式サイト](https://www.mailslurp.com/guides/getting-started/#create-email-addresses)より引用）
>MailSlurpは、開発者とQAテスター向けに構築されたEメールAPIです。オンデマンドで実際の電子メールアドレスを作成し、コード、テスト、またはオンラインダッシュボードから電子メールを送受信できます。

MailSlurpは電子メールをテストするために設計されたサービスです。
個人で利用する分には無料で使うことができます。

CodeceptJSで用意されているプラグイン（MailSlurpヘルパー）をインストールすることで簡単に利用できます。
CodeceptJSのMailSlurpヘルパーの詳細は[こちら](https://github.com/codeceptjs/mailslurp-helper/blob/master/README.md#waitforlatestemail)です。（以下引用）
>MailSlurpサービスを使用して電子メールをテストするためのMailSlurpヘルパー。MailSlurpは、テストごとに使い捨てのメールボックスを作成し、テスト後に削除します。



##MailSlurpヘルパーの導入
公式の手順通りにインストールしていきます。
MailSlurpでアカウントを作成、登録したメールの確認、と進むとMailSlurpにAPIキーが表示されるので保存しておきます。

次にnpmからmailslurpヘルパーをインストール、codecept.conf.jsへ追記をしていきます。

```
npm i @codeceptjs/mailslurp-helper --save-dev
```

```
//codecept.conf.js

helpers: {
    Puppeteer: {
      //省略
    },
    MailSlurp: {
      require: '@codeceptjs/mailslurp-helper',
      apiKey: 'xxxxxxxxxxxxxxxxxxxxxx' 
      // MailSlurpでコピーしたAPIキー
    },
  },
```

###わかってないけどとりあえず公式の通りに
codecept.conf.jsへの追記後、TypeScript定義を再生成？するために以下のコマンドを打つようです。
正直よくわかっていませんが公式に習います。

```
npx codeceptjs def
```


##コードを書く
ではコードを書いていきます。
今回はECサイトアプリの決済完了メールについてテストしていきます。
[こちらのサイト](https://devlog.atlas.jp/2020/09/28/3381)を参考にしました。

①テスト用のダミーのアドレスから、MailSlurpでランダムに生成した試験用アドレスに変更
②試験用アドレスで注文処理
③試験用アドレスに送られたメール文面のテスト
④テスト後に試験用アドレスからダミーのアドレスに戻す

の流れでテストしました。
JUnit5のようにテスト後に実行、な関数がないか調べたのですが
使い方がよくわからなかったのでコードの最後に書いてアドレスを戻してます
（BeforeSuiteやAfterSuite関数？）


###コード

```
Feature('メールテスト');

Scenario('test', async({ I }) => {
　// 試験用メールアドレス生成
  const mailbox = await I.haveNewMailbox();
  I.openMailbox(mailbox) //なくても動く?

  // 試験用メールアドレスに変更
  session('office', () => { 
    I.amOnPage('http://localhost:8080/'); 　　　　　 //ログイン画面へ
    I.click('ログイン'); 　　　　　　　　　　　　　　　 //ログインする
    I.fillField('メールアドレス:', 'xxxxx');
    I.fillField('パスワード:', 'xxxxx');
    I.click('ログイン');  　　　　　　　　　　　　　　　//ログイン
    I.waitForText('dummy');　　　　　　　　　　　　　　//トップ画面が表示されるまで待つ

    I.click('ユーザ情報詳細'); 
    I.click('ユーザ情報を変更する'); 
    I.fillField('メールアドレス:',mailbox.emailAddress); //試験用メールアドレスに変更
    I.click('更新');

    I.click('ログイン');  　　　　　　　　　　　　　　　//ログイン
    I.waitForText('dummy');　　　　　　　　　　　　　　//トップ画面が表示されるまで待つ
  });

　//試験用メールアドレスでログイン、注文して決済完了メールを送る
  session('user', () => { 
    I.amOnPage('http://localhost:8080/'); 
    I.click('ログイン'); 
    I.fillField('メールアドレス:', mailbox.emailAddress); 
    I.fillField('パスワード:', 'xxxxx'); 
    I.click('ログイン'); 
    I.waitForText('dummy'); 

    I.click('ダミー商品');
    I.click('カートに入れる'); 
    I.click('注文に進む'); 
    I.click('この内容で注文する');
    I.waitForText('決済が完了しました！');
  });

  //メールを受信、内容をテストする
  const email = await I.waitForLatestEmail(30);  //最新メールを取得（30秒でタイムアウト）
  I.openEmail(email);
  I.seeEmailIsFrom('アプリから送られるアドレス');  //Fromチェック
  I.seeInEmailSubject('メール件名'); 　　　　　　　//件名チェック
  I.seeInEmailBody('メール本文'); 　　　　　　　　 //本文チェック

  //変更をもとに戻す
  session('after', () => { 
    I.amOnPage('http://localhost');
    I.click('ログイン');
    I.fillField('メールアドレス:', mailbox.emailAddress); 
    I.fillField('パスワード:', 'xxxxx'); 
    I.click('ログイン'); 
    I.waitForText('dummy'); 

    I.click('ユーザ情報詳細'); 
    I.click('ユーザ情報を変更する'); 
    I.fillField('メールアドレス:','xxxxx'); 
    I.click('更新');

    I.fillField('メールアドレス:','xxxxx'); 
    I.fillField('パスワード:', 'xxxxx');
    I.click('ログイン');
    I.waitForText('dummy');
  });

});
```


###詳細
####haveNewMailbox
新しいメールボックスを作成し、開きます。
複数のメールボックスを作成し切り替えるときにopenEmailを使います。

####openEmail
メールボックスを選択して開きます。
例）I.openMailbox(mailbox1);

####emailAddress
haveNewMailboxで作成されたメールボックスのランダムに生成されたアドレス

####waitForLatestEmail
メールボックスから電子メールを返します。
待機時間はデフォルトで10秒、指定することも可能です。
例）I.waitForLatestEmail(30);

####seeEmailIsFrom
電子メールが指定されたアドレスからのものであることを確認します。

####seeInEmailSubject
現在の電子メールの件名にテキストが含まれていることを確認します。

####seeInEmailBody
現在の電子メール本文にテキストが含まれていることを確認します。

###疑問
MailSlurpについては詳しくないのですが、見たところ受信もできるようです。
文面のテストに加えてテスト時のメールを見ることができたら、と思ったのですが

>MailSlurpは、テストごとに使い捨てのメールボックスを作成し、テスト後に削除します。

とMailSlurpヘルパーの説明にあります。削除となるとできないんでしょうか

MailSlurpの方で先にランダムアドレスを生成し、そのアドレスをコードの中に書くことでMailSlurpの受信トレイにテストメールを入れることはできましたが、無料プランだとアドレスに有効期限もあるそうですし、自動テスト的にもどうなのかと。

mailslurp-clientのほうを入れる必要が出てくるんでしょうか。まだ知識が足りないです。



#終わり
MailSlurpヘルパーを用いてメールの文面の確認までテストをすることができました。

まだ良く分かっていない部分も多いですが、導入も簡単で分かりやすいのは魅力だと思います。


#参考
https://codecept.io/email/#installation

https://www.mailslurp.com/guides/creating-inboxes/

https://devlog.atlas.jp/2020/09/28/3381