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

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

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

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

4 ответов


С помощью 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)

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

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

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

надеюсь, что это помогает!


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

Я рекомендую включать скрытые поля только при необходимости. Чтобы достичь этого, я используется этот помощник для тех редких случаев, когда вы действительно хотите 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)

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

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

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

попробуй такое

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