RSpec: Expect one of multiple matchers to match

RSpec let's you chain a matcher with .or. The expectation will then pass if at least one matcher matches:

expect(color).to eq("red").or eq("green")

Real-world example

A real-world use case would be to test if the current page has a button with the label "Foo". There are many ways to render a button with CSS:

<input type="button" value="Foo">
<input type="submit" value="Foo">
<button>Foo</button>

We cannot express it with a single have_css() matcher, since we need the { text: 'Foo' } option for some cases (<input>), but not for others (<button>).

What we can do is chain multiple have_css() matchers with .or like this:

match_button = have_css("button", text: 'Foo')
match_button_input = have_css("input[type='button'][value='Foo']")
match_submit_input = have_css("input[type='submit'][value='Foo']")

expect(page)
  .to match_button
  .or match_button_input
  .or match_submit_input

Tip

Capybara also has a find_button Show archive.org snapshot method that takes care of all these details for you.

You can also require multiple matchers on the same object by chaining them with .and, although you might just want to use multiple expect() statements for readability and mergability.

Henning Koch About 6 years ago