在文本框中,当您键入时,我们有自动完成功能,可生成采用此结构的列表:
<div class="results">
<ul>
<li class="even">
<li class="odd">
<li class="even">
etc...
我正在用Cucumber(加上Capybara和Webdriver)编写测试,我需要选择第一个li
。
page.execute_script
没有通过正确的jQuery,因为以下代码片段不断返回null
。
page.execute_script %Q{ $('li').eq(1).trigger("mouseenter").click(); }
也就是说,我收到了这个错误:
TypeError: $("li") is null (Selenium::WebDriver::Error::UnexpectedJavascriptError)
我只是选择了jQuery,所以有人会告诉我什么是错的,为什么它是错的,可能还有如何修复它?
页面上存在li
元素,我查看了源代码以确保,所以我真的很困惑,它无法找到它。
答案 0 :(得分:5)
我可能不会尝试使用page.execute_script方法单击自动完成列表项。理想情况下,黄瓜的When
步骤应始终100%模仿用户能够做的事情。而且我不希望他们打开一个javascript控制台并开始输入脚本来执行以选择列表项;)
显然我知道这不是你想要的,但这就是你用你的方法测试的。
更好的方法是在你的一个黄瓜步骤定义中使用以下内容:
When /^I follow the autocomplete link containing "([^"]*)"$/ do |link_text|
page.find(:css, ".results ul li", :text => link_text).click
end
我认为这应该有效,而且比在黄瓜步骤中破解JS代码更好。
请注意,page.find方法返回一个Capybara :: Node :: Element(我相信)。 :text hash选项告诉capybara只查找包含指定文本的元素。如果找不到该元素,capybara将引发异常。
如果由于某种原因你的li实际上没有可点击的文字,你可以将选择器更改为".results ul li:first"
,但理想情况下你可以使用该定义而不仅仅是选择第一项。
您可能会遇到一个错误(某些关于'找不到'节点'的方法或某些shinanigans)。如果你得到一个奇怪的错误,你在做这个时无法解释,并且它不是很明显它是什么,那么你可能需要在你黄瓜的支持目录的env.rb中注释掉以下行:
require 'cucumber/rails/capybara_javascript_emulation'
当水豚升级时,放入其中的monkeypatch黄瓜已经破裂,最后我检查的还没有部署为稳定版本。
希望这可以解决您的问题:)
编辑添加:
我再次看了你的问题,觉得我可能想让你知道为什么$(“li”)会返回null。当您在此脚本执行之前添加“我应该看到...”步骤时,capybara具有内置的等待元素到显示的默认超时,当您在页面上查找某个元素时,它会使用它还有。如果它没有出现在指定的时间内(我认为默认为5秒?)那么 capybara会给你一个失败的测试。
然而,当你运行execute_script调用时,你绕过了所有Capybara的真棒框架并尝试使用jquery直接与DOM交互 - 除了Capybara没有“等待”对象出现,所以你的javascript可能不会找到它。
我相信我使用page.find发布的解决方案对您有用,因为该方法会在引发错误之前等待元素出现在页面上。此处详细解释了查找器:https://github.com/jnicklas/capybara位于显示自述文件的“查找”子标题下。
答案 1 :(得分:0)
可能是因为自动完成是在页面呈现之后(之后)生成的,因此执行脚本可能无法获取它。
尝试使用jQuery命令live
将触发器附加到document.ready之后呈现的项目。
答案 2 :(得分:0)
以下代码适用于我。我把所有额外的代码都划掉了。要记住的关键点是,当调用函数时,列表项存在(即,一旦页面“准备好”,我将访问它)
在您的情况下,一旦填充了自动建议,您应该只执行$('li'),否则它将为null。另请注意,eq()基于零 - 所以第一个元素是eq(0),而不是eq(1)。
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
console.log($('li').eq(0)); // outputs the first list element Item 1
});
</script>
</head>
<body>
<div class="results">
<ul>
<li class="even">Item 1</li>
<li class="odd">Item 2</li>
<li class="even">Item 3</li>
<li class="odd">Item 4</li>
</ul>
</div>
</body>