Я тестирую угловые живые обновления с капибарой, огурцом и полтергейстом.
У меня есть следующее определение шага:
Then(/^I should see the following inventory:$/) do |table|
rows = find(".inventory table").all('tr')
page_table = rows.map { |r| r.all('th,td').map { |c| c.text.strip } }
table.dup.diff!(page_table)
end
Ошибка:
Элемент, с которым вы пытаетесь взаимодействовать, либо не является частью DOM, либо в настоящее время не отображается на странице (возможно, отображается: none установлено). Возможно, элемент был заменен другим элементом, и вы хотели бы взаимодействовать с новым элементом. Если это так, вам нужно сделать новое "найти", чтобы получить ссылку на новый элемент. (Капибара :: Полтергейст :: ObsoleteNode)
Однако, если я завершу утверждение (на самом деле просто #find) с ожидающим блоком (повторяет) тест проходит.
с ожидаемым блоком:
Then(/^I should see the following inventory:$/) do |table|
sleeping(0.1).seconds.between_tries.failing_after(20).tries do
rows = find(".inventory table").all('tr')
page_table = rows.map { |r| r.all('th,td').map { |c| c.text.strip } }
table.dup.diff!(page_table)
end
end
Я ненавижу это решение, потому что у огурца /capybara уже должен быть механизм повтора. Таким образом, если этот тайм-аут повторения составляет 5 секунд, вы потенциально пытаетесь выполнить повторную попытку за 5 секунд * 20retries + дополнительные 2 секунды. Теперь я могу добавить wait: 0
в действие find, но все эти решения выглядят как хаки.
Я использую poltergeist 1.9.8, но попробовал модернизировать до 2.1 и до сих пор нет кубиков. Есть ли исправление к этому?
Механизм повторов Capybaras встроен в его матчи, которые вы не используете в этом тесте. Вы также используете #all
который имеет недостаток в том, что элементы, которые он возвращает, не являются автоматически перезаряжаемыми и поэтому должны использоваться только тогда, когда элементы не будут меняться или уже изменены. #all
также имеет время ожидания 0 так, как вы его используете, поскольку пустой массив элементов (без совпадений) является допустимым ответом, поэтому нет ожидаемого поведения. Если в тесте число видимых строк меняется, вы можете использовать опцию count
чтобы принудительно #all
и реализовать что-то вроде
Then(/^I should see the following inventory:$/) do |table|
rows = find(".inventory table").all('tr', count: table.raw.size)
page_table = rows.map { |r| r.all('th,td').map { |c| c.text.strip } }
table.dup.diff!(page_table)
end
Это заставит #all
ждать ожидаемого количества строк на странице, что должно означать, что строки будут меняться и вызывать all('th,td')
чтобы найти текст становится безопасным.
Опция, если количество строк не изменится (только их содержимое), состоит в том, чтобы просто конкатенировать все содержимое вместе и проверить текст таблицы - это не будет 100% проверять таблицу в точности, но в тестовой среде, где вы контролируете данные, вероятно, достаточно хорошо. Это непроверено, но что-то вроде следующего:
Then(/^I should see the following inventory:$/) do |table|
expect(find(".inventory table")).to have_content(table.raw.flatten.join)
end
Еще один вариант попробовать - использовать Capybara :: Node :: synchronize, чтобы получить повторное прохождение - что-то вроде
Then(/^I should see the following inventory:$/) do |table|
inv_table = find(".inventory table")
inv_table.synchronize do
page_table = inv_table.all('tr').map { |r| r.all('th,td').map { |c| c.text.strip } }
table.dup.diff!(page_table)
end
end
#synchronize
должен позволить #synchronize
повторять блок до Capybara.default_max_wait_time, пока он не пройдет. По умолчанию он будет повторять только ошибки, возвращаемые driver.invalid_elements
и Capybara :: ElementNotFound. Если вы также хотите, чтобы он повторил попытку ошибка, возвращаемая diff! (до max_wait_time секунд) вам придется передавать параметры для синхронизации, такие как inv_table.synchronize max_wait_time, errors: page.driver.invalid_element_errors + [Capybara::ElementNotFound, WhateverErrorDiffRaisesOnFailure] do...
count: table.raw.size == find(".inventory table").all('tr').size
всегда равен true. Ошибка появляется при попытке извлечь текст из заголовка и узлов данных ( rows.map { |r| r.all('th,td').map { |c| c.text.strip } }
).
diff!
дает намного более чистый вывод и более простителен для столбцов не по порядку / отсутствует (важно для полей идентификаторов, которые невозможно проверить)