watir 7.1.0 → 7.2.0

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 (253) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/chrome.yml +29 -16
  3. data/.github/workflows/edge.yml +19 -11
  4. data/.github/workflows/firefox.yml +28 -16
  5. data/.github/workflows/ie.yml +13 -7
  6. data/.github/workflows/safari.yml +22 -11
  7. data/.github/workflows/unit.yml +31 -23
  8. data/.rubocop.yml +14 -7
  9. data/.rubocop_todo.yml +0 -26
  10. data/CHANGES.md +16 -1
  11. data/Gemfile +6 -1
  12. data/README.md +15 -11
  13. data/Rakefile +9 -7
  14. data/lib/watir/adjacent.rb +3 -1
  15. data/lib/watir/after_hooks.rb +5 -3
  16. data/lib/watir/alert.rb +2 -0
  17. data/lib/watir/aliases.rb +2 -0
  18. data/lib/watir/attribute_helper.rb +4 -2
  19. data/lib/watir/browser.rb +10 -14
  20. data/lib/watir/capabilities.rb +56 -33
  21. data/lib/watir/cell_container.rb +2 -0
  22. data/lib/watir/container.rb +2 -0
  23. data/lib/watir/cookies.rb +5 -5
  24. data/lib/watir/element_collection.rb +3 -1
  25. data/lib/watir/elements/button.rb +2 -0
  26. data/lib/watir/elements/cell.rb +2 -0
  27. data/lib/watir/elements/checkbox.rb +2 -0
  28. data/lib/watir/elements/date_field.rb +2 -0
  29. data/lib/watir/elements/date_time_field.rb +2 -0
  30. data/lib/watir/elements/dlist.rb +3 -1
  31. data/lib/watir/elements/element.rb +29 -105
  32. data/lib/watir/elements/file_field.rb +2 -0
  33. data/lib/watir/elements/font.rb +2 -0
  34. data/lib/watir/elements/form.rb +2 -0
  35. data/lib/watir/elements/hidden.rb +2 -0
  36. data/lib/watir/elements/iframe.rb +2 -0
  37. data/lib/watir/elements/image.rb +2 -0
  38. data/lib/watir/elements/input.rb +2 -0
  39. data/lib/watir/elements/link.rb +2 -0
  40. data/lib/watir/elements/list.rb +2 -0
  41. data/lib/watir/elements/option.rb +2 -0
  42. data/lib/watir/elements/radio.rb +2 -0
  43. data/lib/watir/elements/row.rb +2 -0
  44. data/lib/watir/elements/select.rb +2 -0
  45. data/lib/watir/elements/table.rb +3 -1
  46. data/lib/watir/elements/table_cell.rb +2 -0
  47. data/lib/watir/elements/table_row.rb +2 -0
  48. data/lib/watir/elements/table_section.rb +2 -0
  49. data/lib/watir/elements/text_area.rb +2 -0
  50. data/lib/watir/elements/text_field.rb +2 -0
  51. data/lib/watir/exception.rb +2 -0
  52. data/lib/watir/extensions/nokogiri.rb +2 -0
  53. data/lib/watir/generator/base/generator.rb +2 -0
  54. data/lib/watir/generator/base/idl_sorter.rb +3 -1
  55. data/lib/watir/generator/base/spec_extractor.rb +6 -4
  56. data/lib/watir/generator/base/util.rb +2 -0
  57. data/lib/watir/generator/base/visitor.rb +5 -5
  58. data/lib/watir/generator/base.rb +2 -1
  59. data/lib/watir/generator/html/generator.rb +2 -0
  60. data/lib/watir/generator/html/spec_extractor.rb +2 -0
  61. data/lib/watir/generator/html/visitor.rb +2 -0
  62. data/lib/watir/generator/html.rb +2 -0
  63. data/lib/watir/generator/svg/generator.rb +2 -0
  64. data/lib/watir/generator/svg/spec_extractor.rb +2 -0
  65. data/lib/watir/generator/svg/visitor.rb +2 -0
  66. data/lib/watir/generator/svg.rb +2 -0
  67. data/lib/watir/generator.rb +2 -0
  68. data/lib/watir/has_window.rb +3 -1
  69. data/lib/watir/http_client.rb +2 -0
  70. data/lib/watir/js_execution.rb +2 -0
  71. data/lib/watir/js_snippets.rb +2 -0
  72. data/lib/watir/locators/anchor/selector_builder.rb +2 -0
  73. data/lib/watir/locators/button/matcher.rb +2 -0
  74. data/lib/watir/locators/button/selector_builder/xpath.rb +15 -19
  75. data/lib/watir/locators/button/selector_builder.rb +2 -0
  76. data/lib/watir/locators/cell/selector_builder/xpath.rb +2 -0
  77. data/lib/watir/locators/cell/selector_builder.rb +2 -0
  78. data/lib/watir/locators/element/locator.rb +2 -0
  79. data/lib/watir/locators/element/matcher.rb +2 -0
  80. data/lib/watir/locators/element/selector_builder/regexp_disassembler.rb +2 -0
  81. data/lib/watir/locators/element/selector_builder/xpath.rb +16 -15
  82. data/lib/watir/locators/element/selector_builder/xpath_support.rb +4 -2
  83. data/lib/watir/locators/element/selector_builder.rb +16 -6
  84. data/lib/watir/locators/option/matcher.rb +2 -0
  85. data/lib/watir/locators/option/selector_builder/xpath.rb +2 -0
  86. data/lib/watir/locators/option/selector_builder.rb +2 -0
  87. data/lib/watir/locators/row/selector_builder/xpath.rb +2 -0
  88. data/lib/watir/locators/row/selector_builder.rb +2 -0
  89. data/lib/watir/locators/text_area/selector_builder/xpath.rb +2 -0
  90. data/lib/watir/locators/text_area/selector_builder.rb +2 -0
  91. data/lib/watir/locators/text_field/matcher.rb +2 -0
  92. data/lib/watir/locators/text_field/selector_builder/xpath.rb +2 -0
  93. data/lib/watir/locators/text_field/selector_builder.rb +2 -0
  94. data/lib/watir/locators.rb +2 -0
  95. data/lib/watir/logger.rb +2 -0
  96. data/lib/watir/navigation.rb +3 -1
  97. data/lib/watir/radio_set.rb +2 -0
  98. data/lib/watir/row_container.rb +2 -0
  99. data/lib/watir/screenshot.rb +2 -0
  100. data/lib/watir/scroll.rb +27 -2
  101. data/lib/watir/search_context.rb +96 -0
  102. data/lib/watir/shadow_root.rb +60 -0
  103. data/lib/watir/user_editable.rb +3 -1
  104. data/lib/watir/version.rb +3 -1
  105. data/lib/watir/wait/timer.rb +3 -1
  106. data/lib/watir/wait.rb +5 -5
  107. data/lib/watir/window.rb +7 -3
  108. data/lib/watir/window_collection.rb +4 -1
  109. data/lib/watir.rb +4 -0
  110. data/lib/watirspec/guards.rb +2 -0
  111. data/lib/watirspec/implementation.rb +14 -10
  112. data/lib/watirspec/rake_tasks.rb +4 -4
  113. data/lib/watirspec/remote_server.rb +5 -3
  114. data/lib/watirspec/runner.rb +3 -1
  115. data/lib/watirspec/server/app.rb +2 -0
  116. data/lib/watirspec/server.rb +2 -0
  117. data/lib/watirspec.rb +7 -4
  118. data/spec/locator_spec_helper.rb +2 -0
  119. data/spec/spec_helper.rb +2 -0
  120. data/spec/unit/capabilities_spec.rb +77 -58
  121. data/spec/unit/element_locator_spec.rb +2 -0
  122. data/spec/unit/match_elements/button_spec.rb +2 -0
  123. data/spec/unit/match_elements/element_spec.rb +10 -8
  124. data/spec/unit/match_elements/text_field_spec.rb +2 -0
  125. data/spec/unit/selector_builder/anchor_spec.rb +2 -0
  126. data/spec/unit/selector_builder/button_spec.rb +31 -28
  127. data/spec/unit/selector_builder/cell_spec.rb +3 -1
  128. data/spec/unit/selector_builder/element_spec.rb +61 -60
  129. data/spec/unit/selector_builder/row_spec.rb +21 -10
  130. data/spec/unit/selector_builder/text_field_spec.rb +29 -21
  131. data/spec/unit/selector_builder/textarea_spec.rb +2 -0
  132. data/spec/unit/unit_helper.rb +2 -0
  133. data/spec/unit/wait_spec.rb +2 -0
  134. data/spec/watirspec/adjacent_spec.rb +8 -6
  135. data/spec/watirspec/after_hooks_spec.rb +19 -21
  136. data/spec/watirspec/alert_spec.rb +2 -0
  137. data/spec/watirspec/attributes_spec.rb +2 -0
  138. data/spec/watirspec/browser_spec.rb +16 -12
  139. data/spec/watirspec/capabilities_spec.rb +569 -0
  140. data/spec/watirspec/cookies_spec.rb +4 -2
  141. data/spec/watirspec/drag_and_drop_spec.rb +2 -0
  142. data/spec/watirspec/element_hidden_spec.rb +2 -0
  143. data/spec/watirspec/elements/area_spec.rb +2 -0
  144. data/spec/watirspec/elements/areas_spec.rb +2 -0
  145. data/spec/watirspec/elements/button_spec.rb +2 -0
  146. data/spec/watirspec/elements/buttons_spec.rb +2 -0
  147. data/spec/watirspec/elements/checkbox_spec.rb +2 -0
  148. data/spec/watirspec/elements/checkboxes_spec.rb +2 -0
  149. data/spec/watirspec/elements/collections_spec.rb +5 -3
  150. data/spec/watirspec/elements/date_field_spec.rb +2 -0
  151. data/spec/watirspec/elements/date_fields_spec.rb +2 -0
  152. data/spec/watirspec/elements/date_time_field_spec.rb +2 -0
  153. data/spec/watirspec/elements/date_time_fields_spec.rb +2 -0
  154. data/spec/watirspec/elements/dd_spec.rb +2 -0
  155. data/spec/watirspec/elements/dds_spec.rb +2 -0
  156. data/spec/watirspec/elements/del_spec.rb +2 -0
  157. data/spec/watirspec/elements/dels_spec.rb +2 -0
  158. data/spec/watirspec/elements/div_spec.rb +2 -1
  159. data/spec/watirspec/elements/divs_spec.rb +2 -0
  160. data/spec/watirspec/elements/dl_spec.rb +6 -6
  161. data/spec/watirspec/elements/dls_spec.rb +2 -0
  162. data/spec/watirspec/elements/dt_spec.rb +2 -0
  163. data/spec/watirspec/elements/dts_spec.rb +2 -0
  164. data/spec/watirspec/elements/element_spec.rb +9 -1
  165. data/spec/watirspec/elements/elements_spec.rb +2 -0
  166. data/spec/watirspec/elements/em_spec.rb +2 -0
  167. data/spec/watirspec/elements/ems_spec.rb +2 -0
  168. data/spec/watirspec/elements/filefield_spec.rb +2 -0
  169. data/spec/watirspec/elements/filefields_spec.rb +2 -0
  170. data/spec/watirspec/elements/font_spec.rb +2 -0
  171. data/spec/watirspec/elements/form_spec.rb +2 -0
  172. data/spec/watirspec/elements/forms_spec.rb +2 -0
  173. data/spec/watirspec/elements/frame_spec.rb +2 -0
  174. data/spec/watirspec/elements/frames_spec.rb +2 -0
  175. data/spec/watirspec/elements/hidden_spec.rb +2 -0
  176. data/spec/watirspec/elements/hiddens_spec.rb +2 -0
  177. data/spec/watirspec/elements/hn_spec.rb +2 -0
  178. data/spec/watirspec/elements/hns_spec.rb +2 -0
  179. data/spec/watirspec/elements/iframe_spec.rb +3 -1
  180. data/spec/watirspec/elements/iframes_spec.rb +2 -0
  181. data/spec/watirspec/elements/image_spec.rb +2 -0
  182. data/spec/watirspec/elements/images_spec.rb +2 -0
  183. data/spec/watirspec/elements/input_spec.rb +2 -0
  184. data/spec/watirspec/elements/ins_spec.rb +2 -0
  185. data/spec/watirspec/elements/inses_spec.rb +2 -0
  186. data/spec/watirspec/elements/label_spec.rb +2 -0
  187. data/spec/watirspec/elements/labels_spec.rb +2 -0
  188. data/spec/watirspec/elements/li_spec.rb +2 -0
  189. data/spec/watirspec/elements/link_spec.rb +4 -4
  190. data/spec/watirspec/elements/links_spec.rb +2 -0
  191. data/spec/watirspec/elements/lis_spec.rb +2 -0
  192. data/spec/watirspec/elements/list_spec.rb +2 -0
  193. data/spec/watirspec/elements/map_spec.rb +2 -0
  194. data/spec/watirspec/elements/maps_spec.rb +2 -0
  195. data/spec/watirspec/elements/meta_spec.rb +2 -0
  196. data/spec/watirspec/elements/metas_spec.rb +2 -0
  197. data/spec/watirspec/elements/ol_spec.rb +2 -0
  198. data/spec/watirspec/elements/ols_spec.rb +2 -0
  199. data/spec/watirspec/elements/option_spec.rb +2 -0
  200. data/spec/watirspec/elements/p_spec.rb +2 -0
  201. data/spec/watirspec/elements/pre_spec.rb +2 -0
  202. data/spec/watirspec/elements/pres_spec.rb +2 -0
  203. data/spec/watirspec/elements/ps_spec.rb +2 -0
  204. data/spec/watirspec/elements/radio_spec.rb +2 -0
  205. data/spec/watirspec/elements/radios_spec.rb +2 -0
  206. data/spec/watirspec/elements/select_list_spec.rb +7 -1
  207. data/spec/watirspec/elements/select_lists_spec.rb +2 -0
  208. data/spec/watirspec/elements/span_spec.rb +2 -0
  209. data/spec/watirspec/elements/spans_spec.rb +2 -0
  210. data/spec/watirspec/elements/strong_spec.rb +2 -0
  211. data/spec/watirspec/elements/strongs_spec.rb +2 -0
  212. data/spec/watirspec/elements/table_nesting_spec.rb +2 -0
  213. data/spec/watirspec/elements/table_spec.rb +2 -0
  214. data/spec/watirspec/elements/tables_spec.rb +2 -0
  215. data/spec/watirspec/elements/tbody_spec.rb +2 -0
  216. data/spec/watirspec/elements/tbodys_spec.rb +2 -0
  217. data/spec/watirspec/elements/td_spec.rb +2 -0
  218. data/spec/watirspec/elements/tds_spec.rb +2 -0
  219. data/spec/watirspec/elements/text_field_spec.rb +2 -0
  220. data/spec/watirspec/elements/text_fields_spec.rb +2 -0
  221. data/spec/watirspec/elements/textarea_spec.rb +2 -0
  222. data/spec/watirspec/elements/textareas_spec.rb +2 -0
  223. data/spec/watirspec/elements/tfoot_spec.rb +2 -0
  224. data/spec/watirspec/elements/tfoots_spec.rb +2 -0
  225. data/spec/watirspec/elements/thead_spec.rb +2 -0
  226. data/spec/watirspec/elements/theads_spec.rb +2 -0
  227. data/spec/watirspec/elements/tr_spec.rb +2 -0
  228. data/spec/watirspec/elements/trs_spec.rb +2 -0
  229. data/spec/watirspec/elements/ul_spec.rb +2 -0
  230. data/spec/watirspec/elements/uls_spec.rb +2 -0
  231. data/spec/watirspec/html/child_frame.html +29 -0
  232. data/spec/watirspec/html/class_locator.html +2 -0
  233. data/spec/watirspec/html/scroll_nested.html +17 -0
  234. data/spec/watirspec/html/scroll_nested_offscreen.html +18 -0
  235. data/spec/watirspec/html/shadow_dom.html +28 -0
  236. data/spec/watirspec/radio_set_spec.rb +2 -0
  237. data/spec/watirspec/screenshot_spec.rb +4 -2
  238. data/spec/watirspec/scroll_spec.rb +75 -7
  239. data/spec/watirspec/shadow_root_spec.rb +103 -0
  240. data/spec/watirspec/special_chars_spec.rb +2 -0
  241. data/spec/watirspec/support/rspec_matchers.rb +35 -32
  242. data/spec/watirspec/user_editable_spec.rb +2 -0
  243. data/spec/watirspec/wait_spec.rb +2 -0
  244. data/spec/watirspec/window_switching_spec.rb +48 -38
  245. data/spec/watirspec_helper.rb +24 -18
  246. data/support/doctest_helper.rb +2 -0
  247. data/support/version_differ.rb +2 -0
  248. data/watir.gemspec +11 -8
  249. metadata +54 -215
  250. data/.github/actions/enable-safari/action.yml +0 -11
  251. data/.github/actions/install-chrome/action.yml +0 -12
  252. data/.github/actions/setup-linux/action.yml +0 -8
  253. data/lib/watir-webdriver.rb +0 -2
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  class TableSection < HTMLElement
3
5
  include RowContainer
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  class TextArea < HTMLElement
3
5
  include UserEditable
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  class TextField < Input
3
5
  include UserEditable
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Exception
3
5
  class Error < StandardError; end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'nokogiri'
2
4
 
3
5
  module Watir
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Generator
3
5
  class Base
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'tsort'
2
4
 
3
5
  module Watir
@@ -40,7 +42,7 @@ module Watir
40
42
  return if @visited.include?(node)
41
43
 
42
44
  @visited << node
43
- puts ' ' * indent + node
45
+ puts (' ' * indent) + node
44
46
  tsort_each_child(node) { |child| print_node(child, indent + 2) }
45
47
  end
46
48
  end # IDLSorter
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Generator
3
5
  class Base
4
6
  class SpecExtractor
5
- IDL_SELECTOR = "//pre[contains(@class, 'idl')]".freeze
7
+ IDL_SELECTOR = "//pre[contains(@class, 'idl')]"
6
8
 
7
9
  class InterfaceNotFound < StandardError; end
8
10
 
@@ -32,9 +34,9 @@ module Watir
32
34
  def sorted_interfaces
33
35
  process if @interfaces.nil?
34
36
 
35
- idl_sorter.sort.map { |name|
37
+ idl_sorter.sort.filter_map do |name|
36
38
  @interfaces.find { |i| i.name == name } || puts("ignoring interface: #{name}")
37
- }.compact
39
+ end
38
40
  end
39
41
 
40
42
  def print_hierarchy
@@ -53,7 +55,7 @@ module Watir
53
55
  end
54
56
 
55
57
  def extract_idl_parts
56
- parsed = @doc.search(IDL_SELECTOR).map { |e| parse_idl(e.inner_text) }.compact
58
+ parsed = @doc.search(IDL_SELECTOR).filter_map { |e| parse_idl(e.inner_text) }
57
59
 
58
60
  implements = []
59
61
  includes = []
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Generator
3
5
  module Util
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Generator
3
5
  class Base
@@ -9,7 +11,7 @@ module Watir
9
11
  'DOMStringMap', 'HTMLPropertiesCollection', /HTML.*Element/, /HTML.*Collection/,
10
12
  'CSSStyleDeclaration', /.+List$/, 'Date', 'Element', /DOM.+ReadOnly/,
11
13
  /SVGAnimated.+/, /SVG.*Element/, /SVG.*Collection/, 'SVGViewSpec',
12
- 'Object', 'USVString'].freeze
14
+ 'Object', 'USVString', 'DOMString', 'any'].freeze
13
15
  def initialize
14
16
  super
15
17
 
@@ -111,7 +113,8 @@ module Watir
111
113
 
112
114
  def ruby_type_for(type)
113
115
  case type.name.to_s
114
- when 'DOMString', 'any'
116
+ when *STRING_TYPES
117
+ # probably completely wrong.
115
118
  String
116
119
  when 'UnsignedLong', 'Long', 'Integer', 'Short', 'UnsignedShort',
117
120
  'SVGAnimatedLength'
@@ -120,9 +123,6 @@ module Watir
120
123
  Float
121
124
  when 'Boolean'
122
125
  'Boolean'
123
- when *STRING_TYPES
124
- # probably completely wrong.
125
- String
126
126
  else
127
127
  raise "unknown type: #{type.name}"
128
128
  end
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'nokogiri'
2
4
  require 'open-uri'
3
- require 'pp'
4
5
  require 'webidl'
5
6
  require 'active_support/inflector'
6
7
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Generator
3
5
  class HTML < Base
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Generator
3
5
  class HTML
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Generator
3
5
  class HTML
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ActiveSupport::Inflector.inflections do |inflect|
2
4
  inflect.plural 'body', 'bodys'
3
5
  inflect.plural 'tbody', 'tbodys'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Generator
3
5
  class SVG < Base
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Generator
3
5
  class SVG
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Generator
3
5
  class SVG
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ActiveSupport::Inflector.inflections do |inflect|
2
4
  inflect.plural 'defs', 'defss'
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'watir/generator/base'
2
4
  require 'watir/generator/html'
3
5
  require 'watir/generator/svg'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module HasWindow
3
5
  attr_writer :original_window
@@ -27,7 +29,7 @@ module Watir
27
29
  def window(opts = {}, &blk)
28
30
  win = Window.new self, opts
29
31
 
30
- win.use(&blk) if block_given?
32
+ win.use(&blk) if blk
31
33
 
32
34
  win
33
35
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  class HttpClient < Selenium::WebDriver::Remote::Http::Default
3
5
  def request(verb, url, headers, payload, redirects = 0)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module JSExecution
3
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module JSSnippets
3
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Locators
3
5
  class Anchor
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Locators
3
5
  class Button
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Locators
3
5
  class Button
@@ -14,27 +16,23 @@ module Watir
14
16
  type = @selector.delete(:type)
15
17
  text = @selector.delete(:text)
16
18
 
17
- string = "(#{button_string(text: text, type: type)})"
18
- string << " or (#{input_string(text: text, type: type)})" unless type.eql?(false)
19
- "[#{string}]"
19
+ button = "(#{button_string(text: text, type: type)})"
20
+ input = type.eql?(false) ? '' : " or (#{input_string(text: text, type: type)})"
21
+
22
+ "[#{button}#{input}]"
20
23
  end
21
24
 
22
25
  def button_string(text: nil, type: nil)
23
- string = process_attribute(:tag_name, 'button')
24
- string << " and #{process_attribute(:text, text)}" unless text.nil?
25
- string << " and #{input_types(type)}" unless type.nil?
26
- string
26
+ input = type.nil? ? '' : " and #{input_types(type)}"
27
+ attribute = text.nil? ? '' : " and #{process_attribute(:text, text)}"
28
+ "#{process_attribute(:tag_name, 'button')}#{input}#{attribute}"
27
29
  end
28
30
 
29
31
  def input_string(text: nil, type: nil)
30
- string = process_attribute(:tag_name, 'input')
31
32
  type = nil if type.eql?(true)
32
- string << " and (#{input_types(type)})"
33
- if text
34
- string << " and #{process_attribute(:value, text)}"
35
- @built.delete(:value)
36
- end
37
- string
33
+ text_value = text.nil? ? '' : " and #{process_attribute(:value, text)}"
34
+ @built.delete(:value) unless text.nil?
35
+ "#{process_attribute(:tag_name, 'input')} and (#{input_types(type)})#{text_value}"
38
36
  end
39
37
 
40
38
  # value locator needs to match input value, button text or button value
@@ -54,17 +52,15 @@ module Watir
54
52
  def input_types(type = nil)
55
53
  types = if type.eql?(nil)
56
54
  Watir::Button::VALID_TYPES
57
- elsif Watir::Button::VALID_TYPES.include?(type)
58
- [type]
59
- elsif type.eql?(true) || type.eql?(false)
55
+ elsif Watir::Button::VALID_TYPES.include?(type) || type.eql?(true) || type.eql?(false)
60
56
  [type]
61
57
  else
62
58
  msg = "Button Elements can not be located by input type: #{type}"
63
59
  raise LocatorException, msg
64
60
  end
65
- types.map { |button_type|
61
+ types.filter_map { |button_type|
66
62
  predicate_expression(:type, button_type)
67
- }.compact.join(' or ')
63
+ }.join(' or ')
68
64
  end
69
65
  end
70
66
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Locators
3
5
  class Button
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Locators
3
5
  class Cell
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Locators
3
5
  class Cell
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Locators
3
5
  class Element
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Locators
3
5
  class Element
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Source: https://github.com/teamcapybara/capybara/blob/xpath_regexp/lib/capybara/selector/regexp_disassembler.rb
2
4
  require 'regexp_parser'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Locators
3
5
  class Element
@@ -22,14 +24,14 @@ module Watir
22
24
  @adjacent = @selector.delete(:adjacent)
23
25
  @scope = @selector.delete(:scope)
24
26
 
25
- xpath = start_string
26
- xpath << adjacent_string
27
- xpath << tag_string
28
- xpath << class_string
29
- xpath << text_string
30
- xpath << additional_string
31
- xpath << label_element_string
32
- xpath << attribute_string
27
+ xpath = "#{start_string}" \
28
+ "#{adjacent_string}" \
29
+ "#{tag_string}" \
30
+ "#{class_string}" \
31
+ "#{text_string}" \
32
+ "#{additional_string}" \
33
+ "#{label_element_string}" \
34
+ "#{attribute_string}"
33
35
 
34
36
  @built[:xpath] = index ? add_index(xpath, index) : xpath
35
37
  @built
@@ -73,7 +75,7 @@ module Watir
73
75
  add_to_matching(key, regexp, results)
74
76
 
75
77
  results.map { |rhs|
76
- rhs = "'#{rhs}'"
78
+ rhs = "\"#{rhs}\""
77
79
  rhs = XpathSupport.downcase(rhs) if downcase
78
80
  "contains(#{lhs}, #{rhs})"
79
81
  }.flatten.compact.join(' and ')
@@ -112,7 +114,7 @@ module Watir
112
114
 
113
115
  @built[:class] = []
114
116
 
115
- predicates = [class_name].flatten.map { |value| process_attribute(:class, value) }.compact
117
+ predicates = [class_name].flatten.filter_map { |value| process_attribute(:class, value) }
116
118
 
117
119
  @built.delete(:class) if @built[:class].empty?
118
120
 
@@ -135,7 +137,7 @@ module Watir
135
137
  end
136
138
 
137
139
  def equal_or_contains(value)
138
- return nil if value.nil? || value.is_a?(String) && value.empty? || value.inspect == '//'
140
+ return nil if value.nil? || (value.is_a?(String) && value.empty?) || value.inspect == '//'
139
141
 
140
142
  process_attribute(:text, value)
141
143
  end
@@ -158,8 +160,7 @@ module Watir
158
160
  elsif index&.positive? && @built.empty?
159
161
  "(#{xpath})[#{index + 1}]"
160
162
  elsif index&.negative? && @built.empty?
161
- last_value = 'last()'
162
- last_value << (index + 1).to_s if index < -1
163
+ last_value = "last()#{index < -1 ? index + 1 : ''}"
163
164
  "(#{xpath})[#{last_value}]"
164
165
  else
165
166
  @built[:index] = index
@@ -220,7 +221,7 @@ module Watir
220
221
  if key == :class
221
222
  negate_xpath = value =~ /^!/
222
223
  value = value[1..] if negate_xpath
223
- expression = "contains(concat(' ', @class, ' '), #{XpathSupport.escape " #{value} "})"
224
+ expression = "contains(concat(' ', normalize-space(@class), ' '), #{XpathSupport.escape " #{value} "})"
224
225
 
225
226
  negate_xpath ? "not(#{expression})" : expression
226
227
  else
@@ -254,7 +255,7 @@ module Watir
254
255
  end
255
256
 
256
257
  def process_string(name)
257
- if name =~ /^[a-zA-Z_:][a-zA-Z0-9_:.\-]*$/
258
+ if /^[a-zA-Z_:][a-zA-Z0-9_:.-]*$/.match?(name)
258
259
  "@#{name}"
259
260
  else
260
261
  "(attribute::*[local-name(.) = '#{name}'])"
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Locators
3
5
  class Element
4
6
  class SelectorBuilder
5
7
  module XpathSupport
6
- UPPERCASE_LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸŽŠŒ'.freeze
7
- LOWERCASE_LETTERS = 'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ'.freeze
8
+ UPPERCASE_LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸŽŠŒ'
9
+ LOWERCASE_LETTERS = 'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ'
8
10
 
9
11
  def self.escape(value)
10
12
  if value.include? "'"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Locators
3
5
  class Element
@@ -22,6 +24,7 @@ module Watir
22
24
  @query_scope = query_scope
23
25
  end
24
26
 
27
+ # rubocop:disable Metrics/PerceivedComplexity:
25
28
  def build(selector)
26
29
  @selector = selector
27
30
 
@@ -29,13 +32,22 @@ module Watir
29
32
  inspected = selector.inspect
30
33
  scope = @query_scope unless @selector.key?(:scope) || @query_scope.is_a?(Watir::Browser)
31
34
 
32
- @built = wd_locators.empty? ? build_wd_selector(@selector) : @selector
35
+ @built =
36
+ if scope.is_a? Watir::ShadowRoot
37
+ raise ArgumentError, ':xpath not supported when locating elements from shadow root' if @selector[:xpath]
38
+
39
+ @selector[:css] ||= '*'
40
+ @selector
41
+ else
42
+ wd_locators.empty? ? build_wd_selector(@selector) : @selector
43
+ end
33
44
  @built.delete(:index) if @built[:index]&.zero?
34
45
  @built[:scope] = scope if scope
35
46
 
36
47
  Watir.logger.info "Converted #{inspected} to #{@built.inspect}"
37
48
  @built
38
49
  end
50
+ # rubocop:enable Metrics/PerceivedComplexity:
39
51
 
40
52
  def wd_locators
41
53
  Watir::Locators::W3C_FINDERS & @selector.keys
@@ -66,9 +78,9 @@ module Watir
66
78
  end
67
79
 
68
80
  def merge_scope?
69
- return false unless (Watir::Locators::W3C_FINDERS + [:adjacent] & @selector.keys).empty?
81
+ return false unless ((Watir::Locators::W3C_FINDERS + [:adjacent]) & @selector.keys).empty?
70
82
 
71
- return false if [Watir::Browser, Watir::IFrame].any? { |k| @query_scope.is_a?(k) }
83
+ return false if [Watir::Browser, Watir::IFrame, Watir::ShadowRoot].any? { |k| @query_scope.is_a?(k) }
72
84
 
73
85
  scope_invalid_locators = @query_scope.selector_builder.built.keys.reject { |key| key == wd_locator }
74
86
  scope_invalid_locators.empty?
@@ -136,10 +148,8 @@ module Watir
136
148
  keys.reject! { |key| %i[visible visible_text index].include? key }
137
149
  if (keys - [:tag_name]).empty?
138
150
  true
139
- elsif selector[:tag_name] == 'input' && keys == %i[tag_name type]
140
- true
141
151
  else
142
- false
152
+ selector[:tag_name] == 'input' && keys == %i[tag_name type]
143
153
  end
144
154
  end
145
155
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Locators
3
5
  class Option
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Locators
3
5
  class Option
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Locators
3
5
  class Option
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Locators
3
5
  class Row
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Locators
3
5
  class Row
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Locators
3
5
  class TextArea
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Locators
3
5
  class TextArea
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Locators
3
5
  class TextField
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Locators
3
5
  class TextField
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Locators
3
5
  class TextField
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'watir/locators/element/locator'
2
4
  require 'watir/locators/element/selector_builder'
3
5
  require 'watir/locators/element/selector_builder/xpath_support'
data/lib/watir/logger.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'forwardable'
2
4
  require 'logger'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module Navigation
3
5
  #
@@ -11,7 +13,7 @@ module Watir
11
13
  #
12
14
 
13
15
  def goto(uri)
14
- uri = "http://#{uri}" unless uri =~ URI::DEFAULT_PARSER.make_regexp
16
+ uri = "http://#{uri}" unless uri&.match?(URI::DEFAULT_PARSER.make_regexp)
15
17
 
16
18
  @driver.navigate.to uri
17
19
  @after_hooks.run
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  class RadioSet
3
5
  extend Forwardable
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  module RowContainer
3
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Watir
2
4
  class Screenshot
3
5
  def initialize(browser)