7

我正在使用 Rails 3.2.8

  • 宝石'jquery-rails','2.1.2'
  • 宝石'rails3-jquery-autocomplete','1.0.9'
  • 宝石'rspec-rails','2.11.4'
  • 宝石'水豚','1.1.3'
  • 宝石“水豚-webkit”,“0.12.1”

我最近将选择下拉列表转换为自动完成(使用 rails3-jquery-autocomplete)并尝试更新我的请求规范以填写自动完成。

我的方法是创建一个助手,如本要点所示:

def fill_autocomplete(field, options = {})
  fill_in field, :with => options[:with]

  selector = "ul.ui-autocomplete a:contains('#{options[:select]}')"

  page.should have_selector selector
  page.execute_script "$(\"#{selector}\").mouseenter().click()"
end

如果我使用 Webkit 进行测试,测试会失败并显示以下消息:

expected css "ul.ui-autocomplete a:contains('Firstname Lastname')" to return something.

如果我使用 Selenium 进行测试,当我在 Firefox 中观看测试时,我看不到下拉选择列表出现。添加一个sleep 3等待下拉菜单没有帮助。

在这里看到capybara-webkit 有一个相关但有点老的问题,当一个字段被填写时,它会立即变得模糊,这当然会阻止自动完成选择列表的出现。但这似乎与其他已使其工作的人不相符。

目前是否可以使用 RSpec 和 Capybara 测试包含 rails3-jquery-autocomplete 字段的表单?如何?如果没有,有没有办法手动填写相应的隐藏id字段,以便我仍然可以测试表单是否创建了正确的数据?

4

5 回答 5

10

终于得到了至少与 Selenium 驱动程序一起工作的自动完成测试。

解决方案是将焦点放在字段上并发出 keydown 事件。

我首先通过浏览器中的手动测试确认了这一点。如果我使用鼠标(不是 Ctrl-V)将搜索词粘贴到自动完成字段中,则不会发生任何事情——不显示下拉选择列表。这显然等同于 Capybara 发送 fill_in 命令时发生的情况。但是,在术语在字段中之后,当焦点仍然在字段上时,如果我触摸任何键,例如 Shift 键,就会出现选择列表。所以显然选择列表只在按下一个键时出现。

选项1

一种解决方案是从原始问题扩展功能,如下所示:

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 = "ul.ui-autocomplete a:contains('#{options[:select]}')"

  page.should have_selector selector
  page.execute_script "$(\"#{selector}\").mouseenter().click()"
end

然后这样称呼它:

fill_autocomplete "to_contact_name", with: "Jone", select: "Bob Jones"

选项 2

一种类似的方法,改编自主要 rails3-jquery-autocomplete gem 中的Steak 测试,使用标准的 fill_in,然后是这个 choose_autocomplete_result:

def choose_autocomplete_result(item_text, input_selector="input[data-autocomplete]")
  page.execute_script %Q{ $('#{input_selector}').trigger("focus") }
  page.execute_script %Q{ $('#{input_selector}').trigger("keydown") }
  # Set up a selector, wait for it to appear on the page, then use it.
  item_selector = "ul.ui-autocomplete li.ui-menu-item a:contains('#{item_text}')"
  page.should have_selector item_selector
  page.execute_script %Q{ $("#{item_selector}").trigger("mouseenter").trigger("click"); }
end

像这样调用:

fill_in "to_contact_name", :with => "Jone"
choose_autocomplete_result "Bob Jones", "#to_contact_name"

我在测试中采用了第二种方法。Selenium 似乎很可靠,但不适用于 webkit,这太糟糕了,因为相比之下 Selenium 测试相当慢。欢迎在 webkit 下工作的解决方案!

于 2012-11-03T20:26:25.533 回答
4

我自己也碰到了同样的痛点。在这上面花了几个小时之后,我有了一个很好的帮手,它可以同时使用 selenium 和 polstergeist,而且不使用sleep(). 以下代码已使用 Capybara 2.1.0 进行了测试:

  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]}")}

    page.should have_selector('ul.ui-autocomplete li.ui-menu-item a')
    page.execute_script %Q{ $('#{selector}').trigger('mouseenter').click() }
  end

基本上,我告诉 Capybara 填写输入字段,然后使用 JS 触发keydown事件以激活自动完成。但是sleep(),我利用了page.should have_selector('ul.ui-autocomplete li.ui-menu-item a')等待下拉列表出现的机会,而不是 。然后我用JS触发mouseenter事件然后点击。我希望有比使用 JS eval 做事更好的方法,但这是我能想到的最可靠的解决方案。

于 2013-09-09T05:06:21.670 回答
2

如果有人需要一些代码来获得灵感(即使在阅读了这个帖子之后我也花了一些时间),这很有效:

      context "with 5 items results" do
        before do
          5.times { FactoryGirl.create(:item, title: "chinese " + random_string(5) ) }
          page.execute_script("$('input#search_param').val('chinese')")
          page.execute_script("$('input#search_param').trigger('focus')")
          page.execute_script("$('input#search_param').trigger('keydown')")
        end
        specify { page.evaluate_script("$('input#search_param').val()").should == 'chinese' }
        specify { page.should have_css "#autocomplete-menu li", count: 5 }
      end

感谢马克贝瑞的灵感。

于 2013-12-04T21:12:32.050 回答
1

另一种选择是capybara send_keys方法:

find('#my_object_id').send_keys 'bob'

我更喜欢这个选项而不是注入 javascript 来触发 keydown/focus/mouseenter 事件。

于 2016-04-29T15:27:22.987 回答
0

我没有使用 page.execute_script,而是在输入后用空白填充输入,以便触发事件。

fill_in("query", :with => "ma")
fill_in("query", :with => "")
# autocomplete suggestions will come up
all('.autocomplete div').first.should have_content("mango")
# other assertions
于 2013-05-21T09:21:55.100 回答