如何从自动完成中选择li

时间:2011-03-03 00:26:16

标签: jquery ruby-on-rails ajax

在文本框中,当您键入时,我们有自动完成功能,可生成采用此结构的列表:

<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元素,我查看了源代码以确保,所以我真的很困惑,它无法找到它。

3 个答案:

答案 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>