# frozen_string_literal: true if defined?(::RSpec::Expectations::Version) module Capybara module RSpecMatchers module Matchers module Compound include ::RSpec::Matchers::Composable def and(matcher) And.new(self, matcher) end def and_then(matcher) ::RSpec::Matchers::BuiltIn::Compound::And.new(self, matcher) end def or(matcher) Or.new(self, matcher) end class CapybaraEvaluator def initialize(actual) @actual = actual @match_results = Hash.new { |hsh, matcher| hsh[matcher] = matcher.matches?(@actual) } end def matcher_matches?(matcher) @match_results[matcher] end def reset @match_results.clear end end # @api private module Synchronizer def match(_expected, actual) @evaluator = CapybaraEvaluator.new(actual) syncer = sync_element(actual) begin syncer.synchronize do @evaluator.reset raise ::Capybara::ElementNotFound unless synchronized_match? true end rescue StandardError false end end def sync_element(el) if el.respond_to? :synchronize el elsif el.respond_to? :current_scope el.current_scope else Capybara.string(el) end end end class And < ::RSpec::Matchers::BuiltIn::Compound::And include Synchronizer private def synchronized_match? [matcher_1_matches?, matcher_2_matches?].all? end end class Or < ::RSpec::Matchers::BuiltIn::Compound::Or include Synchronizer private def synchronized_match? [matcher_1_matches?, matcher_2_matches?].any? end end end end end end end