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

Ruby on rails 3 是否可以通过RSpec/Capybara测试元素的顺序?,ruby-on-rails-3,rspec,ruby-on-rails-3.1,capybara,Ruby On Rails 3,Rspec,Ruby On Rails 3.1,Capybara,我使用RSpec/Capybara作为我的测试套件。我有一些javascript动态地将附加到的末尾。我想写一个请求规范来确保这一点 我尝试使用has\u cssCapybara方法和高级css选择器来测试元素的顺序,但Capybara不支持+css选择器 例如: page.should have_css('li:contains("ITEM #1")') pseuo_add_new_li page.should have_css('li:contains("ITEM #1")+li:conta

我使用RSpec/Capybara作为我的测试套件。我有一些javascript动态地将
  • 附加到
    的末尾。我想写一个请求规范来确保这一点

    我尝试使用
    has\u css
    Capybara方法和高级css选择器来测试
  • 元素的顺序,但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")')
    

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

    水豚应该支持
    +
    选择器(我相信它使用Nokogiri,它肯定支持这一点)。您是否正在使用旧版本?或者您使用的是不支持JavaScript的Capybara驱动程序,因此无法呈现额外的元素


    另外,不要使用RSpec测试HTML。Cucumber在这方面做得更好。要与JavaScript交互,您需要使用Selenium或Capybara Webkit。或者,如果你有很多JavaScript,考虑用贾斯敏测试它。

    < P>我通过测试与页面正文内容的正则表达式匹配来解决这个问题。有点笨拙,但它是有效的

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

    我发现了一种更规范的方法来测试CSS的这种行为。您可以使用
    :第一个孩子
    :最后一个孩子
    :第n个孩子(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")
    

    我希望这对某人有帮助

    这个页面有一个非常聪明的方法来测试页面上字符串元素的顺序,不管它们是否在列表中:

    这是一个黄瓜步骤,但你应该能够提取你需要的Rspec步骤。这类似于约翰的“笨拙”解决方案——但从我的理解来看,有点古怪。他们所有其他狡猾的水豚测试步骤都可以在这里找到:

    列出了几种在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
    
    RSpec::Matchers.define:before|u do | later_内容|
    匹配do |早期内容|
    page.body.index(早期内容)
    我最近也遇到了同样的问题,找到了这个简洁而理想的解决方案:

    它甚至被包装成一颗小小的宝石

    使用您可以使用
    #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)
    
    #首先定义小部件,
    #或可重用的dom元素引用。
    #在本例中,在一个角色中
    类UserRole
    有序地使用前面提到的文章作者编写的

    简单到:

    expect(this).to appear_before(that)
    
    您可以使用finder方法选择多个元素,然后使用collect将文本提取到数组中:

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

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

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

    我已经在这里发布了解决方案-


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

    因为
    page.body.如果不推荐使用
    ,我们可以使用regexp匹配进行多行比较,如那边评论中所说:

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

    n最后一个子项
    从底部选择第n个子项。使用Webrat,我得到了“未定义的局部变量或方法'page'”@JoaoHornburg抱歉,我无能为力。到目前为止,我只使用过水豚。我已经让它和webrat一起工作了。已经在github上完成了这个项目,当我有时间修改文档并发布Gei使用的文档时,我将发布我的代码,而且它可以工作。我想检查特定div中项目的顺序,应该怎么做?这篇文章非常适合进一步了解。我不知道你为什么会投反对票,但你完全正确地认为水豚(Nokogiri)支持
    +
    选择器。我的怀疑是新的
    li
    没有添加到
    项目1
    的旁边,他应该使用
    ~
    选择器。cucumber如何能更好地测试html?@DrewV cucumber更擅长用面向用户的术语对面向用户的内容进行断言。RSpec在测试UI时处于错误的抽象级别。使用简单的Minitest:
    assert page.body=~/ITEM1.*ITEM2.*ITEM3/
    您还可以检查标记的结尾:
    expect(page)=~>ITEM1ITEM2ITEM3Thank You,非常优雅的解决方案。最后我使用了
    expect(response.body)。为了将(/ITEM1.*ITEM2.*ITEM3/m)
    与RSpec4和多行匹配谢谢-那篇文章真的帮助了我(我们使用的是Minitest,而不是RSpec),在OP的情况下,我认为这是一个有待实现的薄弱测试。如果在添加新元素的javascript之前,页面上至少已经存在一个特定元素,那么映射这些元素将立即只返回当前页面上的元素,如果javascript花费的时间太长,则可能不包括新元素。最好像其他答案所建议的那样,显式地使用位置伪类选择器。