93 lines
2.2 KiB
Ruby
93 lines
2.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Capybara
|
|
module RSpecMatchers
|
|
module Compound
|
|
include ::RSpec::Matchers::Composable
|
|
|
|
def and(matcher)
|
|
Capybara::RSpecMatchers::Compound::And.new(self, matcher)
|
|
end
|
|
|
|
def and_then(matcher)
|
|
::RSpec::Matchers::BuiltIn::Compound::And.new(self, matcher)
|
|
end
|
|
|
|
def or(matcher)
|
|
Capybara::RSpecMatchers::Compound::Or.new(self, matcher)
|
|
end
|
|
|
|
class CapybaraEvaluator
|
|
def initialize(actual)
|
|
@actual = actual
|
|
@match_results = Hash.new { |h, matcher| h[matcher] = matcher.matches?(@actual) }
|
|
end
|
|
|
|
def matcher_matches?(matcher)
|
|
@match_results[matcher]
|
|
end
|
|
|
|
def reset
|
|
@match_results.clear
|
|
end
|
|
end
|
|
|
|
class And < ::RSpec::Matchers::BuiltIn::Compound::And
|
|
private
|
|
|
|
def match(_expected, actual)
|
|
@evaluator = CapybaraEvaluator.new(actual)
|
|
syncer = sync_element(actual)
|
|
begin
|
|
syncer.synchronize do
|
|
@evaluator.reset
|
|
raise ::Capybara::ElementNotFound unless [matcher_1_matches?, matcher_2_matches?].all?
|
|
true
|
|
end
|
|
rescue
|
|
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 Or < ::RSpec::Matchers::BuiltIn::Compound::Or
|
|
private
|
|
|
|
def match(_expected, actual)
|
|
@evaluator = CapybaraEvaluator.new(actual)
|
|
syncer = sync_element(actual)
|
|
begin
|
|
syncer.synchronize do
|
|
@evaluator.reset
|
|
raise ::Capybara::ElementNotFound unless [matcher_1_matches?, matcher_2_matches?].any?
|
|
true
|
|
end
|
|
rescue
|
|
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
|
|
end
|
|
end
|
|
end
|