CodeceptJSでよみやすいE2Eテストコードを実行

今回は[このサイト](https://hotel.testplanisphere.dev/ja/index.html)を[CodeceptJS](https://codecept.io/)でE2Eテストを実行してみます！
E2Eテストとして実行する内容はこちらです。下記の内容を実行してくれるテストコードを2つのサンプルで書いてみます!

1. [トップページ](https://hotel.testplanisphere.dev/ja/index.html)にアクセス
2. ログインページへ移動
3. 登録済みユーザでログイン
4. [登録済みデータ](https://hotel.testplanisphere.dev/ja/about.html)の情報がマイページ上に正しく表示されているかassert
5. ログイン


### サンプル1:Semantic Locatorsを使う

```mypage_test.js
const I = actor();

Feature('mypage page test');

Scenario('After logging in, member info should be displayed', () => {
    I.amOnPage("https://hotel.testplanisphere.dev/ja/index.html")
    I.clickLink("ログイン")
    I.fillField("メールアドレス", "ichiro@example.com")
    I.fillField("パスワード", "password")
    I.click("ログイン", "button[type=submit]")  //※Semantic Locatorsではない
    I.see("ichiro@example.com")
    I.see("山田一郎")
    I.see("プレミアム会員")
    I.see("東京都豊島区池袋")
    I.see("01234567891")
    I.see("男性")
    I.see("未登録")
    I.see("受け取る")
    I.click("ログアウト")
});
```

**基本的にXPathやcssセレクタを書いていない**ため、凄くシンプルでテストコードで何をしているか直感的にわかりやすく、読みやすいです。
CodeceptJSの[Semantic Locators](https://codecept.io/locators/#semantic-locators)の機能を使ってどのHTML要素であるか明示的に記載せずとも、CodeceptJSでHTML要素を推測してくれます。賢いやつですね。

賢いSemantic Locatorsですが、万能ではありません。
ログインボタンを押下するときはSemantic Locatorsを使えません。画面上で「ログイン」という文字が**「ログイン画面にいくリンク」**と**「ログインするボタン」**で混在しているためです。明示的に指定しないと「ログイン画面にいくリンク」をクリックしてしまいます。
そういうときは明示的に「ログインするボタン」の方をclickするのだと指定してあげましょう。


### サンプル2:PageObjectを使う

```mypage_test.js
const I = actor();

Feature('mypage page test');

Scenario('After logging in, member info should be displayed', ({IndexPage, LoginPage, MypagePage}) => {
    IndexPage.open()
    IndexPage.gotoLoginPage()
    LoginPage.login("ichiro@example.com", "password")
    MypagePage.mypageAssert("ichiro@example.com",
                            "山田一郎",
                            "プレミアム会員",
                            "東京都豊島区池袋",
                            "01234567891",
                            "男性", 
                            "未登録",
                            "受け取る")
    MypagePage.logout()
});
```

```index.page.js
const { I } = inject();

class IndexPage {
    constructor() {
        this.login_a = '#login-holder > a'
    }
    gotoLoginPage() {
        I.click(this.login_a)
    }
    open() {
        I.amOnPage("https://hotel.testplanisphere.dev/ja/index.html")
    }
}

module.exports = new IndexPage();
```

```login.page.js
const { I } = inject();

class LoginPage {
    constructor() {
        this.email_input = '#email'
        this.password_input = "#password"
        this.login_btn = "#login-button"
    }

    login(email, password) {
        I.fillField(this.email_input, email)
        I.fillField(this.password_input, password)
        I.click(this.login_btn)
    }
}

module.exports = new LoginPage();
```
```mypage.page.js
const { I } = inject();

class MypagePage {
    constructor() {
        this.email_p = "#email"
        this.username_p = "#username"
        this.rank_p = "#rank"
        this.address_p = "#address"
        this.tel_p = "#tel"
        this.gender_p = "#gender"
        this.birthday_p = "#birthday"
        this.notification_p = "#notification"
        this.logout_btn = '#logout-form > button'
    }

    mypageAssert(email, username, rank, address, tel, gender, birthday, notification) {
        I.seeTextEquals(email, this.email_p)
        I.seeTextEquals(username, this.username_p)
        I.seeTextEquals(rank, this.rank_p)
        I.seeTextEquals(address, this.address_p)
        I.seeTextEquals(tel, this.tel_p)
        I.seeTextEquals(gender, this.gender_p)
        I.seeTextEquals(birthday, this.birthday_p)
        I.seeTextEquals(notification, this.notification_p)
    }
    logout() {
        I.click(this.logout_btn)
    }
}

module.exports = new MypagePage();
```
サンプル1はSemantic Locatorsを使って、どのHTML要素であるかをCodeceptJS側で暗黙的に推測してくれました。しかし、**このページ**の**この要素**を選んでほしい！と明示的に記載したいときもあると思います。
そのようなときのために[PageObject](https://codecept.io/pageobjects/#pageobject)として書いたサンプルです。

- ```mypage_test.js ```はどのページでどのような処理を行っているか、```login.page.js ```、```index.pege.js ```、```mypage.page.js ```は要素を選択しているか明示してあげることがわかりやすくで読みやすくなっています。



# さいごに
他にも読みやすい書き方があると思いますが、それぞれのCodeceptJSでE2Eテストを楽しんでいただければと思います...！