Permalink
Browse files

refactor locators to allow specifying multiple tags

  • Loading branch information...
1 parent 56c6e19 commit f169c188e75a6e2bb380acda03d06aca0a87c721 @jarmo jarmo committed Jan 11, 2012
@@ -1,25 +1,13 @@
module Watir
class InputElementCollections < ElementCollections
def each
- @container.input_element_locator(@how, @what, element_class::INPUT_TYPES, element_class).each {|element| yield element}
+ @container.locator_for(InputElementLocator, element_class::INPUT_TYPES, @how, @what, element_class).each {|element| yield element}
end
end
- class Frames < ElementCollections
- def each
- @container.locator_for(FrameLocator, @how, @what).each {|element| yield element}
- end
- end
-
- class Forms < ElementCollections
- def each
- @container.locator_for(FormLocator, @how, @what).each {|element| yield element}
- end
- end
-
class HTMLElements < ElementCollections
def each
- @container.locator_for(ElementLocator, @how, @what).each { |element| yield element }
+ @container.locator_for(TaggedElementLocator, ["*"], @how, @what, Element).each { |element| yield element }
end
end
@@ -45,7 +33,7 @@ class Inses < ElementCollections
def element_class; Ins; end
end
- %w[Link Li Map Area Image Table TableRow TableCell TableHeader TableFooter TableBody
+ %w[Form Frame Link Li Map Area Image Table TableRow TableCell TableHeader TableFooter TableBody
Label Pre P Span Div Dl Dt Dd Strong Em Del
Font H1 H2 H3 H4 H5 H6 Meta Ol Ul FieldSet Option].each do |element|
module_eval %Q{
@@ -98,20 +98,8 @@ def show_all_objects
# Not for external use, but cannot set to private due to usages in Element
# classes.
- def input_element_locator(how, what, types, klass=nil)
- locator = InputElementLocator.new self, types, klass
- locator.set_specifier how, what
- locator
- end
-
- def tagged_element_locator(tag, how, what, klass=nil)
- locator = TaggedElementLocator.new self, tag, klass
- locator.set_specifier how, what
- locator
- end
-
- def locator_for(locator_class, how, what)
- locator = locator_class.new self
+ def locator_for(locator_class, tags, how, what, klass)
+ locator = locator_class.new self, tags, klass
locator.set_specifier how, what
locator
end
@@ -32,9 +32,11 @@ def initialize(ole_object)
def locate
return if self.class == Element
- tag = self.class.const_defined?(:TAG) ? self.class::TAG : self.class.name.split("::").last
- @o = @container.tagged_element_locator(tag, @how, @what).locate
- end
+
+ tags = self.class.const_defined?(:TAG) ? [self.class::TAG] :
+ self.class.const_defined?(:TAGS) ? self.class::TAGS : [self.class.name.split("::").last.upcase]
+ @o = @container.locator_for(TaggedElementLocator, tags, @how, @what, self.class).locate
+ end
# Return the ole object, allowing any methods of the DOM that Watir doesn't support to be used.
def ole_object
@@ -30,7 +30,7 @@ def length
# iterate through each of the elements in the collection in turn
def each
- @container.tagged_element_locator(element_tag, @how, @what, element_class).each {|element| yield element}
+ @container.locator_for(TaggedElementLocator, element_tags, @how, @what, element_class).each {|element| yield element}
end
# allows access to a specific item in the collection
@@ -70,8 +70,10 @@ def element_class
Watir.const_get self.class.name.split("::").last.chop
end
- def element_tag
- element_class.const_defined?(:TAG) ? element_class::TAG : element_class.name.split("::").last
+ def element_tags
+ tags = element_class.const_defined?(:TAG) ? [element_class::TAG] :
+ element_class.const_defined?(:TAGS) ? element_class::TAGS : [element_class.name.split("::").last.upcase]
+ tags
end
end
end
View
@@ -1,6 +1,8 @@
module Watir
class Form < Element
+ TAG = 'FORM'
+
# * container - the containing object, normally an instance of IE
# * how - symbol - how we access the form (:name, :id, :index, :action, :method)
# * what - what we use to access the form
@@ -33,7 +35,7 @@ def method(arg = nil)
end
def locate
- @o = @container.locator_for(FormLocator, @how, @what).locate
+ @o = @container.locator_for(FormLocator, [self.class::TAG], @how, @what, self.class).locate
end
# Submit the data -- equivalent to pressing Enter or Return to submit a form.
View
@@ -1,13 +1,13 @@
module Watir
class Frame < Element
include PageContainer
- TAG = ['FRAME', 'IFRAME']
+ TAGS = ['FRAME', 'IFRAME']
attr_accessor :document
# Find the frame denoted by how and what in the container and return its ole_object
def locate
- frame, document = @container.locator_for(FrameLocator, @how, @what).locate
+ frame, document = @container.locator_for(FrameLocator, self.class::TAGS, @how, @what, self.class).locate
if frame && document
@o = frame
begin
@@ -2,9 +2,9 @@ module Watir
class InputElement < Element #:nodoc:all
def locate
- locator_or_element = @container.input_element_locator(@how, @what, self.class::INPUT_TYPES, self.class)
- @o = locator_or_element.is_a?(WIN32OLE) ? locator_or_element : locator_or_element.locate
+ @o = @container.locator_for(InputElementLocator, self.class::INPUT_TYPES, @how, @what, self.class).locate
end
+
def initialize(container, how, what)
set_container container
@how = how
View
@@ -3,6 +3,28 @@ class Locator
include Watir
include Watir::Exception
+ def initialize container, tags, klass
+ @container = container
+ @tags = tags
+ @klass = klass
+ end
+
+ def each
+ if has_excluding_specifiers?
+ locate_elements_by_xpath_css_ole.each do |element|
+ yield element
+ end
+ else
+ @tags.each do |tag|
+ each_element(tag) do |element|
+ next unless type_matches?(element.ole_object) && match_with_specifiers?(element)
+ yield element
+ end
+ end
+ end
+ nil
+ end
+
def document
@document ||= @container.document
end
@@ -32,8 +54,8 @@ def match_with_specifiers?(element)
return true if has_excluding_specifiers?
@specifiers.all? do |how, what|
how == :index ||
- ((how.to_s =~ /^data_.*/ && element.send(how) == what) ||
- match?(element, how, what)) && type_matches?(element.ole_object)
+ (how.to_s =~ /^data_.*/ && element.send(how) == what) ||
+ match?(element, how, what)
end
end
@@ -82,7 +104,9 @@ def locate_elements_by_xpath_css_ole
end
def type_matches?(el)
- @tag == "*" || (@tag && el.nodeName.downcase == @tag.downcase) || (@tags && (@tags.include?(el.tagname) || @tags.include?(el.invoke('type'))))
+ @tags == ["*"] ||
+ @tags.include?(el.tagName) ||
+ @tags.include?(el.invoke('type')) rescue false
end
def create_element ole_object
@@ -98,32 +122,12 @@ def element.locate; @o; end
end
class TaggedElementLocator < Locator
- def initialize(container, tag, klass)
- @container = container
- @tag = tag
- @klass = klass || Element
- end
-
- def each_element tag
+ def each_element(tag)
document.getElementsByTagName(tag).each do |ole_object|
yield create_element ole_object
end
end
- def each
- if has_excluding_specifiers?
- locate_elements_by_xpath_css_ole.each do |element|
- yield element
- end
- else
- each_element(@tag) do |element|
- next unless match_with_specifiers?(element)
- yield element
- end
- end
- nil
- end
-
def locate
el = locate_by_id
return el if el
@@ -142,7 +146,7 @@ def match?(element, how, what)
method = element.method(how)
rescue NameError
raise MissingWayOfFindingObjectException,
- "#{how} is an unknown way of finding a <#{@tag || @tags.join(", ")}> element (#{what})"
+ "#{how} is an unknown way of finding a <#{@tags.join(", ")}> element (#{what})"
end
case method.arity
when 0
@@ -151,20 +155,14 @@ def match?(element, how, what)
method.call(what)
else
raise MissingWayOfFindingObjectException,
- "#{how} is an unknown way of finding a <#{@tag || @tags.join(", ")}> element (#{what})"
+ "#{how} is an unknown way of finding a <#{@tags.join(", ")}> element (#{what})"
end
end
end
class FrameLocator < TaggedElementLocator
- def initialize(container)
- @container = container
- @tags = Frame::TAG
- @klass = Frame
- end
-
- def each_element tag
+ def each_element(tag)
frames = document.frames
i = 0
document.getElementsByTagName(tag).each do |ole_object|
@@ -175,16 +173,6 @@ def each_element tag
end
end
- def each
- @tags.each do |t|
- each_element(t) do |element|
- next unless match_with_specifiers?(element)
- yield element
- end
- end
- nil
- end
-
def locate
# do not locate frames by getElementById or by xpath since can't get the correct
# 'document' related with that ole_object like it's done in #each_element
@@ -197,10 +185,6 @@ def locate
end
class FormLocator < TaggedElementLocator
- def initialize(container)
- super(container, 'FORM', Form)
- end
-
def each_element(tag)
document.forms.each do |form|
yield create_element form
@@ -209,12 +193,6 @@ def each_element(tag)
end
class InputElementLocator < Locator
- def initialize container, tags, klass
- @container = container
- @tags = tags
- @klass = klass || Element
- end
-
def each_element
elements = locate_by_name || @container.__ole_inner_elements
elements.each do |object|
@@ -242,13 +220,13 @@ def each
end
else
each_element do |element|
- next unless @tags.include?(element.type) && match_with_specifiers?(element)
+ next unless type_matches?(element.ole_object) && match_with_specifiers?(element)
yield element
end
end
nil
end
-
+
# return true if the element matches the provided how and what
def match? element, how, what
begin
@@ -272,11 +250,4 @@ def locate_by_name
end
end
- # This is like the TaggedElementLocator but
- # get all the elements by forcing @tag to be '*'
- class ElementLocator < TaggedElementLocator
- def initialize(container)
- super(container, "*", Element)
- end
- end
end
View
@@ -239,7 +239,7 @@ def rows(how={}, what=nil)
# this class is a table cell - when called via the Table object
class TableCell < NonControlElement
- TAG = "TD"
+ TAGS = ["TH", "TD"]
alias to_s text

0 comments on commit f169c18

Please sign in to comment.