Capybara :: Poltergeist :: ObsoleteNode, когда angular обновляет строку таблицы, отображаемую с помощью ng-repeat

0

Я тестирую угловые живые обновления с капибарой, огурцом и полтергейстом.

У меня есть следующее определение шага:

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 и до сих пор нет кубиков. Есть ли исправление к этому?

  • 0
    Какую версию phantom.js вы используете?
Теги:
cucumber
capybara
poltergeist

1 ответ

3
Лучший ответ

Механизм повторов 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...

  • 0
    Привет том. Спасибо за ваш ответ, но они не работают. Я должен уточнить, что мы модифицируем отдельную строку в существующей таблице. Так что count: table.raw.size == find(".inventory table").all('tr').size всегда равен true. Ошибка появляется при попытке извлечь текст из заголовка и узлов данных ( rows.map { |r| r.all('th,td').map { |c| c.text.strip } } ).
  • 0
    Я размышляю над решением № 2, потому что diff! дает намного более чистый вывод и более простителен для столбцов не по порядку / отсутствует (важно для полей идентификаторов, которые невозможно проверить)
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню