Capybaraが2.1.0になって、また微妙に挙動が変わったので調べてみた

久々にブログ書く。


何気なくbundle updateをしたらcapybaraが2.1.0になってて、テストが落ちるようになった。
また挙動が変わったらしいので、ググって確認してみる。
Introducing Capybara 2.1を参照すると大体分かるけど、一応日本語でざっくり書いておく。

セレクタによるマッチの厳密性が変更になった

capybara2.0から、findメソッドでDOMを探した時に複数マッチすると例外を吐くようになったが、
2.1.0からはマッチングのルールをconfigureで指定できるようになった。

Capybara.configure do |config|
  config.match = :prefer_exact
end


マッチングの種類は以下の四つ

  • :one
  • :first
  • :prefer_exact
  • :smart
:one

2.0と同じルール。複数マッチすると例外になる。

:first

ゆるふわなマッチ。マッチした中で最初の一つを使う。

:prefer_exact

1.x系と同じルール。複数マッチした場合、正確にマッチしているものを優先する。

:smart

2.1からのデフォルト。後述するexactオプションに依存して挙動が変化する。

  • exactオプションがtrueなら、:oneと同じ挙動になる。
  • exactオプションがfalseなら、最初に完全一致で検索し、見つからなければ部分一致で検索する。その時、もし複数の要素が見つかるとAmbiguous例外が発生する。

exactオプション

元々、capybaraでfindやらclick_linkで文字列を元にマッチングをかけると、部分一致でもヒットしていた。
2.1からはデフォルトでは完全一致でないとマッチしないようになっている。
find, click_link, fill_inは、:exactオプションで挙動を制御できるようになっているし、
グローバルなコンフィグを設定する事で、デフォルトの挙動を2.0以前と同様に設定できる。

Capybara.configure do |config|
  config.exact_option = true
end

# or

Capybara.exact = true

可視性による挙動の変化

元々、hiddenな要素を無視するオプションがCapybaraには用意されていたが、それはデフォルトでfalseになっていた。
hiddenな要素が見えるのは混乱を呼ぶらしいので、2.1からはデフォルトの設定がtrueに変わった。つまり、設定してないとhiddenな要素は引っ掛からなくなる。
これ、どうなんだろう。linkとかならそうなんだけど、DOMの状況を調べる場合は見えた方がいいこともあるんで、どっちが良いとも言えないと思うんだが。
元の挙動に戻す時には以下のようにする。

Capybara.ignore_hidden_elements = false

可視性によるtextメソッドの挙動の変化

1.x系だと、そもそもルールが決まっていなくて、driverによって挙動が異なっていた。
2.0系になって、hiddenなDOMに含まれるtextは何も返さなくなった。
2.1系からは、ignore_hidden_elementsに挙動が依存するようになった。
また、textメソッドに引数が渡せるようになり、個別に挙動を上書きできるようになっている。

find("#thing").text           # depends on Capybara.ignore_hidden_elements
find("#thing").text(:all)     # all text
find("#thing").text(:visible) # only visible text


ignore_hidden_elementsの設定に関わらず、2.0と挙動を同じにできるように、
Capybara.visible_text_onlyというオプションが用意された。trueに設定すると、常にvisibleなtextを返す動作になる。

titleの値が取れるようになった

titleの値を取るためのAPIとマッチャーが追加された。

page.title # => "The title"
page.has_title?("The title") # => true
page.should have_title("The title")

disabledなフィールドにアクセスするオプションの追加

find_field, has_field?などのメソッドが、:disabledオプションを取れるようになった。
:disabledをtrueにセットすると、disabledなフィールドのみが検索対象になる。


というわけで、ざっくりまとめて見た。
正確に知りたい人は原文を読んでください。