我使用以下html堆栈创建了自定义上传表单:
<form>
<label></label>
<input type="file">
</form>
文件字段通过具有display: none
属性的css隐藏。因此,当用户点击标签(这是自定义样式的)时,就会调用文件附加对话框。
在我的功能测试中,我无法附加文件,因为输入字段是隐藏的。我尝试了几种可能的解决方案,但都不起作用:
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网络工具包驱动程序以某种理智的方式处理这种微妙的情况吗?
使用capybara webkit,您可以告诉驱动程序在页面上下文中运行任何您想要的javascript,这样您就可以编写一些自定义的东西来破解可见性问题:
script = "$('thelabel').toggle(); " # hide the label
script << "$('myfield').toggle();" # show your field
page.driver.browser.execute_script(script)
这是伪代码,但在调用attach_file
之前,您应该能够执行类似的操作,使字段可见
也就是说,每次(至少我)在测试中做这样有点恶心的事情时,花点时间问一下是测试还是接口需要修复是个好主意。如果你对这个接口很满意,你应该能够使用像上面这样的小js片段来让元素在测试中可见。
更新:
对这种行为的支持已经变得更加广泛,现在在水豚中已经标准化了,所以你可以:
page.execute_script(script)
这个较短的版本应该适用于capybara 2.x和最近版本的capybara webkit或poltergeist,这是我现在使用的一个依赖性较低的替代方案。
还有一种伙伴方法evaluate_script
:
result = page.evaluate_script('4 + 4');
希望这能有所帮助!
Matt Sanders建议使用JS来切换元素的可见性。这会起作用,但这里有另一个更干净的解决方案,IMO.
我建议仅在必要时才包括隐藏字段。为了做到这一点,我当你真的想让水豚包括在内时,在那些罕见的情况下使用了这个助手隐藏字段。例如:
# 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)
现在有了一个选项"make_visible"https://www.rubydoc.info/github/jnicklas/capybara/Capybara/Node/Actions%3Aattach_file
对于其他人来说,可能会发现这很有用:
有时"切换"是不够的,然后检查"不透明度"(不应该为零):
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')