E2Eテストの始め方 TestCafe④ -formテストについて-

[E2Eテストの始め方 TestCafe① -導入編-](https://qiita.com/natsu_mikan/items/8f623ce3b0f518432bbf)
[E2Eテストの始め方 TestCafe② -セレクタについて-](https://qiita.com/natsu_mikan/items/c02ad4761670f7e61856)
[E2Eテストの始め方 TestCafe③ -スクリーンショット編-]
(https://qiita.com/natsu_mikan/items/60b51a0d87dcc98e7e9b)

今回はTestcafeでCVポイント(formなど)テストを行う際に使える各メソッド、オプションについて書いていきたいと思います！
TestControllerオブジェクトのメソッドをいくつかピックアップしました。
**クリック**→**テキストを入力** or **チェックボックスやセレクトボックスを選択**→**送信！！**
のように基本的な項目入力と送信の動作は以下のメソッドで行うことができます。

その他のメソッドについては[公式](https://devexpress.github.io/testcafe/documentation/reference/test-api/testcontroller/)をご覧ください。

#クリックアクションメソッド

クリックアクションメソッド共通パラメーター

| パラメータ | type | 説明 |
|:-----------|:------------|:------------|
|selector|Function / String / Selector / Snapshot / Promise|クリックされたページ要素を識別します。[対象となる要素の選択](https://devexpress.github.io/testcafe/documentation/reference/test-api/testcontroller/click.html#select-target-elements)を参照してください。|
| options     | Object      | アクションに追加のパラメータを提供するオプションのセット[。オプション](https://devexpress.github.io/testcafe/documentation/reference/test-api/testcontroller/click.html#options)を参照。|


##`t.click`メソッド
その名の通り、要素をクリックするためのメソッドです。

`t.click( selector [, options] )`


次の例では、t.clickアクションを使用してチェックボックス要素をチェックする方法を示しています。

```
const checkbox = Selector('#testing-on-remote-devices');

fixture `My fixture`
　.page `http://www.example.com/`;

test('Click a check box and check its state', async t => {
　await t
　　.click(checkbox)
　　.expect(checkbox.checked).ok();
});
```

##`t.doubleClick`メソッド
要素をダブルクリックするためのメソッドです。

`t.doubleClick( selector [, options] )`

##`t.rightClick`メソッド
要素を右クリックするためのメソッドです。
`t.rightClick( selector [, options] )`


###オプション
以下のオプションは、`t.click`、`t.doubleClick`、`t.rightClick`アクションに対し追加パラメーターを提供してくれます。

```
{
    modifiers: {
        ctrl: Boolean,
        alt: Boolean,
        shift: Boolean,
        meta: Boolean
    },

    offsetX: Number,
    offsetY: Number,
    caretPos: Number,
    speed: Number
}
```


| パラメータ | type | 説明 |デフォルト|
|:-----------|:------------|:------------|:------------|
|ctrl<br>alt<br>shift<br>meta|Boolean|マウス操作中に押すべき修飾キーを示します。|false|
|offsetX<br>offsetY|Number|アクションが実行されるか開始される点を定義するマウスポインターの座標。<br>オフセットが正の整数の場合、座標は対象要素の左上隅を基準に計算されます。オフセットが負の整数の場合は、右下隅を基準に計算されます。|対象となる要素の中心|
|caretPos|Number|テキスト入力フィールドに対してアクションを実行した場合の最初のキャレット位置。ゼロベースの整数|入力フィールドの長さ|
|`speed`|Number|アクション エミュレーションの速度。<br>テストを実行するときにアクションを実行する速度を定義します。`1（最高速度）`と`0.01（最低速度）`の間で数値を指定します。CLI、API、またはテストコードでもテスト速度が指定されている場合、アクション速度設定はテスト速度よりも優先されます。|1|



#ドラッグメソッド
ドラッグメソッド共通パラメーター

| パラメータ | type | 説明 |
|:-----------|:------------|:------------|
|selector|Function / String / Selector / Snapshot / Promise|ドラッグするウェブページの要素を識別します。[対象となる要素の選択](https://devexpress.github.io/testcafe/documentation/reference/test-api/testcontroller/drag.html#select-target-elements)を参照してください。|
|options|Object|アクションに追加のパラメータを提供するオプションのセット。[オプション](https://devexpress.github.io/testcafe/documentation/reference/test-api/testcontroller/click.html#options)を参照。|

##`t.drag`メソッド
指定したオフセットに要素をドラッグするメソッドです。
`t.drag( selector, dragOffsetX, dragOffsetY [, options] )`

| パラメータ | type | 説明 |
|:-----------|:------------|:------------|
|dragOffsetX|Number|マウスポインタの初期位置からのドロップ座標のXオフセット。|
|dragOffsetY|Number|マウスポインタの初期位置からのドロップ座標のYオフセット。|

次の例は、`t.drag`アクションをスライダーで使用する方法を示しています。

```
const slider = Selector('#developer-rating');

fixture `My fixture`
　.page `http://www.example.com/`;

test('Drag slider', async t => {
　await t
　　.click('#i-tried-testcafe');
　　.expect(slider.value).eql(1)
　　.drag('.ui-slider-handle', 360, 0, { offsetX: 10, offsetY: 10 })
　　.expect(slider.value).eql(7);
});
```

##`t.dragToElement`メソッド
指定した要素を別の要素へドラッグするメソッドです。

`t.dragToElement( selector, destinationSelector [, options] )`

| パラメータ | type | 説明 |
|:-----------|:------------|:------------|
|destinationSelector|Function / String / Selector / Snapshot / Promise|ドロップの場所として機能するWebページ要素を識別します。[対象となる要素の選択](https://devexpress.github.io/testcafe/documentation/reference/test-api/testcontroller/drag.html#select-target-elements)を参照してください。|

`t.dragToElement`アクションを使って、特定の領域に要素をドロップするサンプルです。

```
const designSurfaceItems = Selector('.design-surface').find('.items');

test('Drag an item from the toolbox', async t => {
    await t
        .dragToElement('.toolbox-item.text-input', '.design-surface')
        .expect(designSurfaceItems.count).gt(0);
});
```

#`t.hover`メソッド
要素をホバーするメソッドです。

| パラメータ | type | 説明 |
|:-----------|:------------|:------------|
|selector|Function / String / Selector / Snapshot / Promise|クリックされたページ要素を識別します。[対象となる要素の選択](https://devexpress.github.io/testcafe/documentation/reference/test-api/testcontroller/click.html#select-target-elements)を参照してください。|
| options     | Object      | アクションに追加のパラメータを提供するオプションのセット[。オプション](https://devexpress.github.io/testcafe/documentation/reference/test-api/testcontroller/click.html#options)を参照。|



#`t.pressKey`メソッド
指定したキーボードのキーを押すメソッドです。

`t.pressKey( keys [, options] )`

| パラメータ | type | 説明 |
|:-----------|:------------|:------------|
|keys|String|押されるキーとキーの組み合わせのシーケンス。|
|options|Object|アクションに追加のパラメータを提供するオプションのセット。[オプション](https://devexpress.github.io/testcafe/documentation/reference/test-api/testcontroller/presskey.html#options)を参照|

以下の表は、異なるタイプのキー、キーシーケンス、および組み合わせのキーを指定する方法を示しています。

| キータイプ | 例 |
|:-----------|:------------|
|英数字キー|`a`,`A`,`1`|
|モディファイアキー| `shift`,`alt`(macOSの⌥キー),`ctrl`,`meta`(Linuxのmetaキー、macOSの⌘キー)|
|ナビゲーションとアクションキー|`backspace`,`tab`,`enter`|
|キーの組み合わせ|`shift+a`,`ctrl+d`|
|連続したキーの押下|上記のいずれかをスペースで区切った文字列、例：`a ctrl+b`|

以下のナビゲーションキーとアクションキーがサポートされています。

`backspace`
`tab`
`enter`
`capslock`
`esc`
`space`
`pageup`
`pagedown`
`end`
`home`
`left`
`right`
`up`
`down`
`ins`
`delete`

※`ctrl+c`,`ctrl+v`はエミュレートされず、`ctrl++`,`ctrl+-`は実行されません。
※`backspace`,`delete`,`left`,`right`キーは、テキストが選択されている場合にのみ処理されます。

```
test('Key Presses', async t => {
　await t
　　.typeText(nameInput, 'Peter Parker')
　　.pressKey('home right . delete delete delete delete')
　　.expect(nameInput.value).eql('P. Parker');
});
```

###オプション
```
{
　speed: Number
}
```
| パラメータ | type | 説明 |
|:-----------|:------------|:------------|
|`speed`|Number|アクション エミュレーションの速度。<br>テストを実行するときにアクションを実行する速度を定義します。`1（最高速度）`と`0.01（最低速度）`の間で数値を指定します。CLI、API、またはテストコードでもテスト速度が指定されている場合、アクション速度設定はテスト速度よりも優先されます。|1|


#`t.typeText`メソッド
指定されたテキストを入力要素に入力するメソッドです。

`t.typeText( selector, text [, options] )`

| パラメータ | type | 説明 |
|:-----------|:------------|:------------|
|selector|Function / String / Selector / Snapshot / Promise|入力フォーカスを受け取るウェブページ要素を指定します。[対象となる要素の選択](https://devexpress.github.io/testcafe/documentation/reference/test-api/testcontroller/typetext.html#select-target-elements)を参照してください。|
|text|String|指定した要素に入力するテキスト|
| options     | Object      | アクションに追加のパラメータを提供するオプションのセット。[オプション](https://devexpress.github.io/testcafe/documentation/reference/test-api/testcontroller/click.html#options)を参照。<br>このパラメータを省略すると、TestCafe は入力前にカーソルをテキストの最後に設定します。これにより、すでに入力ボックスにあるテキストが保持されます。|

※ `t.typeText`アクションは、指定された要素がフォーカスされていない場合、テキストがタイプされる前に指定された要素をクリックします。クリック後にフォーカスされていない場合、`t.typeText`はテキストを入力しません。
テキストの選択や削除などの操作を実装するには、`t.selectText`と`t.pressKey`アクションを使用します。

以下では、`t.typeText`をオプション付きとオプションなしで使用する方法を書いています。

```
const nameInput = Selector('#developer-name');

fixture `My fixture`
    .page `http://www.example.com/`;

test('Type and Replace', async t => {
    await t
        .typeText(nameInput, 'Peter')
        .typeText(nameInput, 'Paker', { replace: true })
        .typeText(nameInput, 'r', { caretPos: 2 })
        .expect(nameInput.value).eql('Parker');
});
```






#ダイアログ操作をする`t.setNativeDialogHandler`メソッド

`t.setNativeDialogHandler( fn(type, text, url) [, options] )`
テスト実行中に呼び出されたネイティブダイアログを処理するには、テストコントローラの`setNativeDialogHandler`メソッドを使用してハンドラ関数を指定します。


| パラメータ | type | 説明 |
|:-----------|:------------|:------------|
| fn       | Function / ClientFunction        | ネガティブダイアログが呼び出されるたびにトリガーされる、通常または[クライアント関数](https://devexpress.github.io/testcafe/documentation/guides/basic-guides/obtain-client-side-info.html)。`null`ネイティブダイアログハンドラを削除します         |
| options     | Object      | [クライアント機能オプション](https://devexpress.github.io/testcafe/documentation/reference/test-api/clientfunction/constructor.html#options)を参照       |



ハンドラー関数には、次の引数があります。

| 引数 | type | 説明 |
|:-----------|:------------|:------------|
|type|String|ネイティブダイアログのタイプ。'alert'/ 'column' / 'beforeunload' / 'prompt'|
|text|String|ダイアログメッセージのテキスト|
|url|String|ダイアログを呼び出したページのURL。これを使用して、ダイアログがメインウィンドウから発生したのか、それとも`<iframe>`から発生したのかを判断します。|

ハンドラーが指定されると、ネイティブダイアログがメインウィンドウからか`<iframe>`からかに関わらず、テストで表示されるたびにトリガーされます。`t.setNativeDialogHandler`をもう一度呼び出すことで、いつでも新しいハンドラを指定することができます。ハンドラが設定されていないときにネイティブダイアログが表示された場合、テストはエラーで失敗します。
`t.setNativeDialogHandler`メソッドに`null`を渡すことで、ダイアログハンドラを削除することができます。
ページロード中に表示されるネイティブダイアログを処理するには、最初のテストアクションの前にダイアログハンドラを指定します。

ハンドラの戻り値を使用して、ダイアログがどのように処理されるかを制御することができます。何も返さない場合、TestCafe はデフォルトの処理を行います。

ダイアログのタイプによって異なります。参考までに下の表を参照してください。

| ダイアログのタイプ | 戻り値 | デフォルトの処理 |
|:-----------|:------------|:------------|
|alert|ignored|'OK' button|
|beforeunload|ignored|'Leave' ボタンです。「Stay」をプログラムでエミュレートする方法はありません。|
|confirm|「OK」と答えた場合は`true`<br>「キャンセル」と答えた場合は`false`|'Cancel' button.|
|prompt|promptに入力するテキストを含む文字列|'Cancel' button.|


##警告ダイアログを処理する

fixtureとtestを宣言するのはこれまでと同じです。

```
fixture `My fixture`
　.page `http://www.example.com/`;

test('My test', async t => {
　await t
　　.setNativeDialogHandler(() => true)
　　.click('#show-alert-button');
});
```

複数のダイアログを処理するサンプルも公式で紹介されています。

```
fixture `My fixture`
　.page `http://www.example.com/`;
test('My test', async t => {
　await t
　　.setNativeDialogHandler((type, text, url) => {
　　　switch (type) {
　　　　case 'confirm':
　　　　　switch (text) {
　　　　　　case 'Do you want to subscribe?':
　　　　　　　return false;
　　　　　　case 'Do you want to delete your account?':
　　　　　　　return true;
　　　　　　default:
　　　　　　　throw 'Unexpected confirm dialog!';
　　　　　}
　　　　　case 'prompt':
　　　　　　return 'Hi there';
　　　　　case 'alert':
　　　　　　throw 'An alert was invoked!';
　　　　}
　　　})
　　　.click('#confirm-subscription');
　　　.click('#show-prompt');
　　　.click('#confirm-account-deletion');
});
```

##ダイアログハンドラーで変数を使用する
この例では、[ページモデル](https://devexpress.github.io/testcafe/documentation/guides/concepts/page-model.html)内の`delete`メソッドを示しています。ダイアログ・ハンドラは、削除されたアイテムの名前`this.name`をプロンプト・ダイアログに入力して削除を確認します。`name`変数は、`options.dependencies`を通してハンドラに渡されます。

```
class Page {
　constructor () {
　　/* ... */
　　this.name = Selector('.item-name').textContent;
　}
　async delete () {
　　const name = await this.name;
　　await t
　　　.setNativeDialogHandler(() => name, { dependencies: { name }})
　　　.click(this.deleteBtn);
　}
}
```

という訳で今回は9つのメソッドについて書いてみました。
たくさんのメソッドがありすぎて書ききれないのでその他は今後の記事で書いていけたらいいなあ。。。