Rspec Capybaraで実際テストを書いて困ったシチュエーションの解消法


オレがRailsで困ったことをググるとだいたい先に解決してくれているでお馴染みの[@jnchito](http://qiita.com/jnchito)さんの大変参考にしているCapybaraの記事
[使えるRSpec入門・その4「どんなブラウザ操作も自由自在！逆引きCapybara大辞典」](http://qiita.com/jnchito/items/607f956263c38a5fec24)
これには載っていないが、実際のテストを書く上で遭遇してどうやってspecファイルを書いたらいいものかこまった事象を幾つか解決したので共有したいと思う


## テキストエリアに文字を入力したいけど、idがなくてfill_inが出来ない時

## 発生したシチュエーション

テキストエリアに文字を入力する際にはfill_inを使い以下のように指定するが、fill_inを使うにはIDを指定する必要がある。

```rb
fill_in "id名", with: "入力値"

# こう書くことが出来ない
# fill_in ".cssClassName", with: "入力値"
```

## 解決したRspecの書き方
CSSセレクタで指定してsetを使い値を入力する

```rb
find(".cssClassName").set("入力値")

# 同じクラスのものが複数ある場合は、更に絞り込んでやると入力できる
(all(".cssClassName")[2]).set("入力値")
```

ref: http://stackoverflow.com/questions/8534365/how-to-use-fill-in-with-find-in-capybara-if-possible


## ボタンにテキストがない場合は、findで絞り込んでクリック

## 発生したシチュエーション

以下のようにbuttonタグ内にボタン名以外のタグを含んでいたり、動的に変わる数字を含んでいる場合
click_onでうまくクリックさせることが出来ない


```rb
#＜button class="cssClassName"＞ボタン名＜/button＞
# このような場合は押せる
click_on "ボタン名"


#＜button class="cssClassName"＞<i xxxx />ボタン名＜/button＞
#＜button class="cssClassName"＞ボタン名(1)＜/button＞
# こんな感じだタグ内の値だとうまくいかない
# click_on "ボタン名"
```

## 解決したRspecの書き方

findでCSSセレクタで対象のタグ絞り込んでクリックしてやる

```rb
find(".cssClassName").click
```


# Page全体ではなく把握て絞り込んだ領域内の値で判定したい時


## 発生したシチュエーション
あるボタンを押して、実行結果を確認する方法として, page全体からある値があるかどうかを見るのに
have_contentを使うが、この探している値がボタンを押す前から表示されていてる場合は正しい検査ができない。

```rb
# これだと探している値はボタンを押す前から表示されているのでボタンの押す押さないにかかわらずテストが通ってしまう
expect(page).to have_content "探している値"
```


## 解決したRspecの書き方

検査対象をpage全体ではなく、特定の領域を対象にしてhave_contentを使うと良い

```
expect(find("#someId")).to have_content "探している値"
```


# TinyMCEをpoltergeistで値を入力した場合

## 発生したシチュエーション
TinyMCE( https://www.tinymce.com/ )と言うWYSWIYGエディタに値を入力したい場合、
テキストエリアのようにfill_inで入力することが出来ない


## Rspecの書き方
TinyMCEのエディタは指定したID＋_ifrというID名のIFrameが作成されその中のbodyタグのなかがTextAreaの中身というような感じに構成されている
iframeで絞り込むwithin_frameを使いつつキー入力してやる必要がある

```rb
within_frame("tinymaceID_ifr") do
  element = find("body")
  element.native.send_keys("input sentence")
end
```

ref: https://github.com/teampoltergeist/poltergeist/issues/445


# 画面の任意の位置をクリックしたい場合

## 発生したシチュエーション
モーダルダイアログがあり、画面のモーダル以外の部分をクリックした場合にモーダルが消えることを確認したい場合

## 解決したRspecの書き方

```rb
# x, y でピクセル位置を指定
page.driver.click(x, y)
```

```rb
# Bodyタグをクリックしても良さそう
first("body").click
```



#ラベルのないチェックボックスがチェックされているか判定する

## 発生したシチュエーション

チェックボックスにラベルがない場合、後述するシンプルな書き方ができない


## 解決したRspecの書き方

チェックボックスにラベルがない場合

```html
<input type="checkbox" id="foobar" value="yes" checked="checked">
```

対象のオブジェクトを取得してチェックがされているか判定する

```rb
checkbox = find("#foobar")
expect(checkbox).to be_checked
```

### チェックボックスにラベルがある場合

```html
<label>html
 <input type="checkbox" id="foobar" value="yes" checked="checked">
 ラベル名
</label>

```

```rb
# テストはこんな感じ
expect(page).to have_checked_field("ラベル名")
```


ref: http://stackoverflow.com/questions/9570588/how-to-obtain-the-value-of-a-checkbox-in-capybara



# パラメタ付きのURLをチェックする

## 発生したシチュエーション

あるリンクを押して/foo/bar?param1=1へ遷移した時に

current_urlだと/foo/bar/ しか取れないで以下のテストをしても、テストが通らない

```rb
expect(current_url).to foo_bar_index_path(param1: 1)

# current_url　=> /foo/bar
# foo_bar_index_path(param1: 1) => /foo/bar?param1=1
```

urlの?foo=barなどが取れない


## 解決したRspecの書き方
URIオブジェクトを作ってから比較してあげると良い

```
uri = URI.parse(current_url)
expect("#{uri.path}?#{uri.query}").to eq user_index_path(param1: 1)

/user?param1=1
```

ref: http://stackoverflow.com/questions/5228371/how-to-get-current-path-with-query-string-using-capybara



# confirm ウインドウをOKボタンを押す

動作確認してません

```
# OKボタン
page.driver.browser.switch_to.alert.accept
# キャンセル
page.driver.browser.switch_to.alert.dismiss
```
ref: http://qiita.com/sawamur@github/items/952f34ac07cc3cc7515f