Module: Vapir::Container

Included in:
PageContainer
Defined in:
lib/vapir-common/container.rb

Defined Under Namespace

Modules: WatirContainerConfigCompatibility

Class Method Summary collapse

Class Method Details

.assert_exists(options = {}) ⇒ Object

asserts that this element exists - optionally, takes a block, and other calls to assert_exists over the course of the block will not cause redundant assertions.



104
105
106
107
108
109
110
111
112
# File 'lib/vapir-common/container.rb', line 104

def assert_exists(options={})
  # yeah, this line is an unreadable mess, but I have to skip over it so many times debugging that it's worth just sticking it on one line 
  (was_asserting_exists=@asserting_exists); (locate! if !@asserting_exists || options[:force]); (@asserting_exists=true)
  begin; result=yield if block_given?
  ensure
    @asserting_exists=was_asserting_exists
  end
  result
end

.base_extra_for_containedObject Also known as: extra_for_contained



172
173
174
175
176
177
# File 'lib/vapir-common/container.rb', line 172

def base_extra_for_contained
  extra={:container => self}
  extra[:browser]= browser if respond_to?(:browser)
  extra[:page_container]= page_container if respond_to?(:page_container)
  extra
end

.base_innermost_by_node(match_proc) ⇒ Object Also known as: innermost_by_node

takes one argument, a proc. this will be yielded successive dom nodes, and should return true if the node matches whatever criteria you care to match; false otherwise.

returns an ElementCollection consisting of the deepest elements within the dom heirarchy which match the given match_proc_or_function.



240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
# File 'lib/vapir-common/container.rb', line 240

def base_innermost_by_node(match_proc)
  ElementCollection.new(self, base_element_class, extra_for_contained.merge(:candidates => proc do |container|
    ycomb do |innermost_matching_nodes|
      proc do |container_node|
        child_nodes = Vapir::Element.object_collection_to_enumerable(container_node.childNodes)
        matched_child_elements=child_nodes.select do |node|
          node.nodeType==1 && match_proc.call(node)
        end
        if matched_child_elements.empty?
          [container_node]
        else
          matched_child_elements.map do |matched_child_element|
            innermost_matching_nodes.call(matched_child_element)
          end.inject([], &:+)
        end
      end
    end.call(container.containing_object)
  end))
end

.base_innermost_matching_visible_text(text_or_regexp) ⇒ Object Also known as: innermost_matching_visible_text

takes text or regexp, and returns an ElementCollection consisting of deepest (innermost) elements in the dom heirarchy whose visible text matches what’s given (by substring for text; by regexp match for regexp)



262
263
264
265
266
# File 'lib/vapir-common/container.rb', line 262

def base_innermost_matching_visible_text(text_or_regexp)
  innermost_by_node(proc do |node|
    visible_text_nodes_method.call(node, document_object).join('')[text_or_regexp] # String#[] works with either text or regexp - returns the matched substring or nil 
  end)
end

.contains_text?(match) ⇒ Boolean Also known as: contains_text

Checks if this container’s text includes the given regexp or string. Returns true if the container’s #text matches the given String or Regexp; otherwise false.

Deprecated Instead use

Container#text.include? target

or

Container#text.match target

Returns:

  • (Boolean)


201
202
203
204
205
206
207
208
209
# File 'lib/vapir-common/container.rb', line 201

def contains_text?(match)
  if match.kind_of? Regexp
    !!(text =~ match)
  elsif match.kind_of? String
    text.include?(match)
  else
    raise TypeError, "Expected String or Regexp, got #{match.inspect} (#{match.class.name})"
  end
end

.element_by_howwhat(klass, first, second, other = {}) ⇒ Object

returns an Element of the given class klass with the specified how & what, and with self as its container. takes options:

  • :locate => true, false, :assert, or :nil_unless_exists

    whether the element should locate itself. 
    - false -  will not attempt to locate element at all
    - true - will try to locate element but not complain if it can't
    - :assert - will raise UnkownObjectException if it can't locate. 
    - :nil_unless_exists - will attempt to locate the element, and only return it if 
      successful - returns nil otherwise.
    
  • :other_attributes => Hash, attributes other than the given how/what to look for. This is

    used by radio and checkbox to specify :value (the third argument).
    

the arguments ‘first’ and ‘second’ (they are the first and second arguments given to the container method, not to this method) correspond to ‘how’ and ‘what, after a fashion.

see also #extra_for_contained on inheriting classes (IE::Element, Firefox::Element) for what this passes to the created element, in terms of browser, container, other things each element uses.



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/vapir-common/container.rb', line 24

def element_by_howwhat(klass, first, second, other={})
  other={:other_attributes => nil}.merge(other)
  
  how, what, index= *normalize_how_what_index(first, second, klass)

  if other[:other_attributes]
    if how==:attributes
      what.merge!(other[:other_attributes])
    else
      raise ArgumentError, "other attributes were given, but we are not locating by attributes. We are locating by how=#{how.inspect} what=#{what.inspect}. other attributes given were #{other[:other_attributes].inspect}"
    end
  end
  extra=extra_for_contained.merge(:index => index)
  extra.merge!(other[:extra]) if other[:extra]
  if !other.key?(:locate)
    element=klass.new(how, what, extra)
  elsif other[:locate]==:nil_unless_exists
    element=klass.new(how, what, extra.merge(:locate => true))
    element.exists? ? element : nil
  else
    element=klass.new(how, what, extra.merge(:locate => other[:locate]))
  end
end

.element_class_for(common_module) ⇒ Object

for a common module, such as a TextField, returns an elements-specific class (such as Firefox::TextField) that inherits from the base_element_class of self. That is, this returns a sibling class, as it were, of whatever class inheriting from Element is instantiated.



221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/vapir-common/container.rb', line 221

def element_class_for(common_module)
  element_class=nil
  ObjectSpace.each_object(Class) do |klass|
    if klass < common_module && klass <= base_element_class && (!element_class || element_class < klass)
      element_class= klass
    end
  end
  unless element_class
    raise RuntimeError, "No class found that inherits from both #{common_module} and #{base_element_class}"
  end
  element_class
end

.element_object_style(element_object, document_object) ⇒ Object

this is defined on each class to reflect the browser’s particular implementation.



213
214
215
# File 'lib/vapir-common/container.rb', line 213

def element_object_style(element_object, document_object)
  base_element_class.element_object_style(element_object, document_object)
end

.handling_existence_failure(options = {}) ⇒ Object Also known as: base_handling_existence_failure

catch exceptions that indicate some failure of something existing.

takes an options hash:

  • :handle indicates how the method should handle an encountered exception. value may be:

    • :ignore (default) - the exception is ignored and nil is returned.

    • :raise - the exception is raised (same as if this method weren’t used at all).

    • :return - returns the exception which was raised.

    • Proc, Method - the proc or method is called with the exception as an argument.

  • :assert_exists causes the method to check existence before yielding to the block. value may be:

    • :force (default) - assert_exists(:force => true) is called so that existence is checked even if we’re inside an assert_exists block already. this is the most common case, since this method is generally used when the element may have recently stopped existing.

    • true - assert_exists is called (without the :force option)

    • false - assert_exists is not called.

If no exception was raised, then the result of the give block is returned. – this may be overridden elsewhere to deal with any other stuff that indicates failure to exist, as it is to catch WIN32OLERuntimeErrors for Vapir::IE.



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/vapir-common/container.rb', line 134

def handling_existence_failure(options={})
  options=handle_options(options, {:assert_exists => :force}, [:handle])
  begin
    case options[:assert_exists]
    when true
      assert_exists
    when :force
      assert_exists(:force => true)
    when false, nil
    else
      raise ArgumentError, "option :assert_exists should be true, false, or :force; got #{options[:assert_exists].inspect}"
    end
    yield
  rescue Vapir::Exception::ExistenceFailureException
    handle_existence_failure($!, options.reject{|k,v| ![:handle].include?(k) })
  end
end

.normalize_how_what_index(first, second, klass) ⇒ Object

figure out how and what from the form(s) that users give to the container methods, and translate that to real how and what where ‘how’ is one of Vapir::ElementObjectCandidates::HowList and ‘what’ corresponds. this also determines index, when appropriate.



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/vapir-common/container.rb', line 52

def normalize_how_what_index(first, second, klass)
  case first
  when nil
    if second==nil
      how, what, index = nil, nil, nil
    else
      raise Vapir::Exception::MissingWayOfFindingObjectException, "first argument ('how') was nil but second argument ('what') was given as #{second.inspect}"
    end
  when Hash
    how=:attributes
    what=first.dup
    index=what.delete(:index)
    unless second==nil
      raise(ArgumentError, "first argument was given as a Hash, so assumed to be the 'what' for how=:attributes, but a second argument was also given. arguments were #{first.inspect}, #{second.inspect}")
    end
  when String, Symbol
    if Vapir::ElementObjectCandidates::HowList.include?(first)
      how=first
      what=second
      index=nil
    else
      if second.nil?
        if klass.default_how
          how=:attributes
          what={klass.default_how => first}
          index=nil
        else
          raise Vapir::Exception::MissingWayOfFindingObjectException, "Cannot search using arguments #{first.inspect} (#{first.class}) and #{second.inspect} (#{second.class})"
        end
      elsif first==:index # index isn't a real 'how' 
        how=nil
        what=nil
        index=second
      else
        if klass.all_dom_attr_aliases.any?{|(dom_attr, aliases)| aliases.include?(first.to_sym) || dom_attr==first.to_sym}
          how=:attributes
          what={first.to_sym => second}
          index=nil
        else
          raise Vapir::Exception::MissingWayOfFindingObjectException, "Cannot search for a #{klass} using the given argument: #{first.inspect} (other argument was #{second.inspect})"
        end
      end
    end
  else
    raise Vapir::Exception::MissingWayOfFindingObjectException, "Locating with the given arguments is not recognized or supported: #{first.inspect}, #{second.inspect}"
  end
  return [how, what, index]
end

.show_all_objects(write_to = $stdout) ⇒ Object

shows the available objects on the current container. This is usually only used for debugging or writing new test scripts. This is a nice feature to help find out what HTML objects are on a page when developing a test case using Vapir.

Typical Usage:

browser.show_all_objects
browser.div(:id, 'foo').show_all_objects

API: no



366
367
368
369
370
371
372
373
374
# File 'lib/vapir-common/container.rb', line 366

def show_all_objects(write_to=$stdout)
  # this used to reject tagNames 'br', 'hr', 'doctype', 'meta', and elements with no tagName
  elements.map do |element| 
    element=element.to_subtype
    write_to.write element.to_s+"\n"
    write_to.write '-'*42+"\n"
    element
  end
end

.visible_textObject

returns an visible text inside this element by concatenating text nodes below this element in the DOM heirarchy which are visible.



188
189
190
191
# File 'lib/vapir-common/container.rb', line 188

def visible_text
  # TODO: needs tests 
  visible_text_nodes.join('')
end

.visible_text_nodesObject

returns an array of text nodes below this element in the DOM heirarchy which are visible - that is, their parent element is visible.



182
183
184
185
186
# File 'lib/vapir-common/container.rb', line 182

def visible_text_nodes
  assert_exists do
    visible_text_nodes_method.call(containing_object, document_object)
  end
end