Подтвердить что ты не робот

Как сделать проверку Capybara для видимости после запуска JS?

После загрузки страницы у меня есть код, который запускает и скрывает и показывает различные элементы на основе данных, возвращаемых xhr.

Мой интеграционный тест выглядит примерно так:

it "should not show the blah" do
    page.find('#blah').visible?.should be_true
end 

Когда я вручную перехожу на страницу в контексте этого теста, #blah не отображается, как я ожидаю. Я подозреваю, что Capybara смотрит на начальное состояние страницы (в этом случае это невидимое), оценивая состояние DOM и не выполняя тест до запуска JS.

Да, я устанавливаю :js => true в содержащий блок описания:)

Любые идеи были бы очень признательны! Я надеюсь, что мне не нужно вводить преднамеренную задержку здесь, которая кажется шелушащейся и замедлит работу.

4b9b3361

Ответ 1

Я думаю, что здесь инструкция find - это та, которая имеет неявное ожидание, поэтому Capybara будет ждать, пока элемент не окажется на странице, но не будет ждать, пока он станет видимым.

Здесь вам нужно, чтобы Capybara дождался появления видимого элемента, что должно быть возможным, указав параметр visible:

expect(page).to have_selector('#blah', visible: true)

Я не пробовал, но параметр конфигурации ignore_hidden_elements может быть полезен и здесь, если вы хотите, чтобы find всегда ждал видимых элементов.

Ответ 2

Это еще один способ сделать это, который отлично подходит для меня:

find(:css, "#some_element").should be_visible

Специально для более сложных находок, таких как

find(:css, "#comment_stream_list li[data-id='#{@id3}']").should_not be_visible

который утверждал бы, что элемент был скрыт.

Ответ 3

Если вы хотите проверить, что элемент находится на странице, но не отображается, visible: false не будет работать так, как вы могли бы ожидать. Я немного пошатнулся.

Вот как это сделать:

# assert element is present, regardless of visibility
page.should have_css('#some_element', :visible => false)
# assert visible element is not present
page.should have_no_css('#some_element', :visible => true)

Ответ 4

Использование:

 Ruby:     ruby 1.9.3dev (2011-09-23 revision 33323) [i686-linux]
 Rails:    3.2.9
 Capybara: 2.0.3

У меня есть приложение Rails, в котором есть ссылка, которая при нажатии должна отправить запрос на отправку AJAX и вернуть ответ JS.

Код ссылки:

 link_to("Send Notification", notification_path(user_id: user_id), remote: true, method: :post)

Ответ JS (файл .js.haml) должен переключать следующий скрытый div на странице, где существует ссылка:

 #notification_status(style='display:none')

Содержимое файла js.haml:

:plain
  var notificationStatusContainer = $('#notification_status');
  notificationStatusContainer.val("#{@notification_status_msg}");
  notificationStatusContainer.show();

Я тестировал свой сценарий отправки уведомлений и показывал сообщение о статусе уведомления пользователю с использованием огурца (жемчужина огуречных рельсов со встроенным Capybara)

Я пытался проверить, что элемент, имеющий id: notification_status, был видимым на успешный ответ в моем определении шага. Для этого я пробовал следующие утверждения:

page.find('# notification_status'). должно быть_visible page.should have_selector ('# notification_status', visible: true) page.should have_css ('# notification_status', visible: true) page.find('# notification_status', visible: true) page.find(: css, 'div # notification_status', visible: true)

Ни один из вышеперечисленных не работал у меня и не прошел мой шаг. Из приведенных выше 5 фрагментов последние 4 не были выполнены со следующей ошибкой:

'expected to find css "#notification_status" but there were no matches. Also found "", which matched the selector but not all filters. (Capybara::ExpectationNotMet)'

что было странно, потому что следующее утверждение прошло правильно:

page.has_selector?('#notification_status')

И на самом деле я проверил источник страницы, используя

  print page.html

который показал

<div style='' id='notification_status'></div>

который ожидался.

Наконец, я нашел эту ссылку capybara assert атрибуты элемента, в которой показано, как необработанным образом проверять атрибут элемента.

Также я нашел в документации Capybara для видимых? метод (http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Element#visible%3F-instance_method) следующая информация:

 Not all drivers support CSS, so the result may be inaccurate.

Таким образом, я пришел к выводу, что при проверке видимости элемента не полагайтесь на результаты Капибары, видимые? метод при использовании селектора CSS и используя решение, предложенное в ссылке capybara, утверждают атрибуты элемента

Я придумал следующее:

 module CustomMatchers
   def should_be_visible(css_selector)
    find(css_selector)['style'].should_not include('display:none', 'display: none')
   end
 end

 World(CustomMatchers)

Использование:

should_be_visible('#notification_status')

Ответ 5

Какие видимые средства не очевидны

Неисправность может возникнуть из-за непонимания того, что считается видимым или нет, поскольку оно неочевидно, а не переносное устройство и недостаточно документировано. Некоторые тесты:

HTML:

<div id="visible-empty"                                                                   ></div>
<div id="visible-empty-background"      style="width:10px; height:10px; background:black;"></div>
<div id="visible-empty-background-same" style="width:10px; height:10px; background:white;"></div>
<div id="visible-visibility-hidden"     style="visibility:hidden;"                        >a</div>
<div id="visible-display-none"          style="display:none;"                             >a</div>

Единственное, что Rack test считает невидимым, - это встроенный display: none (не внутренний CSS, поскольку он не делает селекторов):

!all('#visible-empty',                 visible: true).empty? or raise
!all('#visible-empty-background',      visible: true).empty? or raise
!all('#visible-empty-background-same', visible: true).empty? or raise
!all('#visible-visibiility-hidden',    visible: true).empty? or raise
 all('#visible-display-none',          visible: true).empty? or raise

Полтергейст имеет аналогичное поведение, но он может иметь дело с внутренними манипуляциями CSS и Js style.display:

Capybara.current_driver = :poltergeist
!all('#visible-empty',                 visible: true).empty? or raise
!all('#visible-empty-background',      visible: true).empty? or raise
!all('#visible-empty-background-same', visible: true).empty? or raise
!all('#visible-visibiility-hidden',    visible: true).empty? or raise
 all('#visible-display-none',          visible: true).empty? or raise

Селен ведет себя совершенно иначе: если считает пустой элемент невидимым и visibility-hidden, а также display: none:

Capybara.current_driver = :selenium
 all('#visible-empty',                 visible: true).empty? or raise
!all('#visible-empty-background',      visible: true).empty? or raise
!all('#visible-empty-background-same', visible: true).empty? or raise
 all('#visible-visibiility-hidden',    visible: true).empty? or raise
 all('#visible-display-none',          visible: true).empty? or raise

Другим распространенным уловком является значение по умолчанию visible:

  • он был false (видит как видимые и невидимые элементы),
  • в настоящее время true
  • управляется опцией Capybara.ignore_hidden_elements.

Ссылка.

Полный runnable-тест на моем GitHub.

Ответ 6

Возможно, вы захотите посмотреть этот пост, который дает примерный метод для ожидания завершения всех запросов ajax:

def wait_for_ajax(timeout = Capybara.default_wait_time)
  page.wait_until(timeout) do
    page.evaluate_script 'jQuery.active == 0'
  end
end

Ответ 7

Принятый ответ немного устарел, так как "should" - это устаревший синтаксис. В эти дни вам будет лучше делать что-то по строкам expect(page).not_to have_css('#blah', visible: :hidden)

Ответ 8

Другие ответы здесь - лучший способ "подождать" для элемента. Однако я обнаружил, что это не работает для сайта, над которым я работаю. В основном элемент, который нуждался в щелчке, был видимым до того, как функция, которая была полностью загружена. Это в доли секунды, но я обнаружил, что мой тест проходил так быстро, что он нажал кнопку, и ничего не произошло. Мне удалось обойти это, выполнив это логическое выражение make-shift:

if page.has_selector?('<css-that-appears-after-click>')
  puts ('<Some-message-you-want-printed-in-the-output>')
else
  find('<css-for-the-button-to-click-again>', :match == :first).trigger('click')
end

В основном он использует время ожидания по умолчанию capybara, чтобы искать что-то, что должно появиться, если оно не существует, он будет повторять ваш клик.

Снова я скажу, что метод should have_selector должен быть проверен первым, но если он просто не работает, попробуйте это