teamcapybara/capybara · error · Capybara::ExpectationNotMet
result.failure_message
Error message
result.failure_message
What it means
Node::Matchers#assert_selector raises ExpectationNotMet with Result#failure_message when, after waiting, the resolved element set neither matches the count options nor contains anything (unless the query expects zero). The message reads 'expected to find <description> <count expectation>' plus what was actually found and elements that matched the selector but failed filters ('Also found ... which matched the selector but not all filters').
Source
Thrown at lib/capybara/node/matchers.rb:112
#
# It also accepts all options that {Capybara::Node::Finders#all} accepts,
# such as `:text` and `:visible`.
#
# page.assert_selector('li', text: 'Horse', visible: true)
#
# {#assert_selector} can also accept XPath expressions generated by the
# XPath gem:
#
# page.assert_selector(:xpath, XPath.descendant(:p))
#
# @param (see Capybara::Node::Finders#all)
# @option options [Integer] :count (nil) Number of times the expression should occur
# @raise [Capybara::ExpectationNotMet] If the selector does not exist
#
def assert_selector(*args, &optional_filter_block)
_verify_selector_result(args, optional_filter_block) do |result, query|
unless result.matches_count? && (result.any? || query.expects_none?)
raise Capybara::ExpectationNotMet, result.failure_message
end
end
end
##
#
# Asserts that an element has the specified CSS styles.
#
# element.assert_matches_style( 'color' => 'rgb(0,0,255)', 'font-size' => /px/ )
#
# @param styles [Hash]
# @raise [Capybara::ExpectationNotMet] If the element doesn't have the specified styles
#
def assert_matches_style(styles = nil, **options)
styles, options = options, {} if styles.nil?
query_args, query_opts = _set_query_session_options(styles, options)
query = Capybara::Queries::StyleQuery.new(*query_args, **query_opts)
synchronize(query.wait) doView on GitHub (pinned to 15b5fdb76e)
Solutions
- Read the failure message: 'found N matches' tells you the real count; adjust the count option or the selector
- If 'Also found ... not all filters' appears, loosen the failing filter (:text/:visible/:exact)
- Increase wait: assert_selector('tr', count: 3, wait: 5)
- Prefer the predicate when you need a boolean: page.has_selector?('tr', count: 3)
Example fix
# before
page.assert_selector('table tbody tr', count: 5)
# after
page.assert_selector('table tbody tr', minimum: 1, wait: 5)
expect(page.all('table tbody tr').size).to eq(5) Defensive patterns
Strategy: retry
Validate before calling
n = page.all('table tbody tr').size
page.assert_selector('table tbody tr', count: n) if n.positive? Try / catch
begin
page.assert_selector('tr', minimum: 1, wait: 5)
rescue Capybara::ExpectationNotMet => e
puts e.message # lists actual matches and filter-excluded elements
raise
end Prevention
- Read the 'Also found ... not all filters' section before loosening selectors
- Start with minimum: 1 and tighten to count: once the page is deterministic
- Keep assert_selector wait: aligned with the slowest environment (CI)
When it happens
Trigger: page.assert_selector('table tr', count: 3) with 4 rows; element.assert_selector('li', minimum: 2) on an empty list; assert_selector(:field, 'Email', disabled: true) when the field is enabled; assert_selector('a', text: 'Home', visible: true) when the link is display:none.
Common situations: Timing races on dynamic pages, wrong counts after pagination/filtering, filters that silently exclude the intended elements, porting RSpec matchers (have_selector) to bare assert_* calls in minitest and hitting the same count semantics.
Related errors
- res.join(' or ')
- result.negative_failure_message
- result.failure_message
- Item does not match the provided selector
- Ambiguous match, found #{result.size} elements matching #{qu
AI-assisted analysis of teamcapybara/capybara@15b5fdb76e (2026-08-21).
Data as JSON: /api/errors/c30e9dd1529cd14f.
Report an issue: GitHub.