【问题标题】:Rspec/capybara - test presence of a class OR another classRspec/capybara - 测试一个类或另一个类的存在
【发布时间】:2017-05-27 22:39:08
【问题描述】:

在我的 ruby​​ on Rails 4.2 应用程序中,在页面上我有一个条件后端规则,该规则在类的更改中转换为页面前端

<div id="content">
    <i class='<% if x=true %>glyphicon glyphicon-thumbs-down<% else> glyphicon glyphicon-thumbs-up ><% end %>' </i>
       this is the message.
</div>

如何使用 rspec 3/capybara 检查页面是否包含 glyphicon-thumbs-down 类或 glyphicon-thumbs-up 类?

我尝试了下面的代码,但它失败了:

it "should sheck one of the 2 classes presence" do
  expect(page).to have_css '.glyphicon-thumbs-down' || expect(page).to have_css '.glyphicon-thumbs-up'
end

我收到以下错误消息:

syntax error, unexpected tIDENTIFIER, expecting keyword_end (SyntaxError)

【问题讨论】:

  • 您不应该准备包括后端规则在内的测试,以便准确知道将在页面上呈现哪个类?
  • 不,因为这是后端的随机规则(这是运气游戏)所以我无法在我的测试套件中预测它

标签: ruby-on-rails ruby ruby-on-rails-4 rspec capybara


【解决方案1】:

多个 OR-ed css 选择器可以用逗号分隔。请尝试以下操作:

it "should sheck one of the 2 classes presence" do
  expect(page).to have_css '#content i.glyphicon-thumbs-down,#content i.glyphicon-thumbs-up'
end

(我添加了#contenti 选择器,以便查询更具体。)

但是,我建议不要这样做,而是尝试使测试以精确定义的方式运行,并仅测试规范中的单个类。查看this SO question 及其答案,了解在测试中存根或预设随机数生成器的各种方法。

【讨论】:

    【解决方案2】:

    首先,您正在检查类名,因此您需要在类名前加上. 以使其成为 CSS 类选择器。然后,您可以使用 RSpec or 匹配器组合器

    expect(page).to have_css('.glyphicon-thumbs-down').or(have_css '.glyphicon-thumbs-up')
    

    但它的缺点是第一个在检查第二个之前重试/等待Capybara.default_max_wait_time 秒。如果您知道页面已加载,因此不需要重试/等待,则可以指定 0/false 等待时间

     expect(page).to have_css('.glyphicon-thumbs-down', wait: false).or(have_css '.glyphicon-thumbs-up', wait: false)
    

    但是,使用普通的 CSS , 检查任一元素可能没问题

     expect(page).to have_css('.glyphicon-thumbs-down, .glyphicon-thumbs-up')
    

    【讨论】:

    • 非常感谢您的回答,我给 Borama 点了积分,因为他的建议与 2 分钟前我需要的(您的最后一个建议)相匹配:)确实,我必须等待服务器 ajax 响应并且可以' t 使用 0 等待时间,所以赌注是先 wait_for_ajax 然后 have_css('.glyphicon-thumbs-down, .glyphicon-thumbs-up')
    • @Mathieu 你根本不需要wait_for_ajaxhave_css 将等待两个选择器之一匹配(最多 Capybara.default_max_wait_time 秒)
    • 我等待 ajax,因为我有一个 ajax 请求发送到服务器以检查数据并将其发送回视图。我知道 have_css 会等待......但有时在我的特定情况下我不得不使用 wait_for_ajax 来工作。感谢您提供额外的积极关注信息
    【解决方案3】:

    您的错误来自这一行:

      expect(page).to have_css 'glyphicon-thumbs-down' || expect(page).to have_css 'glyphicon-thumbs-up'
    

    你只需要添加一些括号,那么它就是有效的语法:

    expect(page).to(have_css('glyphicon-thumbs-down')) || expect(page).to(have_css('glyphicon-thumbs-up'))
    

    但这并不能解决您的问题,因为如果左侧条件失败,则 rspec 将退出并且不会运行后半部分。

    一种可行的方法是将条件评估为布尔变量,然后将其传递给单个 rspec 期望。这样做需要使用核心 Capybara 方法 has_css 来测试 css 的存在,而不是 rspec 匹配器包中的 have_css?

    selectors = ['.glyphicon-thumbs-down', '.glyphicon-thumbs-up']
    glyph_exists = selectors.any? do |selector|
      page.has_css? selector
    end
    expect(glyph_exists).to be true
    

    还请注意,我已将 . 添加到选择器字符串中,这是必要的,因为它是一个 css 类。

    【讨论】:

    • 这有每次调用 has_css? 等待 Capybara.default_max_wait_time 秒的缺点,然后再检查下一个如果不匹配。
    • 是的。为了解决这个问题,我将它们包装在一个非常短的持续时间的显式等待中,并挽救了错误以返回 false。虽然不理想
    【解决方案4】:

    也许你可以尝试使用选项:count,在expect方法中是这样的:

    it 'should contains 2 same selector' do
      expect(page).to have_css '.some-class', count: 2
    end
    

    【讨论】:

      猜你喜欢
      • 2012-04-12
      • 2021-12-23
      • 2016-02-29
      • 1970-01-01
      • 2022-01-23
      • 2011-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多