我在第4天尝试在RSpec测试中启动autocomplete
场。在浏览器中超级工作,它非常难以在我的请求规范中运行。
更新:看起来我的RSpec / Capy脚本正在针对dev db而不是test db运行。我正在使用Pow,因此我不知道将default_url_options[:host]
或Capybara.app_host
和Capybara.server_port
设置为什么。我有一种感觉,如果我解决这个问题,它可能会有效。
堆栈是:
点击链接,点击按钮,fill_in字段一切都很棒。但是,当需要让这个自动完成工作时,它绝对拒绝工作。
我正在使用这种方法:
def fill_autocomplete(field, options = {})
fill_in field, with: options[:with]
page.execute_script %Q{ $("##{field}").trigger('focus') }
page.execute_script %Q{ $("##{field}").trigger('keydown') }
selector = %Q{ul.ui-autocomplete li.ui-menu-item a:contains("#{options[:select]}")}
Capybara::Screenshot.screenshot_and_open_image
page.should have_selector('ul.ui-autocomplete li.ui-menu-item a')
page.execute_script %Q{ $("#{selector}").trigger('mouseenter').click() }
end
我找到了here。 screenshot
行是我自己的。但是上面的一行:
page.should have_selector('ul.ui-autocomplete li.ui-menu-item a')
返回false
。它就像浏览器中的魅力一样。我不能为我的生活弄清楚为什么它不起作用。我已经尝试过我所知道的一切。我该怎么调试呢?
屏幕截图只显示了我期待的页面,并且字段填写正确。我甚至用“hello”警告对此进行了测试,我将其插入到autocomplete
调用中。在浏览器中完美运行,但在测试中根本没有结果。
简而言之,看起来以下两行没有效果:
page.execute_script %Q{ $("##{field}").trigger('focus') }
page.execute_script %Q{ $("##{field}").trigger('keydown') }
答案 0 :(得分:2)
我遇到了类似的问题,即使Capybara的文档说have_selector
将等待AJAX调用完成,但它对我来说无效。
以下情况适用于我的情况:
def fill_in_autocomplete(field_label, field_class, options = {})
field_id = "##{page.evaluate_script("$('#{field_class}').attr('id')")}"
selector = "ul.ui-autocomplete li.ui-menu-item a"
fill_in(field_label, with: options[:with])
page.execute_script("$('#{field_id}').trigger('focus')")
page.execute_script("$('#{field_id}').trigger('keydown')")
sleep(2) # Hack! not sure why the line below isn't working...
#expect(page).to have_selector(selector, text: options[:with])
page.execute_script("$('#{selector}').click()")
end
您可以像这样调用上面的方法:
fill_in_autocomplete('Some label', '.js-some-field', with: 'Some value'
我不想传递字段ID而是选择了一个类,这就是帮助器中的第一行根据元素的类获取ID的原因。
答案 1 :(得分:0)
这种异步调用对于排除故障非常棘手。正如Xaid建议的那样,有时只需要进行任意的睡眠即可完成工作。
我在自己的编码中发现,通常发生的事情是,尽管Capybara试图智能地等待AJAX发挥其魔力,但是有些事情导致Capybara相信条件得到满足它会在你没有的时候继续实际上已经准备好了。
深入研究Capybara的代码,您会发现异步行为的延迟是通过同步包装函数完成的,该函数是Node :: Base类的一部分。 (见这里,如果你很好奇它是如何运作的:https://github.com/jnicklas/capybara/blob/master/lib/capybara/node/base.rb#L73)
基本上,它正在为您执行一系列等待命令(每次0.05秒)并捕获任何“我找不到该元素”异常,直到超时(默认为2秒)过去。如果出于任何原因,您正在等待的元素在您预期之前存在,它将停止等待并继续前进。
在无头浏览器中存储页面的HTML可能是一个很好的故障排除技巧。尝试在截屏代码之前在代码中插入puts page.body
。那应该输出页面的HTML。代码是否包含您期望的ul.ui-autocomplete li.ui-menu-item a
?在夏德建议的延迟之后怎么样?它存在吗?
对于非常棘手的问题,我会将pry gem添加到我的项目中并将binding.pry插入代码中。这让我可以在测试中使用浏览器来查看它所看到的内容。当然,由于时间问题,我通常不能足够快地看到它看到的东西,但即使这是一个线索。
希望这些故障排除技巧很有用。
答案 2 :(得分:0)
我有这个问题,没有提出的解决方案可以解决它。尝试查找ul.ui-autocomplete
元素时,我的测试总是失败。我终于注意到,jQuery自动完成将ul
附加到html页面的末尾而不是有问题的输入字段。在我的规范中,我遵循within my_form do
明确定位表单的做法,并执行此块中的所有fill_in
内容:
within my_form do
fill_autocomplete …
end
当然,这个表单元素永远找不到ul
附加的OUTSIDE。我的解决方案很简单:在初始化自动完成时使用jQuery自动完成的属性appendTo: '#id_of_input_field'
。现在它可以找到我的ul
,一切正常。