Support passing evaluation context to filers

This commit is contained in:
Thomas Walpole 2018-11-09 16:03:53 -08:00
parent 66689fd352
commit 0c4857e3e1
3 changed files with 26 additions and 9 deletions

View File

@ -7,9 +7,18 @@ module Capybara
def initialize(name, matcher, block, **options)
@name = name
@matcher = matcher
@block = block
@options = options
@options[:valid_values] = [true, false] if options[:boolean]
@block = if boolean?
proc do |node, value|
error_cnt = errors.size
block.call(node, value).tap do |res|
add_error("Expected #{@name} #{value} but it wasn't") if !res && error_cnt == errors.size
end
end
else
block
end
end
def default?
@ -28,6 +37,10 @@ module Capybara
!@matcher.nil?
end
def boolean?
!!@options[:boolean]
end
def handles_option?(option_name)
if matcher?
option_name =~ @matcher
@ -38,17 +51,21 @@ module Capybara
private
def apply(subject, name, value, skip_value)
def apply(subject, name, value, skip_value, ctx)
return skip_value if skip?(value)
raise ArgumentError, "Invalid value #{value.inspect} passed to #{self.class.name.split('::').last} #{name}#{" : #{@name}" if @name.is_a?(Regexp)}" unless valid_value?(value)
if @block.arity == 2
@block.call(subject, value)
filter_context(ctx).instance_exec(subject, value, &@block)
else
@block.call(subject, name, value)
filter_context(ctx).instance_exec(subject, name, value, &@block)
end
end
def filter_context(context)
context || @block.binding.receiver
end
def valid_value?(value)
return true unless @options.key?(:valid_values)

View File

@ -6,8 +6,8 @@ module Capybara
class Selector
module Filters
class ExpressionFilter < Base
def apply_filter(expr, name, value)
apply(expr, name, value, expr)
def apply_filter(expr, name, value, selector)
apply(expr, name, value, expr, selector)
end
end
@ -15,7 +15,7 @@ module Capybara
def initialize(name); super(name, nil, nil); end
def default?; false; end
def matcher?; false; end
def apply_filter(expr, _name, _value); expr; end
def apply_filter(expr, _name, _value, _ctx); expr; end
end
end
end

View File

@ -6,8 +6,8 @@ module Capybara
class Selector
module Filters
class NodeFilter < Base
def matches?(node, name, value)
apply(node, name, value, true)
def matches?(node, name, value, context=nil)
apply(node, name, value, true, context)
rescue Capybara::ElementNotFound
false
end