Gebチートシート


[stac2014](https://github.com/kyonmm/stac2014-handson-document)のTAをしたときに整理したものです。

基本は、[公式サイト](http://www.gebish.org/manual/current/all.html)で調べましょう。

# 要素取得

指定 | コード
-----|-----
id   | $("#foo")
name | $(name:"foo")
class| $(".foo")

## Formの中の要素の選択

formの中の要素は、formをcontentに用意すれば、name属性を使って簡単にアクセスできる。

content部分

```
static content = {
    testCaseForm { $("form[role=form]") }
}
```

formの要素をname属性を使ってアクセスしている例

```
public void addTestCase(String name, String scenario, String tag) {
    testCaseForm.name = name
    testCaseForm.scenario = scenario
    if(tag != null){
        testCaseForm.tags = tag
    }
    testCaseForm.create().click()
}
```

# 操作

取得した要素が変数elementに格納されている前提で記載します。

操作 | コード
-----|-----
クリック | element.click()
テキスト入力 | element = "テキスト"
ラジオボタン選択 | element = "valueの値"
チェックボックスをチェック | element = true
プルダウン | element << "valueの値"
セレクト | element = "foo"
マルチセレクト | element = ["foo", "bar"]

## formの場合

`$('form').name属性名`でとるのもよくやるテクニック。
例えばこんな感じ。

```html
<form>
  <input id="on_radio" type="radio" value="on" name="on_off_radio">あり
  <input id="off_radio" type="radio" value="off" name="on_off_radio">なし
</form>
```

```geb
$('form').on_off_radio = 'on'
```

# 要素の情報取得

取得した要素が変数elementに格納されている前提で記載します。

情報 | コード
-----|-----
テキスト | element.text()
inputのテキスト | element.text() 
表示/非表示 | element.isDisplayed()
実行可/不可 | element.isEnabled()
選択済/未選択 | element.isSelected()
存在する/しない | element.size() > 0

# window処理

to()を実行すると、PageObjectのat()チェックもしてくれる。

※Page Objectについては後述

操作 | コード
-----|-----
指定URLへ移動 | go "URL"
指定Pageへ移動 | to PageObject
指定Pageへ移動（リダイレクトされるとき） | via PageObject
現在のwindowを閉じる | close()
WebDriverを終了 | quit()
ブラウザバック | driver.navigate().back()
ブラウザフォワード | driver.navigate().forward()
ポップアップ（OK） | withConfirm(true) { 処理 }
ポップアップ（キャンセル） | withConfirm(false) { 処理 }

# Waitとスクリーンショット取得

waitFor{}の中はどんな判定でもよいため、いくらでも応用がきく（isEnabled()とか）。

操作 | コード
-----|-----
要素が表示されるまで待機 | waitFor{ element.isDisplayed() }
PageObjectのcontentでwait指定 | helpButton(to: HelpPage, toWait: true) { $("button#help") }
スクリーンショット取得 | report "ファイル名"

# 設定ファイル（GebConfig.groovy）

```
import geb.report.ScreenshotReporter

reportsDir = "build/geb-reports" // スクリーンショットの出力ディレクトリ
baseUrl = "http://fathomless-stream-3131.herokuapp.com" // 起点となるURL
// 待機時間の指定（キーワード指定）
waiting {
    presets {
        slow {
            timeout = 15
            retryInterval = 1
        }
        quick {
            timeout = 1
        }
    }
}
// 待機時間の指定
waiting {
    timeout = 60
    retryInterval = 0.5
}
atCheckWaiting = true // at()チェックの待機設定
baseNavigatorWaiting = true // base navigatorのための待機設定
// スクリーンショットのファイル名文字化け対策
reporter = new ScreenshotReporter() {
    @Override
    protected escapeFileName(String name) {
        name.replaceAll('[\\\\/:\\*?\\"&lt;>\\|]', '_')
    }
}
```

# Page Object

```
class AdminPage extends Page {
    static at = {
        assert $("h1").text() == "Admin Page"
    }
}
```

# PageObjectのContent

```
class ExamplePage extends Page {
    static content = {
        heading { $("h1").text() }
        loginButton(to: AdminPage) { $("input", type: "submit", name: "login") }
    }
}
```

# module

module

```
class ExampleModule extends Module {
    static content = {
        button { $("input", type: "submit") }
    }
}
```

PageObjectでmoduleを使う

```
class ExamplePage extends Page {
    static content = {
        theModule { module ExampleModule }
    }
}
```

# Module List

基本的には以下のとおり。

http://www.gebish.org/manual/current/all.html#using_modules_for_repeating_content_on_a_page

### 簡単に解説。

#### module

`cell(N)`の部分は`edit {cell(2).$("a", 0)}`のような書き方もできる。

```
class CartRow extends Module {
    static content = {
        cell { $("td", it) }
        productName { cell(0).text() }
        quantity { cell(1).text().toInteger() }
        price { cell(2).text().toDouble() }
    }
}
```

#### Page Object

`tail()`部分はヘッダーを飛ばすため。

今回のアプリはヘッダーがthになっているので不要。

```
class CheckoutPage extends Page {
    static content = {
        cartItems { moduleList CartRow, $("table tr").tail() } // tailing to skip the header row
    }
}
```

#### 検索

直接、ModuleListとは関係ないが、Groovyのfindメソッドを使って検索するとよい。
以下は、OverLoadを何度もしなくてよいように、引数をMapにしたパターン。
入力がないときは、検索条件なしと判定するようにしている。

```
public List<TestCaseRow> searchTestCases(Map param) {
        String name = param?.name ?: ""
        String scenario = param?.scenario ?: ""
        List<String> tags = param?.tags ?: []

        List<TestCaseRow> result = testCaseItems.findAll {
            (name == "" || it.name == name) && (scenario == "" || it.scenario == scenario) && (tags == [] || it.tags.split("\n").toList().containsAll(tags))
        }
        if(result){
            return result
        } else if(find(".nextLink")){
            next.click()
            sleep(3000)
            searchTestCases(name:name, scenario:scenario, tags:tags)
        } else{
            return []
        }
    }```