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 Base

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

Overview

Defines the base classes for all Capybara RSpec matchers, providing session handling, element wrapping, negation support, and a countable/spatial mixin hierarchy.

Description

The Base class stores matcher arguments (*args, **kw_args, &filter_block) and resolves session options from the matched context element, falling back to Capybara.session_options. WrappedElementMatcher extends Base with matches? and does_not_match? methods that automatically wrap the actual value into a Capybara node (via to_capybara_node or Capybara.string) and delegate to abstract element_matches? / element_does_not_match? hooks. CountableWrappedElementMatcher mixes in CountSugar and SpatialSugar for count-based and spatial assertions. NegatedMatcher is a decorator that swaps matches? and does_not_match? on any existing matcher, inverting its logic and failure messages.

Usage

Use these base classes when building custom RSpec matchers for Capybara. Subclass WrappedElementMatcher for simple presence/absence matchers, CountableWrappedElementMatcher when you need count or spatial constraints, and wrap any matcher in NegatedMatcher to invert its assertion semantics.

Code Reference

Source Location

Signature

# Base
class Capybara::RSpecMatchers::Matchers::Base
  def initialize(*args, **kw_args, &filter_block)
end

# WrappedElementMatcher
class Capybara::RSpecMatchers::Matchers::WrappedElementMatcher < Base
  def matches?(actual, &filter_block)
  def does_not_match?(actual, &filter_block)
end

# CountableWrappedElementMatcher
class Capybara::RSpecMatchers::Matchers::CountableWrappedElementMatcher < WrappedElementMatcher
  include CountSugar
  include SpatialSugar
end

# NegatedMatcher
class Capybara::RSpecMatchers::Matchers::NegatedMatcher
  def initialize(matcher)
  def matches?(actual, &filter_block)
  def does_not_match?(actual, &filter_block)
  def description
  def failure_message
  def failure_message_when_negated
end

Import

require 'capybara/rspec/matchers/base'

I/O Contract

Base#initialize

Parameter Type Description
*args Array Positional arguments forwarded to underlying Capybara queries
**kw_args Hash Keyword arguments forwarded to underlying Capybara queries
&filter_block Proc Optional block used to filter matched elements
Returns Type Description
Instance Base A new matcher base instance storing the provided arguments

WrappedElementMatcher#matches?

Parameter Type Description
actual Object The page, node, or string to match against; auto-wrapped into a Capybara node
&filter_block Proc Optional filter block (used if none was provided at initialization)
Returns Type Description
result Boolean true if element matches, false if Capybara::ExpectationNotMet is raised

NegatedMatcher#initialize

Parameter Type Description
matcher Base The original matcher whose logic will be inverted
Returns Type Description
Instance NegatedMatcher A decorator that swaps match/no-match semantics

Usage Examples

Subclassing WrappedElementMatcher

class HaveWidget < Capybara::RSpecMatchers::Matchers::WrappedElementMatcher
  def element_matches?(el)
    el.assert_selector('.widget', **session_query_options, &@filter_block)
  end

  def element_does_not_match?(el)
    el.assert_no_selector('.widget', **session_query_options, &@filter_block)
  end

  def description
    "have widget"
  end
end

expect(page).to HaveWidget.new

Using NegatedMatcher

matcher = HaveSelector.new(:css, '.active')
negated = Capybara::RSpecMatchers::Matchers::NegatedMatcher.new(matcher)

negated.matches?(page) # delegates to matcher.does_not_match?(page)
negated.description     # => "not have css \".active\""

CountableWrappedElementMatcher with count sugar

# CountSugar and SpatialSugar are mixed in automatically
expect(page).to have_selector('.item', count: 3)
expect(page).to have_selector('.item', minimum: 1, maximum: 5)

Related Pages

Page Connections

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