teamcapybara/capybara · error · Capybara::ExpectationNotMet

Item does not match the provided selector

Error message

Item does not match the provided selector

What it means

assert_matches_selector verifies that the receiver element itself is among the nodes matching the given selector plus filters; _verify_match_result resolves the MatchQuery and raises ExpectationNotMet 'Item does not match the provided selector' when self is not in the result set. Unlike assert_selector it checks identity of this specific node, not just that some node matches.

Source

Thrown at lib/capybara/node/matchers.rb:590

      ##
      #
      # Asserts that the current node matches a given selector.
      #
      #     node.assert_matches_selector('p#foo')
      #     node.assert_matches_selector(:xpath, '//p[@id="foo"]')
      #     node.assert_matches_selector(:foo)
      #
      # It also accepts all options that {Capybara::Node::Finders#all} accepts,
      # such as `:text` and `:visible`.
      #
      #     node.assert_matches_selector('li', text: 'Horse', visible: true)
      #
      # @param (see Capybara::Node::Finders#all)
      # @raise [Capybara::ExpectationNotMet]      If the selector does not match
      #
      def assert_matches_selector(*args, &optional_filter_block)
        _verify_match_result(args, optional_filter_block) do |result|
          raise Capybara::ExpectationNotMet, 'Item does not match the provided selector' unless result.include? self
        end
      end

      ##
      #
      # Asserts that the current node does not match a given selector.
      # Usage is identical to {#assert_matches_selector}.
      #
      # @param (see #assert_matches_selector)
      # @raise [Capybara::ExpectationNotMet]      If the selector matches
      #
      def assert_not_matches_selector(*args, &optional_filter_block)
        _verify_match_result(args, optional_filter_block) do |result|
          raise Capybara::ExpectationNotMet, 'Item matched the provided selector' if result.include? self
        end
      end

      ##

View on GitHub (pinned to 15b5fdb76e)

Solutions

  1. Inspect the element (el.text, el[:class], el[:type]) and align the selector/filters with its real state
  2. For dynamic states add wait: el.assert_matches_selector('input', checked: true, wait: 5)
  3. Use the right selector type (:field/:link/:css) whose built-in filters match what you assert
  4. If you only care that the page contains such nodes, use assert_selector instead of the element-matching form

Example fix

# before
el.assert_matches_selector('li', text: 'Horse')  # el.text == 'Horse '

# after
el.assert_matches_selector('li', text: /Horse/)
# or normalize whitespace
el.assert_matches_selector('li', text: 'Horse', normalize_ws: true)
Defensive patterns

Strategy: validation

Validate before calling

return unless el.matches_selector?('li', text: /Horse/)
el.assert_matches_selector('li', text: /Horse/)

Type guard

def node_matches?(node, *args, **opts, &block)
  node.matches_selector?(*args, **opts, &block)
end

Try / catch

begin
  el.assert_matches_selector('input', checked: true, wait: 3)
rescue Capybara::ExpectationNotMet => e
  raise unless el.matches_selector?('input') # node exists; state differs — re-drive UI
  raise
end

Prevention

When it happens

Trigger: el.assert_matches_selector('li', text: 'Horse') when el is a li but its text is 'Cow'; el.assert_matches_selector('input[type=checkbox]', checked: true) when the box is unchecked; el.assert_matches_selector(:field, 'Email') on an element labelled differently; matching on tag/class that the node does not have.

Common situations: Verifying a located element still satisfies a contract after page updates (element went stale or attributes changed between find and assert), wrong filter values (text with different whitespace), asserting on attributes that toggle dynamically (checked/disabled/active class) before the state settles.

Related errors


AI-assisted analysis of teamcapybara/capybara@15b5fdb76e (2026-08-21). Data as JSON: /api/errors/2e9459b34f7c4c77. Report an issue: GitHub.