如何编写尊重块内水豚的RSpec匹配器?

时间:2018-11-18 13:45:44

标签: ruby-on-rails rspec capybara

我正在尝试编写一个自定义的RSpec匹配器,用于在Capybara下运行的Rails系统测试中-这个想法是在匹配文本的同时忽略某些<span>标签。

这是匹配者:

RSpec::Matchers.define :have_cleaned_text do |text|
  match do |content|
    content.body.include?(text) || content.body.gsub(%r{<span class=["']separator["'].*?>.*?</span>}, ' ').include?(text)
  end
end

和要测试的页面的HTML正文:

<h1>Test Page</h1>
<div id='constraint'>
  <p>Clean text</p>
  <p>Broken<span class='separator'>|<span>text</p>
</div>

前两个测试通过:

within('#constraint') do
  expect(page).to have_cleaned_text('Clean text')
  expect(page).to have_cleaned_text('Broken text')
  expect(page).not_to have_cleaned_text('Test Page') # fails!
end

…但是第三个失败,因为have_cleaned_text忽略了within块并针对整个页面进行了测试。

如何使匹配器尊重within块?我希望它以content而不是整个页面的形式传递。

1 个答案:

答案 0 :(得分:2)

在您的示例中,page是一个Capybara会话(包含其当前作用域)。在会话上调用bodysourcehtml是别名)时,它将返回文档的HTML源。由于您正在寻找元素的HTML源,因此需要类似

RSpec::Matchers.define :have_cleaned_text do |text|
  match do |session|
    session.current_scope[:innerHTML].include?(text) || session.current_scope[:innerHTML].gsub(%r{<span class=["']separator["'].*?>.*?</span>}, ' ').include?(text)
  end
end

请注意,这样编写的匹配器不会像Capybara提供的匹配器那样具有任何等待/重试行为,因此您需要在使用页面之前确保页面已加载/稳定。