セキュリティ系の勉強・その他開発メモとか雑談. Twitter, ブログカテゴリ一覧
本ブログはあくまでセキュリティに関する情報共有の一環として作成したものであり,公開されているシステム等に許可なく実行するなど、違法な行為を助長するものではありません.

【Rspec, Capybara】dt, dd要素を取得 ~ 隣の要素を取得

//

タイトル通りの内容です。 フィーチャーテストをする際に、dd, dtの値を関連づけて取ることでテストをわかりやすく、書きやすくしたいと思いました。

問題

<dl>
  <dt id="family-name" class="label">f_name</dt>
  <dd class="data--string">family</dd>
  <dt id="given-name" class="label">g_name</dt>
  <dd class="data--string">given</dd>
<dl>

上のfamilyと言う<dd>の値をラベルf_name経由で取得したい。Capybaraであれば、find("dd.data--string")で取得可能ですが、該当するものが2つあり(更に表示が増える可能性も今後ある)、find_all("dd.data--string").firstとかで順番を指定して取るのも可読性が低いと思うので、f_nameラベルの隣の要素として取得できないかと思いました。

解決

find("dt#family-name", text: "f_name").find("+dd").text # =>"family"
find("dt#family-name", text: "f_name").first(:xpath, './following-sibling::dd').text # => "family"

上のどちらでも希望通りの値が取得可能です。
余談ですが、こちらで紹介した、CapybaraJavaScriptのテスト時では前者の+を用いた手法はエラーになって使えないので注意。

sibling()

siblingと言うメソッドも用意されていて、find("dt#family-name", text: "f_name").sibling("dd")といった形で使います。しかし、このメソッドはfind()見つけた要素と横並びになっている(兄弟?)タグを探索します。ですので、今書いたコードを最初のhtmlに使用すると、ddが2つ見つかってしまいエラーになるので注意。(find()の仕様と同じ。詳しくはリファレンスで)

参考

stackoverflow.com

www.rubydoc.info