From 0c4857e3e114de381b5abe223971b8bd8ca5faa6 Mon Sep 17 00:00:00 2001 From: Thomas Walpole Date: Fri, 9 Nov 2018 16:03:53 -0800 Subject: [PATCH] Support passing evaluation context to filers --- lib/capybara/selector/filters/base.rb | 25 ++++++++++++++++--- .../selector/filters/expression_filter.rb | 6 ++--- lib/capybara/selector/filters/node_filter.rb | 4 +-- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/lib/capybara/selector/filters/base.rb b/lib/capybara/selector/filters/base.rb index 2ddeaa1c..3cd6acc0 100644 --- a/lib/capybara/selector/filters/base.rb +++ b/lib/capybara/selector/filters/base.rb @@ -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) diff --git a/lib/capybara/selector/filters/expression_filter.rb b/lib/capybara/selector/filters/expression_filter.rb index c2ec5431..f96a0418 100644 --- a/lib/capybara/selector/filters/expression_filter.rb +++ b/lib/capybara/selector/filters/expression_filter.rb @@ -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 diff --git a/lib/capybara/selector/filters/node_filter.rb b/lib/capybara/selector/filters/node_filter.rb index 75b99bda..73f0b289 100644 --- a/lib/capybara/selector/filters/node_filter.rb +++ b/lib/capybara/selector/filters/node_filter.rb @@ -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