是否可以通过RSpec / Capybara测试元素的顺序?

时间:2011-12-07 22:32:51

标签: ruby-on-rails-3 rspec ruby-on-rails-3.1 capybara

我正在使用RSpec / Capybara作为我的测试套件。我有一些javascript动态地将<li>附加到<ul>的末尾。我想写一个请求规范来确保这种情况发生。

我尝试使用has_css Capybara方法和高级CSS选择器来测试<li>元素的排序,但Capybara不支持+ CSS选择器。

示例:

page.should have_css('li:contains("ITEM #1")')
pseuo_add_new_li
page.should have_css('li:contains("ITEM #1")+li:contains("ITEM #2")')

有没有人知道测试订购的另一种方法?

11 个答案:

答案 0 :(得分:33)

我通过测试针对页面正文内容的正则表达式匹配来解决此问题。有点kludgy,但它的工作原理。

page.body.should =~ /ITEM1.*ITEM2.*ITEM3/

答案 1 :(得分:29)

我找到了一种使用CSS测试此行为的更规范的方法。您可以在任何您喜欢的断言中使用:first-child:last-child:nth-child(n)选择器。

在你的例子中我会尝试这些断言:

page.should have_tag("ul:last-child", :text => "ITEM #1")
pseuo_add_new_li
page.should have_tag("ul:nth-last-child(2)", :text => "ITEM #1")
page.should have_tag("ul:last-child", :text => "ITEM #2")

我希望这有助于某人。 Read more about this

答案 2 :(得分:26)

this article列出了几种在R​​Spec中测试排序顺序的方法,其中最好的方法似乎就是这个匹配器:

RSpec::Matchers.define :appear_before do |later_content|
  match do |earlier_content|
    page.body.index(earlier_content) < page.body.index(later_content)
  end
end

答案 3 :(得分:4)

我最近遇到了同样的问题,发现这个问题很简洁。理想解决方案 http://launchware.com/articles/acceptance-testing-asserting-sort-order

它甚至被打包成一颗小宝石。

答案 4 :(得分:2)

这个页面有一个非常聪明的方法来测试页面上字符串元素的顺序 - 无论是否在列表中:

https://makandracards.com/makandra/789-match-strings-in-a-given-order-with-cucumber-and-capybara

它采用黄瓜步骤的形式,但您应该能够提取Rspec步骤所需的内容。它类似于Johns'kludgy'的解决方案 - 但是我能从中得到更多的信息。他们所有其他狡猾的水豚测试步骤都可以在这里找到:

https://github.com/makandra/spreewald

答案 5 :(得分:2)

您可以使用all finder方法选择多个元素,然后使用collect将文本拉出到数组中:

assert_equal page.all('#navigation ul li').collect(&:text), ['Item 1', 'Item 2', 'Item 3']

如果您的列表在页面上不可见,例如弹出式导航菜单,则需要将visible: false传递到all方法。

答案 6 :(得分:1)

使用前面提到的gem作者撰写的orderly article

这很简单:

expect(this).to appear_before(that)

答案 7 :(得分:0)

Capybara应该支持+选择器(我相信它使用了Nokogiri,它肯定支持这个)。你是在使用旧版本吗?或者您使用的是不支持JavaScript的Capybara驱动程序,以便额外的元素根本不会被渲染?

另外,请勿使用RSpec来测试HTML。黄瓜在这方面要好得多。要与JavaScript交互,您需要使用Selenium或Capybara-Webkit。或者,如果您有很多JavaScript,请考虑使用Jasmine进行测试。

答案 8 :(得分:0)

使用capybara-ui,您可以使用#widgets方法以自上而下的顺序获取所有元素。

# First define the widget,
# or reusable dom element reference.
# In this case in a role
class UserRole < Capybara::UI::Role
  widget :list_item, '.list-item'
end

# Then test the expected order using #widgets
role = UserRole.new
expected_order = ['buy milk', 'get gas', 'call dad']
actual_order = role.widgets(:list_item).map(&:text)

expect(actual_order).to eq(expected_order)

答案 9 :(得分:0)

在上述解决方案中,如果在页面上有多个元素,则很难测试顺序。所以,我找到了另一种方式。

我已在此处发布了解决方案 - Test order(sequence) of content using capybara

映射具有css特定元素的数组,然后将该数组与期望数组匹配(保持元素顺序)

答案 10 :(得分:0)

由于page.body.should已过时,我们可以对多行​​使用regexp匹配,就像在评论中所说的Ben一样:

expect(page.body).to match /#{item1.name}.*#{item2.name}/m