Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:Teamcapybara Capybara RSpec Matchers Compound

From Leeroopedia
Knowledge Sources
Domains Testing, RSpec Matchers
Last Updated 2026-02-12 06:00 GMT

Overview

Provides compound AND/OR matcher logic that synchronizes multiple Capybara matchers within a single Capybara synchronize block, enabling atomic compound assertions on asynchronous page content.

Description

The Compound module is mixed into matcher base classes to add and, and_then, and or combinator methods. The and and or methods return Capybara-aware And and Or compound matchers that extend RSpec's built-in compound matcher classes. These compound matchers use the Synchronizer module to execute both sub-matchers inside a single synchronize block, ensuring that asynchronous element matching is retried atomically. The CapybaraEvaluator caches match results for each matcher per synchronize cycle and is reset on each retry. The and_then method bypasses Capybara synchronization and delegates to RSpec's native Compound::And, useful when synchronization is not needed.

Usage

Use the compound matchers when you need to assert multiple conditions on the same Capybara element or page within a single expectation. Use and for synchronized conjunction, or for synchronized disjunction, and and_then when you want standard RSpec compound behavior without Capybara synchronization.

Code Reference

Source Location

Signature

# Compound module (mixed into Base)
module Capybara::RSpecMatchers::Matchers::Compound
  include ::RSpec::Matchers::Composable

  def and(matcher)    # => And
  def and_then(matcher) # => RSpec::Matchers::BuiltIn::Compound::And
  def or(matcher)     # => Or
end

# CapybaraEvaluator
class Capybara::RSpecMatchers::Matchers::Compound::CapybaraEvaluator
  def initialize(actual)
  def matcher_matches?(matcher)
  def reset
end

# Synchronizer (private API)
module Capybara::RSpecMatchers::Matchers::Compound::Synchronizer
  def match(_expected, actual)
  def sync_element(el)
end

# And
class Capybara::RSpecMatchers::Matchers::Compound::And < RSpec::Matchers::BuiltIn::Compound::And
  include Synchronizer
  def synchronized_match? # => Boolean (all sub-matchers pass)
end

# Or
class Capybara::RSpecMatchers::Matchers::Compound::Or < RSpec::Matchers::BuiltIn::Compound::Or
  include Synchronizer
  def synchronized_match? # => Boolean (any sub-matcher passes)
end

Import

require 'capybara/rspec/matchers/compound'

I/O Contract

Compound#and

Parameter Type Description
matcher RSpec::Matchers::BuiltIn::BaseMatcher The second matcher to combine with the receiver via synchronized AND
Returns Type Description
compound And A synchronized compound AND matcher

Compound#or

Parameter Type Description
matcher RSpec::Matchers::BuiltIn::BaseMatcher The second matcher to combine with the receiver via synchronized OR
Returns Type Description
compound Or A synchronized compound OR matcher

Compound#and_then

Parameter Type Description
matcher RSpec::Matchers::BuiltIn::BaseMatcher The second matcher to combine without Capybara synchronization
Returns Type Description
compound RSpec::Matchers::BuiltIn::Compound::And A standard RSpec compound AND matcher (no synchronization)

Synchronizer#match

Parameter Type Description
_expected Object Unused (required by RSpec interface)
actual Object The element, session, or string to match against
Returns Type Description
result Boolean true if synchronized_match? succeeds within the synchronize block, false otherwise

Usage Examples

Synchronized AND matching

expect(page).to have_selector('.header').and have_selector('.footer')
# Both matchers are evaluated inside a single Capybara synchronize block.
# If either fails transiently, the entire compound is retried until timeout.

Synchronized OR matching

expect(page).to have_selector('.success-message').or have_selector('.warning-message')
# Passes if at least one of the selectors is found on the page.

Non-synchronized AND with and_then

expect(page).to have_selector('.loaded').and_then have_css('[data-ready="true"]')
# Uses standard RSpec Compound::And without Capybara synchronization.
# Each matcher is evaluated independently.

Related Pages

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment