Nightwatch.js の E2E テストでメールの配信をテストする
Nightwatch.js で書いた E2E テストプロジェクトで、Mandrill と RequestBin を使ってメールの配信もテストするサンプルプロジェクトを公開しました。
ngs/nightwatch-mail-example on GitHub
このサンプルプロジェクトは Hacker News Letter を購読・購読解除を行うユーザーの操作を実行しています。
テストコードは以下の様な書き方です:
page
.navigate()
//
// Mandrill のメールルートを作成する
.createEmailRoute(email)
//
// フォーム入力
.waitForElementVisible("@form")
.clearValue("@email")
.setValue("@email", email)
.click("@submit")
//
// 完了画面に遷移
.waitForElementNotPresent("@form")
.assert.urlEquals(page.url + "almostfinished.html")
//
// 指定した件名のメールの受信を確認
.assert.receivedEmailSubjectEquals(
email,
"Hacker Newsletter: Please Confirm Subscription"
)
//
// 指定した文字列が HTML 本文に含まれるメールの受信を確認
.assert.receivedEmailHTMLBodyContains(
email,
'<a class="button" href="https://hackernewsletter.us1.list-manage.com/subscribe/confirm?u='
);
動機
弊社では最近 Nightwatch.js を製品の E2E テスト実装に導入し、とても簡単でシンプルに Web アプリケーションのテストコードを記述できるので気に入りました。。
テストコードを書いている最中、メールの受信を介したユーザーフローのテストコードを書こうと思い、Nightwatch.js を拡張して、カスタムアクションとアサージョンを実装しました。
ref: Extending Nightwatch - Nightwatch Developer Guide
導入方法
1. Mandrill の受信ドメイン (Inbound Domain) を設定する
まず、Mandrill のドキュメントを参考にして、受信用のメールドメイン (Inbound Email Domain) を設定します。
ドメインを入力し、Inbound Domains 画面の青い + Add ボタンをクリックするだけです。
ドメインを追加したら、MX Setup ポップアップに記載されている DNS レコードを追加します。
2. Mandrill の API キーを取得する
次に、Mandrill の API を設定画面から取得します。
間違えて実際にメールを誰かに送ってしまわないために、Test Key チェックボックスはオンにすることをお勧めします。
3. (任意) 自身の RequestBin を使う
配信されたメール RequestBin で他の人でも閲覧ができます。もしアプリケーションから配信されるメールを一般から閲覧できることに懸念がある場合には、自身の RequestBin を Heroku や IBM Bluexix に オープンソースの RequestBin をデプロイすることで、利用できます。
git clone git://github.com/Runscope/requestbin.git
cd requestbin
heroku create
heroku addons:add heroku-redis
heroku config:set REALM=prod
git push heroku master
4. 環境変数
サンプルプロジェクトを実行するために、上記の手順で取得した情報を環境変数に書き出します。
自分は direnv をローカル環境変数の管理に使っています:
echo "export MANDRILL_API_KEY=${YOUR_API_KEY_HERE}" >> .envrc
echo "export MAIL_DOMAIN=${YOUR_MAIL_DOMAIN_HERE}" >> .envrc
# If you set up your own RequestBin in Step 3
echo "export REQUEST_BIN_HOST=https://${YOUR_HEROKU_APP}.herokuapp.com" >> .envrc
# Allow new environment variables
direnv allow
5. NPM!
これで、npm
コマンドを使ってサンプルテストスイートを実行できます。
npm install # for first time
npm test
カスタムアサージョンとコマンド
機能拡張のファイルレイアウトは以下の様になっています:
lib
├── custom_assertions
│ ├── receivedEmailHTMLBodyContains.js
│ ├── receivedEmailSubjectContains.js
│ └── receivedEmailSubjectEquals.js
├── custom_commands
│ ├── checkEmails.js
│ ├── createEmailRoute.js
│ └── deleteEmailRoutes.js
├── globals.js
└── page_objects
└── hackernewsletter.js # example specific file
設定ファイル からそれらを指定します。
{
"custom_commands_path": "./lib/custom_commands",
"custom_assertions_path": "./lib/custom_assertions",
"page_objects_path": "./lib/page_objects",
"globals_path": "./lib/globals.js",
// snip ...
}
もっとアサージョンを追加する
サンプルプロジェクトでは receivedEmailHTMLBodyContains
, receivedEmailSubjectContains
, receivedEmailSubjectEquals
を実装しました。
もし from_email
や attachments
などの他のフィールドをテストしたい場合には、既存の実装をフォークして、アサージョンを追加することができます。 (一覧を見る)
const util = require("nightwatch/lib/util/utils");
exports.assertion = function receivedEmailSubjectEquals(
address,
expected,
msg
) {
const DEFAULT_MSG = 'Testing if <%s> received with subject equals to "%s".';
this.message = msg || util.format(DEFAULT_MSG, address, expected);
this.expected = function () {
return expected;
};
this.pass = function (value) {
const expected = this.expected();
return (
value.filter(function (email) {
return email.subject === expected;
// use indexOf(expected) !== -1 for *contains* implementation.
}).length > 0
);
};
this.value = function (result) {
return result || [];
};
this.command = function (callback) {
return this.api.checkEmails(address, callback);
};
};
もし、便利なアサージョンを実装したら、是非 リポジトリをフォーク してプルリクエストを送って頂けると幸いです!
Happy testing!