watir-webdriver 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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