Edited at

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

More than 3 years have passed since last update.

オレがRailsで困ったことをググるとだいたい先に解決してくれているでお馴染みの@jnchitoさんの大変参考にしているCapybaraの記事

使えるRSpec入門・その4「どんなブラウザ操作も自由自在!逆引きCapybara大辞典」

これには載っていないが、実際のテストを書く上で遭遇してどうやってspecファイルを書いたらいいものかこまった事象を幾つか解決したので共有したいと思う


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


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

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

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

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


解決したRspecの書き方

CSSセレクタで指定してsetを使い値を入力する

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でうまくクリックさせることが出来ない

#<button class="cssClassName">ボタン名</button>

# このような場合は押せる
click_on "ボタン名"

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


解決したRspecの書き方

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

find(".cssClassName").click


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


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

あるボタンを押して、実行結果を確認する方法として, page全体からある値があるかどうかを見るのに

have_contentを使うが、この探している値がボタンを押す前から表示されていてる場合は正しい検査ができない。

# これだと探している値はボタンを押す前から表示されているのでボタンの押す押さないにかかわらずテストが通ってしまう

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を使いつつキー入力してやる必要がある

within_frame("tinymaceID_ifr") do

element = find("body")
element.native.send_keys("input sentence")
end

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


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


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

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


解決したRspecの書き方

# x, y でピクセル位置を指定

page.driver.click(x, y)

# Bodyタグをクリックしても良さそう

first("body").click


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


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

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


解決したRspecの書き方

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

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

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

checkbox = find("#foobar")

expect(checkbox).to be_checked


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

<label>html

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

# テストはこんな感じ

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/ しか取れないで以下のテストをしても、テストが通らない

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