From 87e6796ded2341ab2c1bd118ef03334a6bd74d95 Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Wed, 17 Feb 2010 17:10:33 +0100 Subject: [PATCH] pick the matching type (equals/contains) based on the attribute name so that users aren't required to have that knowledge --- TODO | 2 +- lib/locator/dom/htmlunit/element.rb | 6 +++--- lib/locator/element.rb | 6 +++--- lib/locator/element/area.rb | 2 +- lib/locator/element/button.rb | 4 ++-- lib/locator/element/form.rb | 2 +- lib/locator/element/form_element.rb | 8 +++++++- lib/locator/element/input.rb | 2 +- lib/locator/element/label.rb | 2 +- lib/locator/element/select.rb | 2 +- lib/locator/element/select_option.rb | 2 +- lib/locator/element/text_area.rb | 2 +- lib/locator/result.rb | 28 ++++++++++++++++++++++------ lib/locator/xpath.rb | 4 ++++ test/locator/element_test.rb | 5 +++++ 15 files changed, 54 insertions(+), 23 deletions(-) diff --git a/TODO b/TODO index 3d0cd6f..6298d2c 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,4 @@ -somehow allow these? +Somehow allow these? locate(html, :foo) { locate(:bar) } within(html, :foo) { locate(:bar) } \ No newline at end of file diff --git a/lib/locator/dom/htmlunit/element.rb b/lib/locator/dom/htmlunit/element.rb index cb9a814..f90b81c 100644 --- a/lib/locator/dom/htmlunit/element.rb +++ b/lib/locator/dom/htmlunit/element.rb @@ -21,9 +21,9 @@ def xpath element.getCanonicalXPath end - # def css_path - # element.css_path.to_s - # end + def css_path + raise 'not implemented' + end def content # TODO HtmlUnit has asText and getTextContent diff --git a/lib/locator/element.rb b/lib/locator/element.rb index 3e2f57a..3cacf14 100644 --- a/lib/locator/element.rb +++ b/lib/locator/element.rb @@ -24,10 +24,10 @@ class Element attr_reader :name, :css, :locatables, :attributes def initialize(*args) - options, name = args.last.is_a?(Hash) ? args.pop : {}, args.pop + attributes, name = args.last.is_a?(Hash) ? args.pop : {}, args.pop @name = name - @attributes = options.slice!(:equals, :matches) - @locatables = { :equals => :id, :matches => :content }.merge(options || {}) + @attributes = attributes + @locatables = ((attributes.delete(:matches) || [:content]) + [:id]).uniq end def locate(*args) diff --git a/lib/locator/element/area.rb b/lib/locator/element/area.rb index 90d58c2..2d2b299 100644 --- a/lib/locator/element/area.rb +++ b/lib/locator/element/area.rb @@ -2,7 +2,7 @@ module Locator class Element class Area < Element def initialize - super(:area, :equals => [:id], :matches => [:alt]) + super(:area, :matches => [:alt]) end end end diff --git a/lib/locator/element/button.rb b/lib/locator/element/button.rb index d3e1745..2147712 100644 --- a/lib/locator/element/button.rb +++ b/lib/locator/element/button.rb @@ -2,8 +2,8 @@ module Locator class Element class Button < ElementsList def initialize - input = Element.new(:input, :equals => [:id, :name], :matches => [:value], :type => %w(submit button image)) - button = Element.new(:button, :equals => [:id, :name], :matches => [:content]) + input = Element.new(:input, :matches => [:value], :type => %w(submit button image)) + button = Element.new(:button, :matches => [:content]) super(input, button) end end diff --git a/lib/locator/element/form.rb b/lib/locator/element/form.rb index 7fe5f4b..2d211f2 100644 --- a/lib/locator/element/form.rb +++ b/lib/locator/element/form.rb @@ -2,7 +2,7 @@ module Locator class Element class Form < Element def initialize - super(:form, :equals => [:id, :name]) + super(:form) end end end diff --git a/lib/locator/element/form_element.rb b/lib/locator/element/form_element.rb index 71fa5b2..1cc22ba 100644 --- a/lib/locator/element/form_element.rb +++ b/lib/locator/element/form_element.rb @@ -1,8 +1,14 @@ module Locator class Element class FormElement < Element + def initialize(name, attributes = {}) + attributes[:matches] ||= [] + attributes[:matches] << :name + super + end + def lookup(dom, selector, attributes) - super(dom, selector, attributes) + LabeledElement.new(name).send(:lookup, dom, selector, attributes) + super(dom, selector, attributes) + LabeledElement.new(name).send(:lookup, dom, selector, attributes.dup) end end end diff --git a/lib/locator/element/input.rb b/lib/locator/element/input.rb index 3719e18..2acb087 100644 --- a/lib/locator/element/input.rb +++ b/lib/locator/element/input.rb @@ -2,7 +2,7 @@ module Locator class Element class Input < FormElement def initialize(attributes = {}) - defaults = { :equals => [:id, :name], :type => [:text, :password , :email, :url, :search, :tel, :color] } + defaults = { :type => [:text, :password , :email, :url, :search, :tel, :color] } super(:input, defaults.merge(attributes)) end end diff --git a/lib/locator/element/label.rb b/lib/locator/element/label.rb index 33203b8..d44b7b3 100644 --- a/lib/locator/element/label.rb +++ b/lib/locator/element/label.rb @@ -2,7 +2,7 @@ module Locator class Element class Label < Element def initialize - super(:label, :equals => [:id, :content]) + super(:label, :matches => [:content]) end end end diff --git a/lib/locator/element/select.rb b/lib/locator/element/select.rb index f90ad70..51d0123 100644 --- a/lib/locator/element/select.rb +++ b/lib/locator/element/select.rb @@ -2,7 +2,7 @@ module Locator class Element class Select < FormElement def initialize - super(:select, :equals => [:id, :name]) + super(:select) end end end diff --git a/lib/locator/element/select_option.rb b/lib/locator/element/select_option.rb index f1c1d85..2802859 100644 --- a/lib/locator/element/select_option.rb +++ b/lib/locator/element/select_option.rb @@ -2,7 +2,7 @@ module Locator class Element class SelectOption < Element def initialize - super(:option, :equals => [:id, :value, :content]) + super(:option, :matches => [:value, :content]) end end end diff --git a/lib/locator/element/text_area.rb b/lib/locator/element/text_area.rb index c837a68..546649f 100644 --- a/lib/locator/element/text_area.rb +++ b/lib/locator/element/text_area.rb @@ -2,7 +2,7 @@ module Locator class Element class TextArea < FormElement def initialize - super(:textarea, :equals => [:id, :name]) + super(:textarea) end end end diff --git a/lib/locator/result.rb b/lib/locator/result.rb index c193084..07c2ec3 100644 --- a/lib/locator/result.rb +++ b/lib/locator/result.rb @@ -1,13 +1,29 @@ module Locator class Result < Array + MATCH_TYPES = { + :alt => :contains, + :title => :contains, + :content => :contains + } + class << self + def matches?(name, value, selector) + value = normalize_whitespace(value) + case selector + when Regexp + value =~ selector + else + type = MATCH_TYPES[name] || :equals + send("#{type}?", value, selector) + end + end + def equals?(value, selector) value == selector end - def matches?(value, selector) - value = normalize_whitespace(value) - Regexp === selector ? value =~ selector : value.include?(selector) + def contains?(value, selector) + value.include?(selector) end def normalize_whitespace(value) @@ -20,7 +36,7 @@ def filter!(selector, locatables) end def filter(selector, locatables) - selector ? locatables.map { |(type, attrs)| filter_by(type, selector, attrs) }.flatten : self + selector ? filter_by(selector, locatables) : self end def sort! @@ -34,11 +50,11 @@ def +(other) protected - def filter_by(type, selector, attributes) + def filter_by(selector, attributes) select do |element| Array(attributes).any? do |name| value = name == :content ? element.content : element.attribute(name.to_s) - element.matches << value if self.class.send("#{type}?", value, selector) + element.matches << value if self.class.matches?(name, value, selector) end end end diff --git a/lib/locator/xpath.rb b/lib/locator/xpath.rb index de73344..39cd4d6 100644 --- a/lib/locator/xpath.rb +++ b/lib/locator/xpath.rb @@ -46,6 +46,10 @@ def and!(other) replace(self.map { |l| other.map { |r| "#{l}#{r}" } }) end + def or!(other) + other.empty? ? self : replace([self.dup, other]) + end + def to_s flatten.join(' | ') end diff --git a/test/locator/element_test.rb b/test/locator/element_test.rb index ef36bd6..c14ce73 100644 --- a/test/locator/element_test.rb +++ b/test/locator/element_test.rb @@ -29,6 +29,11 @@ class LocatorElementTest < Test::Unit::TestCase assert_equal ".//div[@type=\"type\"] | .//p[@type=\"type\"]", xpath end + test "xpath merges given attributes with element attributes" do + xpath = Element.new(:div, :foo => 'foo').xpath(:bar => 'bar') + assert_equal ".//div[@foo=\"foo\"][@bar=\"bar\"]", xpath + end + # all test "all selects all elements when given no attributes" do