我正在使用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")')
有没有人知道测试订购的另一种方法?
答案 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列出了几种在RSpec中测试排序顺序的方法,其中最好的方法似乎就是这个匹配器:
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'的解决方案 - 但是我能从中得到更多的信息。他们所有其他狡猾的水豚测试步骤都可以在这里找到:
答案 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)
答案 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