Капибара и Rspec: правильный способ использовать в пределах () и have_selector () вместе? - PullRequest
10 голосов
/ 28 марта 2012

Я использую rspec 2.6.0 и Capybara 1.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 (), не являетсяограничено блоком inside (), но я не уверен, почему это так.Документация на капибару использует этот шаблон и, похоже, не упоминает никаких ошибок.Какой правильный способ использовать внутри, чтобы ограничить область моего выбора?Спасибо./ Salernost

Ответы [ 4 ]

12 голосов
/ 06 апреля 2012

Все еще изучаю Капибару, но вы пробовали have_link вместо have_selector? Также я не думаю, что вам нужно |ref|. Например:

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


Обновление от 13 октября 2012 г.

Пройдя немного дальше с Капибарой, я вижу здесь несколько потенциальных проблем:

  • within может игнорировать поле text. Вы заметите, что примеры показывают только искатели CSS или XPath без дополнительных аргументов.
  • Если within использует text, он может здесь не работать, потому что вы просите его взглянуть на <tr>, но текст находится в <td>.
  • Вполне возможно, что субъект page по-прежнему нацелен на всю страницу, даже если вы находитесь в блоке within. Примеры within в основном касаются использования fill_in или click. Исключением является пример под Остерегайтесь XPath // trap .

Что касается создания блока within, вы можете либо присвоить своим строкам таблицы уникальные идентификаторы и искать их с помощью CSS, либо вы можете написать конкретный XPath, нацеливающийся на первую подходящую строку.

Проблема с последним заключается в том, что вы хотите использовать within на <tr>, но текст, который вы используете для таргетинга, находится внутри подэлемента <td>. Так, например, этот XPath должен найти ячейку таблицы, содержащую текст Team 3 Name, но тогда вы работаете только с within в этой первой ячейке, а не со всей строкой.

within(:xpath, "//tr/td[normalize-space(text())='Team 3 Name'") do

Существуют способы «резервного копирования» на родительский элемент с использованием XPath, но я не знаю, как это сделать, и я прочитал, что это не очень хорошая практика. Я думаю, что вам лучше всего сгенерировать идентификаторы, чтобы ваши строки начинались так:

<tr id="team_3">

затем наведите на них простое

within("tr#team_3")
5 голосов
/ 13 апреля 2015

Я бы также порекомендовал Последний вариант Марка Берри , о котором он упомянул, - добавление идентификаторов к каждому из элементов вашей таблицы.

<tr id="team_3">

затем прицельтесь с

within("tr#team_3")

При выборе xpath у меня возникли проблемы с тем, что он не работает согласованно, особенно со службами CI.

Я также хочу отметить в этом же ответе этот раздел:

Вполне возможно, что тема страницы по-прежнему нацелена на всю страницу, даже если вы находитесь внутри блока.Примеры внутри в основном об использовании fill_in или клика.Исключением является пример в разделе Остерегайтесь XPath // trap.

Возможно, это имело место в более старой версии, но в текущей версии 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
4 голосов
/ 18 марта 2013

have_selector, кажется, игнорирует опции :text и :content.Мне пришлось использовать что-то вроде этого:

within 'a' do
  page.should have_content 'Deactivate'
end
3 голосов
/ 06 января 2018

Решение состоит в том, чтобы не использовать within метод:

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