watir-webdriver 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. data/Rakefile +53 -31
  2. data/VERSION +1 -1
  3. data/lib/watir-webdriver.rb +6 -8
  4. data/lib/watir-webdriver/attribute_helper.rb +121 -0
  5. data/lib/watir-webdriver/browser.rb +13 -6
  6. data/lib/watir-webdriver/collections/element_collection.rb +21 -15
  7. data/lib/watir-webdriver/collections/table_row_collection.rb +11 -0
  8. data/lib/watir-webdriver/container.rb +17 -11
  9. data/lib/watir-webdriver/element.rb +201 -0
  10. data/lib/watir-webdriver/elements/button.rb +19 -2
  11. data/lib/watir-webdriver/elements/checkbox.rb +24 -4
  12. data/lib/watir-webdriver/elements/file_field.rb +24 -4
  13. data/lib/watir-webdriver/elements/font.rb +10 -11
  14. data/lib/watir-webdriver/elements/frame.rb +11 -3
  15. data/lib/watir-webdriver/elements/generated.rb +2491 -1313
  16. data/lib/watir-webdriver/elements/hidden.rb +16 -5
  17. data/lib/watir-webdriver/elements/input.rb +44 -5
  18. data/lib/watir-webdriver/elements/link.rb +6 -8
  19. data/lib/watir-webdriver/elements/radio.rb +25 -6
  20. data/lib/watir-webdriver/elements/{select_list.rb → select.rb} +8 -9
  21. data/lib/watir-webdriver/elements/text_field.rb +32 -3
  22. data/lib/watir-webdriver/html.rb +18 -0
  23. data/lib/watir-webdriver/html/generator.rb +112 -0
  24. data/lib/watir-webdriver/html/idl_sorter.rb +49 -0
  25. data/lib/watir-webdriver/html/spec_extractor.rb +111 -0
  26. data/lib/watir-webdriver/html/util.rb +31 -0
  27. data/lib/watir-webdriver/html/visitor.rb +186 -0
  28. data/lib/watir-webdriver/locators/element_locator.rb +4 -0
  29. data/lib/watir-webdriver/locators/text_field_locator.rb +2 -2
  30. data/lib/watir-webdriver/xpath_support.rb +3 -5
  31. data/lib/yard/handlers/watir.rb +57 -0
  32. data/spec/{base_element_spec.rb → element_spec.rb} +3 -2
  33. data/spec/input_spec.rb +65 -0
  34. data/spec/spec_helper.rb +9 -2
  35. data/spec/watirspec/area_spec.rb +9 -13
  36. data/spec/watirspec/areas_spec.rb +7 -1
  37. data/spec/watirspec/browser_spec.rb +68 -72
  38. data/spec/watirspec/button_spec.rb +16 -9
  39. data/spec/watirspec/buttons_spec.rb +11 -9
  40. data/spec/watirspec/checkbox_spec.rb +1 -1
  41. data/spec/watirspec/checkboxes_spec.rb +7 -1
  42. data/spec/watirspec/collections_spec.rb +18 -0
  43. data/spec/watirspec/dd_spec.rb +1 -1
  44. data/spec/watirspec/dds_spec.rb +7 -1
  45. data/spec/watirspec/del_spec.rb +141 -0
  46. data/spec/watirspec/dels_spec.rb +37 -0
  47. data/spec/watirspec/div_spec.rb +6 -22
  48. data/spec/watirspec/divs_spec.rb +8 -2
  49. data/spec/watirspec/dl_spec.rb +1 -1
  50. data/spec/watirspec/dls_spec.rb +7 -1
  51. data/spec/watirspec/dt_spec.rb +1 -1
  52. data/spec/watirspec/dts_spec.rb +7 -1
  53. data/spec/watirspec/element_spec.rb +11 -20
  54. data/spec/watirspec/em_spec.rb +1 -1
  55. data/spec/watirspec/ems_spec.rb +7 -1
  56. data/spec/watirspec/filefield_spec.rb +8 -11
  57. data/spec/watirspec/filefields_spec.rb +7 -1
  58. data/spec/watirspec/font_spec.rb +2 -2
  59. data/spec/watirspec/form_spec.rb +10 -18
  60. data/spec/watirspec/forms_spec.rb +7 -1
  61. data/spec/watirspec/frame_spec.rb +69 -73
  62. data/spec/watirspec/frames_spec.rb +15 -2
  63. data/spec/watirspec/hidden_spec.rb +1 -1
  64. data/spec/watirspec/hiddens_spec.rb +7 -1
  65. data/spec/watirspec/hn_spec.rb +1 -1
  66. data/spec/watirspec/hns_spec.rb +23 -27
  67. data/spec/watirspec/image_spec.rb +9 -15
  68. data/spec/watirspec/images_spec.rb +7 -1
  69. data/spec/watirspec/ins_spec.rb +142 -0
  70. data/spec/watirspec/inses_spec.rb +37 -0
  71. data/spec/watirspec/label_spec.rb +1 -1
  72. data/spec/watirspec/labels_spec.rb +7 -1
  73. data/spec/watirspec/li_spec.rb +1 -1
  74. data/spec/watirspec/lib/guards.rb +12 -12
  75. data/spec/watirspec/lib/implementation.rb +48 -0
  76. data/spec/watirspec/lib/watirspec.rb +17 -12
  77. data/spec/watirspec/link_spec.rb +6 -11
  78. data/spec/watirspec/links_spec.rb +1 -1
  79. data/spec/watirspec/lis_spec.rb +7 -1
  80. data/spec/watirspec/map_spec.rb +1 -1
  81. data/spec/watirspec/maps_spec.rb +7 -1
  82. data/spec/watirspec/meta_spec.rb +13 -15
  83. data/spec/watirspec/metas_spec.rb +6 -1
  84. data/spec/watirspec/ol_spec.rb +57 -59
  85. data/spec/watirspec/ols_spec.rb +10 -4
  86. data/spec/watirspec/option_spec.rb +50 -83
  87. data/spec/watirspec/p_spec.rb +1 -1
  88. data/spec/watirspec/pre_spec.rb +1 -1
  89. data/spec/watirspec/pres_spec.rb +7 -1
  90. data/spec/watirspec/ps_spec.rb +7 -1
  91. data/spec/watirspec/radio_spec.rb +9 -11
  92. data/spec/watirspec/radios_spec.rb +1 -1
  93. data/spec/watirspec/select_list_spec.rb +27 -40
  94. data/spec/watirspec/select_lists_spec.rb +1 -1
  95. data/spec/watirspec/span_spec.rb +1 -1
  96. data/spec/watirspec/spans_spec.rb +7 -1
  97. data/spec/watirspec/spec_helper.rb +1 -0
  98. data/spec/watirspec/strong_spec.rb +1 -1
  99. data/spec/watirspec/strongs_spec.rb +7 -1
  100. data/spec/watirspec/table_bodies_spec.rb +22 -10
  101. data/spec/watirspec/table_body_spec.rb +33 -40
  102. data/spec/watirspec/table_cell_spec.rb +1 -1
  103. data/spec/watirspec/table_cells_spec.rb +36 -15
  104. data/spec/watirspec/table_footer_spec.rb +43 -40
  105. data/spec/watirspec/table_footers_spec.rb +35 -19
  106. data/spec/watirspec/table_header_spec.rb +44 -39
  107. data/spec/watirspec/table_headers_spec.rb +37 -19
  108. data/spec/watirspec/table_row_spec.rb +13 -9
  109. data/spec/watirspec/table_rows_spec.rb +16 -6
  110. data/spec/watirspec/table_spec.rb +83 -62
  111. data/spec/watirspec/tables_spec.rb +7 -1
  112. data/spec/watirspec/text_field_spec.rb +4 -6
  113. data/spec/watirspec/text_fields_spec.rb +1 -1
  114. data/spec/watirspec/ul_spec.rb +1 -1
  115. data/spec/watirspec/uls_spec.rb +25 -22
  116. data/support/html5.html +89235 -0
  117. data/watir-webdriver.gemspec +31 -21
  118. metadata +52 -23
  119. data/TODO +0 -15
  120. data/lib/watir-webdriver/base_element.rb +0 -361
  121. data/lib/watir-webdriver/collections/buttons_collection.rb +0 -15
  122. data/lib/watir-webdriver/collections/table_rows_collection.rb +0 -16
  123. data/lib/watir-webdriver/collections/text_fields_collection.rb +0 -15
  124. data/lib/watir-webdriver/elements/headings.rb +0 -48
  125. data/support/html5/html5.idl +0 -1274
  126. data/support/html5/old/html5.idl +0 -962
  127. data/support/html5/old/html5_extras.idl +0 -145
  128. data/support/html5/watir_visitor.rb +0 -173
  129. data/support/yard_handlers.rb +0 -87
data/Rakefile CHANGED
@@ -14,10 +14,12 @@ begin
14
14
  gem.add_dependency "selenium-webdriver", '>= 0.0.26'
15
15
 
16
16
  gem.add_development_dependency "rspec"
17
- gem.add_development_dependency "webidl"
17
+ gem.add_development_dependency "webidl", ">= 0.0.4"
18
18
  gem.add_development_dependency "sinatra", ">= 1.0"
19
+ gem.add_development_dependency "nokogiri"
19
20
  gem.add_development_dependency "activesupport", ">= 2.3.5" # for pluralization during code generation
20
21
  end
22
+
21
23
  Jeweler::GemcutterTasks.new
22
24
  rescue LoadError
23
25
  puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
@@ -38,57 +40,77 @@ end
38
40
 
39
41
  task :spec => :check_dependencies
40
42
 
43
+ task :lib do
44
+ $LOAD_PATH.unshift(File.expand_path("lib", File.dirname(__FILE__)))
45
+ end
46
+
41
47
  namespace :html5 do
42
- IDL_PATH = "support/html5/html5.idl"
43
- SPEC_URI = "http://dev.w3.org/html5/spec/Overview.html" # TODO: use http://www.whatwg.org/specs/web-apps/current-work/source
48
+ SPEC_URI = "http://www.whatwg.org/specs/web-apps/current-work/"
49
+ SPEC_PATH = "support/html5.html"
44
50
 
45
- desc "Print IDL parts from #{SPEC_URI}"
46
- task :extract do
47
- require "nokogiri"
51
+ task :html_lib => :lib do
52
+ require 'watir-webdriver/html'
53
+ end
54
+
55
+ desc "Download the HTML5 spec from #{SPEC_URI}"
56
+ task :download do
48
57
  require "open-uri"
49
- doc = Nokogiri.HTML(open(SPEC_URI))
50
- puts doc.search("//pre[@class='idl']").map { |e| e.inner_text }.join("\n\n")
58
+ mv SPEC_PATH, "#{SPEC_PATH}.old" if File.exist?(SPEC_PATH)
59
+ downloaded_bytes = 0
60
+
61
+ File.open(SPEC_PATH, "w") do |io|
62
+ io << "<!-- downloaded from #{SPEC_URI} on #{Time.now} -->\n"
63
+ io << data = open(SPEC_URI).read
64
+ downloaded_bytes = data.bytesize
65
+ end
66
+
67
+ puts "#{SPEC_URI} => #{SPEC_PATH} (#{downloaded_bytes} bytes)"
51
68
  end
52
69
 
53
- desc 'Re-enerate the base Watir element classes from the spec '
54
- task :generate do
55
- require "support/html5/watir_visitor"
70
+ desc "Print IDL parts from #{SPEC_URI}"
71
+ task :print => :html_lib do
72
+ extractor = Watir::HTML::SpecExtractor.new(SPEC_PATH)
56
73
 
57
- code = WatirVisitor.generate_from(IDL_PATH)
58
- old_file = "lib/watir-webdriver/elements/generated.rb"
74
+ extractor.process.each do |tag_name, interface_definitions|
75
+ puts "#{tag_name.ljust(10)} => #{interface_definitions.map { |e| e.name }}"
76
+ end
59
77
 
60
- File.open("#{old_file}.new", "w") { |file| file << code }
61
- if File.exist?(old_file)
62
- system "diff -Naut #{old_file} #{old_file}.new | less"
78
+ extractor.print_hierarchy
79
+
80
+ unless extractor.errors.empty?
81
+ puts "\n\n<======================= ERRORS =======================>\n\n"
82
+ puts extractor.errors.join("\n" + "="*80 + "\n")
63
83
  end
64
84
  end
65
85
 
66
- desc 'Check the syntax of support/html5/*.idl'
67
- task :syntax do
68
- require 'webidl'
69
- parser = WebIDL::Parser::IDLParser.new
70
- failures = []
71
- Dir['support/html5/*.idl'].each do |path|
72
- unless parser.parse(File.read(path))
73
- failures << [path, parser.failure_reason]
74
- end
86
+ desc 'Re-enerate the base Watir element classes from the spec '
87
+ task :generate => :html_lib do
88
+ old_file = "lib/watir-webdriver/elements/generated.rb"
89
+ generator = Watir::HTML::Generator.new
90
+
91
+ File.open("#{old_file}.new", "w") do |file|
92
+ generator.generate(SPEC_PATH, file)
75
93
  end
76
94
 
77
- if failures.any?
78
- puts "Parse errors!"
79
- failures.each { |path, reason| puts "#{path.ljust(40)}: #{reason}" }
80
- else
81
- puts "Syntax OK."
95
+ if File.exist?(old_file)
96
+ system "diff -Naut #{old_file} #{old_file}.new | less"
82
97
  end
83
98
  end
84
99
 
100
+ desc 'Move generated.rb.new to generated.rb'
101
+ task :overwrite do
102
+ file = "lib/watir-webdriver/elements/generated.rb"
103
+ mv "#{file}.new", file
104
+ end
105
+
85
106
  end # html5
86
107
 
87
108
  task :default => :spec
88
109
 
89
110
  begin
90
111
  require 'yard'
91
- require 'support/yard_handlers'
112
+ Rake::Task[:lib].invoke
113
+ require "yard/handlers/watir"
92
114
  YARD::Rake::YardocTask.new do |task|
93
115
  task.options = %w[--debug] # this is pretty slow, so nice with some output
94
116
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.6
1
+ 0.0.7
@@ -21,35 +21,33 @@ module Watir
21
21
  end
22
22
 
23
23
  def element_class_for(tag_name)
24
- tag_to_class[tag_name] || HTMLElement
24
+ tag_to_class[tag_name.to_sym] || HTMLElement
25
25
  end
26
26
  end
27
27
 
28
28
  end
29
29
 
30
- require "watir-webdriver/base_element"
30
+ require "watir-webdriver/attribute_helper"
31
+ require "watir-webdriver/element"
31
32
  require "watir-webdriver/collections/element_collection"
32
33
  require "watir-webdriver/elements/generated"
33
34
  require "watir-webdriver/elements/frame"
34
35
  require "watir-webdriver/elements/input"
35
36
  require "watir-webdriver/elements/button"
36
- require "watir-webdriver/collections/buttons_collection"
37
37
  require "watir-webdriver/elements/checkbox"
38
38
  require "watir-webdriver/elements/file_field"
39
- require "watir-webdriver/elements/font"
40
- require "watir-webdriver/elements/headings"
41
39
  require "watir-webdriver/elements/image"
42
40
  require "watir-webdriver/elements/link"
41
+ require "watir-webdriver/elements/font"
43
42
  require "watir-webdriver/elements/radio"
44
43
  require "watir-webdriver/elements/text_field"
45
- require "watir-webdriver/collections/text_fields_collection"
46
44
  require "watir-webdriver/elements/hidden"
47
- require "watir-webdriver/elements/select_list"
45
+ require "watir-webdriver/elements/select"
48
46
  require "watir-webdriver/elements/form"
49
47
  require "watir-webdriver/elements/option"
50
48
  require "watir-webdriver/elements/table"
51
49
  require "watir-webdriver/elements/table_row"
52
- require "watir-webdriver/collections/table_rows_collection"
50
+ require "watir-webdriver/collections/table_row_collection"
53
51
 
54
52
  Watir.tag_to_class.freeze
55
53
 
@@ -0,0 +1,121 @@
1
+ module Watir
2
+
3
+ #
4
+ # @private
5
+ #
6
+ # Extended by Element, provides methods for defining attributes on the element classes.
7
+ #
8
+
9
+ module AttributeHelper
10
+
11
+ IGNORED_ATTRIBUTES = [:text, :hash]
12
+
13
+ def typed_attributes
14
+ @typed_attributes ||= Hash.new { |hash, type| hash[type] = [] }
15
+ end
16
+
17
+ def attribute_list
18
+ @attribute_list ||= (
19
+ list = typed_attributes.values.flatten
20
+ list += ancestors[1..-1].map do |e|
21
+ e.attribute_list if e.respond_to?(:attribute_list)
22
+ end.compact.flatten
23
+ ).uniq
24
+ end
25
+
26
+ def attributes(attribute_map = nil)
27
+ attribute_map or return attribute_list
28
+
29
+ add_attributes attribute_map
30
+
31
+ attribute_map.each do |type, attribs|
32
+ attribs.each do |name|
33
+ # we don't want to override methods like :text or :hash
34
+ next if IGNORED_ATTRIBUTES.include?(name)
35
+ define_attribute(type, name)
36
+ end
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def define_attribute(type, name)
43
+ method_name = method_name_for(type, name)
44
+ attribute_name = attribute_for_method(name)
45
+
46
+ (@attributes ||= []) << attribute_name
47
+
48
+ case type
49
+ when :string
50
+ define_string_attribute(method_name, attribute_name)
51
+ when :bool
52
+ define_boolean_attribute(method_name, attribute_name)
53
+ when :int
54
+ define_int_attribute(method_name, attribute_name)
55
+ else
56
+ # $stderr.puts "treating #{type.inspect} as string for now"
57
+ end
58
+ end
59
+
60
+ def define_string_attribute(mname, aname)
61
+ define_method mname do
62
+ assert_exists
63
+ @element.attribute(aname).to_s
64
+ end
65
+ end
66
+
67
+ def define_boolean_attribute(mname, aname)
68
+ define_method mname do
69
+ assert_exists
70
+ !!@element.attribute(aname)
71
+ end
72
+ end
73
+
74
+ def define_int_attribute(mname, aname)
75
+ define_method mname do
76
+ assert_exists
77
+ @element.attribute(aname).to_i
78
+ end
79
+ end
80
+
81
+ def add_attributes(attributes)
82
+ attributes.each do |type, attr_list|
83
+ typed_attributes[type] += attr_list
84
+ end
85
+ end
86
+
87
+ def method_name_for(type, attribute)
88
+ # TODO: rethink this - this list could get pretty long...
89
+ name = case attribute
90
+ when :html_for
91
+ 'for'
92
+ when :col_span
93
+ 'colspan'
94
+ when :row_span
95
+ 'rowspan'
96
+ else
97
+ attribute.to_s
98
+ end
99
+
100
+ name << "?" if type == :bool
101
+
102
+ name
103
+ end
104
+
105
+ def attribute_for_method(method)
106
+ case method.to_sym
107
+ when :class_name
108
+ 'class'
109
+ when :html_for
110
+ 'for'
111
+ when :read_only
112
+ 'readonly'
113
+ when :http_equiv
114
+ 'http-equiv'
115
+ else
116
+ method.to_s
117
+ end
118
+ end
119
+
120
+ end # AttributeHelper
121
+ end # Watir
@@ -4,7 +4,7 @@ module Watir
4
4
  include Container
5
5
 
6
6
  attr_reader :driver
7
- alias_method :wd, :driver # ensures duck typing with BaseElement
7
+ alias_method :wd, :driver # ensures duck typing with Watir::Element
8
8
 
9
9
  class << self
10
10
  def start(url, browser = :firefox)
@@ -34,6 +34,7 @@ module Watir
34
34
 
35
35
  @error_checkers = []
36
36
  @current_frame = nil
37
+ @closed = false
37
38
  end
38
39
 
39
40
  def inspect
@@ -73,7 +74,9 @@ module Watir
73
74
  end
74
75
 
75
76
  def close
77
+ return if @closed
76
78
  @driver.quit
79
+ @closed = true
77
80
  end
78
81
  alias_method :quit, :close # TODO: close vs quit
79
82
 
@@ -99,7 +102,7 @@ module Watir
99
102
  end
100
103
 
101
104
  def execute_script(script, *args)
102
- args.map! { |e| e.kind_of?(Watir::BaseElement) ? e.element : e }
105
+ args.map! { |e| e.kind_of?(Watir::Element) ? e.element : e }
103
106
  returned = @driver.execute_script(script, *args)
104
107
 
105
108
  if returned.kind_of? WebDriver::Element
@@ -128,18 +131,22 @@ module Watir
128
131
  end
129
132
 
130
133
  #
131
- # Protocol shared with BaseElement
134
+ # Protocol shared with Watir::Element
132
135
  #
133
136
  # @api private
134
137
  #
135
138
 
136
139
  def assert_exists
137
- driver.switch_to.default_content
138
- true
140
+ if @closed
141
+ raise Error, "browser was closed"
142
+ else
143
+ driver.switch_to.default_content
144
+ true
145
+ end
139
146
  end
140
147
 
141
148
  def exist?
142
- true
149
+ not @closed
143
150
  end
144
151
 
145
152
  def browser
@@ -3,12 +3,13 @@ module Watir
3
3
  class ElementCollection
4
4
  include Enumerable
5
5
 
6
- def initialize(parent, element_class)
7
- @parent, @element_class = parent, element_class
6
+ def initialize(parent, selector)
7
+ @parent = parent
8
+ @selector = selector
8
9
  end
9
10
 
10
11
  #
11
- # @yieldparam [Watir::BaseElement] element Iterate through the elements in this collection.
12
+ # @yieldparam [Watir::Element] element Iterate through the elements in this collection.
12
13
  #
13
14
 
14
15
  def each(&blk)
@@ -32,54 +33,59 @@ module Watir
32
33
  # instance even if the index is out of bounds.
33
34
  #
34
35
  # @param [Fixnum] n Index of wanted element, 0-indexed
35
- # @return [Watir::BaseElement] Returns an instance of a Watir::BaseElement subclass
36
+ # @return [Watir::Element] Returns an instance of a Watir::Element subclass
36
37
  #
37
38
 
38
39
 
39
40
  def [](idx)
40
- to_a[idx] || @element_class.new(@parent, :index, idx)
41
+ to_a[idx] || element_class.new(@parent, :index => idx)
41
42
  end
42
43
 
43
44
  #
44
45
  # First element of this collection
45
46
  #
46
- # @return [Watir::BaseElement] Returns an instance of a Watir::BaseElement subclass
47
+ # @return [Watir::Element] Returns an instance of a Watir::Element subclass
47
48
  #
48
49
 
49
50
  def first
50
- to_a[0] || @element_class.new(@parent, :index, 0)
51
+ to_a[0] || element_class.new(@parent, :index => 0)
51
52
  end
52
53
 
53
54
  #
54
55
  # Last element of the collection
55
56
  #
56
- # @return [Watir::BaseElement] Returns an instance of a Watir::BaseElement subclass
57
+ # @return [Watir::Element] Returns an instance of a Watir::Element subclass
57
58
  #
58
59
 
59
60
  def last
60
- to_a[-1] || @element_class.new(@parent, :index, -1)
61
+ to_a[-1] || element_class.new(@parent, :index => -1)
61
62
  end
62
63
 
63
64
  #
64
65
  # This collection as an Array
65
66
  #
66
- # @return [Array<Watir::BaseElement>]
67
+ # @return [Array<Watir::Element>]
67
68
  #
68
69
 
69
70
  def to_a
70
- # TODO: optimize - lazily @element_class instance
71
- @to_a ||= elements.map { |e| @element_class.new(@parent, :element, e) }
71
+ # TODO: optimize - lazy element_class instance?
72
+ @to_a ||= elements.map { |e| element_class.new(@parent, :element => e) }
72
73
  end
73
74
 
74
75
  private
75
76
 
76
77
  def elements
77
- @elements ||= ElementLocator.new(
78
+ @elements ||= locator_class.new(
78
79
  @parent.wd,
79
- @element_class.default_selector,
80
- @element_class.attribute_list
80
+ @selector,
81
+ element_class.attribute_list
81
82
  ).locate_all
82
83
  end
83
84
 
85
+ # overridable by subclasses
86
+ def locator_class
87
+ ElementLocator
88
+ end
89
+
84
90
  end # ElementCollection
85
91
  end # Watir
@@ -0,0 +1,11 @@
1
+ module Watir
2
+ class TableRowCollection < ElementCollection
3
+
4
+ private
5
+
6
+ def locator_class
7
+ @parent.kind_of?(Watir::Table) ? TableRowLocator : super
8
+ end
9
+
10
+ end # TrCollection
11
+ end # Watir