{"record":{"id":"20c88d1cb8ef7d9a","repo":"teamcapybara/capybara","slug":"the-have-all-selectors-matcher-does-not-support-us","errorCode":null,"errorMessage":"The have_all_selectors matcher does not support use with not_to/should_not","messagePattern":"The have_all_selectors matcher does not support use with not_to/should_not","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/capybara/rspec/matchers/have_selector.rb","lineNumber":40,"sourceCode":"\n        def element_does_not_match?(el)\n          el.assert_no_selector(*@args, **session_query_options, &@filter_block)\n        end\n\n        def description = \"have #{query.description}\"\n\n        def query\n          @query ||= Capybara::Queries::SelectorQuery.new(*session_query_args, **session_query_options, &@filter_block)\n        end\n      end\n\n      class HaveAllSelectors < WrappedElementMatcher\n        def element_matches?(el)\n          el.assert_all_of_selectors(*@args, **session_query_options, &@filter_block)\n        end\n\n        def does_not_match?(_actual)\n          raise ArgumentError, 'The have_all_selectors matcher does not support use with not_to/should_not'\n        end\n\n        def description = 'have all selectors'\n      end\n\n      class HaveNoSelectors < WrappedElementMatcher\n        def element_matches?(el)\n          el.assert_none_of_selectors(*@args, **session_query_options, &@filter_block)\n        end\n\n        def does_not_match?(_actual)\n          raise ArgumentError, 'The have_none_of_selectors matcher does not support use with not_to/should_not'\n        end\n\n        def description = 'have no selectors'\n      end\n\n      class HaveAnySelectors < WrappedElementMatcher","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/teamcapybara/capybara/blob/15b5fdb76e972e9623d5af2123ed3755594f9732/lib/capybara/rspec/matchers/have_selector.rb#L22-L58","documentation":"The RSpec matcher HaveAllSelectors implements does_not_match? by raising ArgumentError. 'Not all selectors present' is ambiguous (how many? which ones?), so Capybara forbids negating have_all_selectors with not_to/should_not. The positive form asserts every given selector is present via assert_all_of_selectors.","triggerScenarios":"expect(page).not_to have_all_selectors('.header', '.footer'); should_not have_all_selectors(:field, 'Email') - RSpec calls does_not_match? and the matcher raises immediately.","commonSituations":"RSpec cops or shared examples mechanically rewriting to to not_to; developers writing 'the page should not show all of these sections' one-liners; copy-pasting a negated have_selector pattern onto the aggregate matcher without rethinking the intent.","solutions":["State the real expectation positively: expect(page).to have_selector('.header') and a separate expectation for whatever absence you meant.","If you meant 'none of these exist', use the positive form of the none matcher: expect(page).to have_none_of_selectors('.header', '.footer').","If you meant 'at least one exists', assert that single selector with have_selector instead of negating the all-form.","Audit auto-generated negations (RuboCop RSpec/NotToNot rewrites or matcher wrappers) that flip to to not_to mechanically."],"exampleFix":"# before\nexpect(page).not_to have_all_selectors('.header', '.footer')\n\n# after\nexpect(page).to have_none_of_selectors('.header', '.footer')","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never mechanically flip to to not_to; for these aggregate matchers decide what absence you actually mean and use the matching positive matcher.","Add a grep check in CI (e.g. rg 'not_to have_all_selectors') to catch regressions in shared examples."],"tags":["ruby","capybara","rspec","matchers"],"backgroundTag":"matcher-negation-unsupported","analyzedSha":"15b5fdb76e972e9623d5af2123ed3755594f9732","analyzedAt":"2026-08-21T16:53:45.588Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}