Read more

Chaining Capybara matchers in RSpec

Henning Koch
March 07, 2024Software engineer at makandra GmbH

You can chain multiple Capybara matchers Show archive.org snapshot on the page or any element:

expect(page)
  .to have_content('Example Course')
  .and have_css('.course.active')
  .and have_button('Start')
Illustration web development

Do you need DevOps-experts?

Your development team has a full backlog? No time for infrastructure architecture? Our DevOps team is ready to support you!

  • We build reliable cloud solutions with Infrastructure as code
  • We are experts in security, Linux and databases
  • We support your dev team to perform
Read more Show archive.org snapshot

When you chain multiple matchers using and, Capybara will retry the entire chain Show archive.org snapshot if any of the matchers fail.

This helps when browser state changes between expectations, e.g. by async JavaScript that mutates the DOM tree while you're making multiple observations.

Custom matchers must be retryable

For Capybara to be able to retry chain, any custom matchers must be able to re-run their match block.

Here is a ❌ bad example of a matcher that memoizes its observation (in #actual_state) and cannot be retried:

RSpec::Matchers.define :have_state do |expected_state|

  match do |element|
    actual_state(element) == expected_state
  end
  
  failure_message do
    "expected state to be #{expected_state}, but was #{actual_state(element)}"
  end

  def actual_state(element)
    @actual_state ||= element['data-state']
  end

end
Posted by Henning Koch to makandra dev (2024-03-07 08:50)