web-dev-qa-db-ja.com

CapybaraとRspec:within()とhave_selector()を一緒に使用する正しい方法は?

受け入れテストにはrspec2.6.0とCapybara1.1.1を使用しています。
次のようなビューで:

<tr >
  <td>Team 3 Name</td>
  <td>true</td>
  <td><a href="/teams/3">Show</a></td>
  <td><a href="/teams/3/edit">Edit</a></td>
  <td><a href="/teams/3">Deactivate</a></td>
</tr>
<tr >
  <td>Team 4 Name</td>
  <td>true</td>
  <td><a href="/teams/4">Show</a></td>
  <td><a href="/teams/4/edit">Edit</a></td>
  <td><a href="/teams/4">Deactivate</a></td>
</tr>

「チーム3には「非アクティブ化」リンクがありません」という受け入れテストを作成したいと思います。私は以下が失敗することを期待しています:

within('tr', :text => 'Team 3 Name') do |ref|
  page.should_not have_selector('a', :text => 'Deactivate')
end

しかし、それは通過します。何が起こっているのかをさらにテストするために、私はばかげたことを書きました:

lock = false
within('tr', :text => 'Team 3 Name') do |ref|
  page.should have_selector('a', :text => 'Deactivate')
  page.should_not have_selector('a', :text => 'Deactivate')
  lock = true
end
lock.should be_true

これも合格です。

このことから、have_selector()呼び出しが使用しているスコープは、within()ブロックによって制限されていないと想定していますが、その理由はわかりません。カピバラのドキュメントはこのパターンを使用しており、落とし穴については言及していないようです。選択範囲を制限するために使用する正しい方法は何ですか?ありがとうございました。/Salernost

14
salernost

have_selector:textおよび:contentオプションを無視しているようです。代わりに次のようなものを使用する必要がありました。

within 'a' do
  page.should have_content 'Deactivate'
end
4
Anton Styagun

また、 Mark Berry の最後のアプローチとして、各テーブル要素にIDを追加することをお勧めします。

<tr id="team_3">

次に、

within("tr#team_3")

Capybaraは、xpathで選択するときに、特にCIサービスで一貫して機能しないように見えるという問題を私に与えました。

私はまた、このセクションの同じ答えに注意したいと思います:

ブロック内にいる場合でも、ページの件名がページ全体をターゲットにしている可能性は十分にあります。内の例は、主にfill_inまたはclickの使用に関するものです。例外は、「XPathに注意してください//トラップ」の例です。

これは古いバージョンの場合であった可能性がありますが、現在のバージョンのCapybaraでは、pageブロック内でwithinを呼び出すと、対象のページの部分のみが検査されます。したがって、マークの上記の例を使用すると、次のようになります。

within("tr#team_3") do
  expect(page).to have_content 'Team 3 Name'
  # => true
  expect(page).to have_content 'Team 4 Name'
  # => false
end
3
supremebeing7

解決策は、withinメソッドを使用しないことです。

expect(page).to have_css('tr#team_3') do
  without_tag('a', text: 'Deactivate')
end
2
Philippe Perret