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

Capybara, capybara-webkit и пользовательская форма загрузки файлов

Я создал пользовательскую форму загрузки, используя следующий html-стек:

<form>
  <label></label>
  <input type="file">
</form>

Поле файла скрыто через css с свойством display: none. Поэтому диалог прикрепления файла вызывается пользователем, когда она нажимает на ярлык (который является обычным стилем).

В моем тестовом тесте я не могу прикрепить файл, так как поле ввода скрыто. Я пробовал несколько возможных решений, но ни один из них не работает:

find(:xpath, '//input', visible: false).set(some_file_path)

или

within('form') do                                                                                                                                                                       
  attach_file(:input, some_file_path, visible: false)                                                                                                                                          
end

И многие другие. Все время, в которое я попал, не удалось щелкнуть элемент по ошибке неизвестной позиции. Как только я удаляю ярлык, перекрывающий поле ввода, сделайте его видимым и запустите мою спецификацию. Поэтому проблема заключается в том, что:

  • Поле входного файла имеет свойство display: none (и, следовательно, не может быть найдено)
  • Существует метка, перекрывающая скрытое поле файла (возможно)

Есть ли способ заставить Capybara с драйвером Capybara-webkit справиться с этой деликатной ситуацией каким-то разумным способом?

4b9b3361

Ответ 1

С помощью capybara-webkit вы можете сказать, что драйвер запускает любой javascript, который вы хотите, в контексте страницы, поэтому вы можете написать что-то обычное, чтобы взломать проблему видимости:

script = "$('thelabel').toggle(); " # hide the label
script << "$('myfield').toggle();"  # show your field

page.driver.browser.execute_script(script)

Это псевдокод, но вы должны сделать что-то подобное, чтобы сделать поле видимым, прежде чем вы назовете attach_file на нем.

Тем не менее, каждый раз (по крайней мере, я) делаю что-то вроде такого грубого, как это в моих тестах, это хорошая идея сделать быстрый момент и спросить, является ли это тестом или интерфейсом, который необходимо исправлять. Если вы довольны интерфейсом, вы можете использовать небольшой фрагмент js, как показано выше, чтобы получить видимый элемент для вашего теста.

Обновление:

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

page.execute_script(script)

Эта более короткая версия должна работать с capybara 2.x и последние версии capybara-webkit или poltergeist, который является альтернативой более низкой зависимости, который я использую сейчас.

Существует также партнерский метод evaluate_script:

result = page.evaluate_script('4 + 4');

Надеюсь, это поможет!

Ответ 2

Мэтт Сандерс предлагает использовать JS для переключения видимости элемента. Это будет работать, но здесь другое решение, которое немного чище, ИМО.

Я рекомендую включать скрытые поля только при необходимости. Чтобы добиться этого, я использовал этот помощник для тех редких случаев, когда вы действительно хотите, чтобы Capybara включила скрытые поля. Например:

# features/support/capybara_helpers.rb
module CapybaraHelpers
  # By default, capybara will ignore all hidden fields. This is a smart default
  # except in rare cases. For example, our AS3 file uploader requires you to
  # click a hidden file field - and that makes perfect sense. In those rare
  # cases, you can use this helper to override the default and force capybara
  # to include hidden fields.
  #
  # Examples
  #
  #   include_hidden_fields do
  #     attach_file("hidden-input", "path/to/fixture/file")
  #   end
  #
  def include_hidden_fields
    Capybara.ignore_hidden_elements = false
    yield
    Capybara.ignore_hidden_elements = true
  end
end
World(CapybaraHelpers)

Ответ 3

для кого-то другого, может показаться полезным:

Иногда "toggle" недостаточно, затем установите флажок "непрозрачность" (не должна быть равна нулю):

script = "$('#file-field').css({opacity: 100, display: 'block'});"
page.driver.browser.execute_script(script)

Ответ 4

Попробуйте это

file_field = page.find('input[type="file"]', visible: false) file_field.set('path/to/my/image.jpg')