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.