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
  require 'watirspec_helper'
2
4
 
3
5
  describe 'Ul' do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'watirspec_helper'
2
4
 
3
5
  describe 'Uls' do
@@ -0,0 +1,29 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Child frame</title>
5
+ <meta name="author" content="Software Freedom Conservancy">
6
+ <link rel="author" href="https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/common/src/web/scrolling_tests/frame_with_height_above_200.html">
7
+ <link rel="license" href="https://github.com/SeleniumHQ/selenium/blob/trunk/LICENSE">
8
+ </head>
9
+ <body>
10
+ <h1>This is a scrolling frame test</h1>
11
+ <div>
12
+ <table>
13
+ <tr height="50px">
14
+ <td>First row</td>
15
+ </tr>
16
+ <tr height="50px">
17
+ <td>Second row</td>
18
+ </tr>
19
+ <tr height="50px">
20
+ <td>Third row</td>
21
+ </tr>
22
+ <tr height="50px">
23
+ <td>Fourth row</td>
24
+ </tr>
25
+ </table>
26
+ </div>
27
+ <input type='checkbox' name='scroll_checkbox' />
28
+ </body>
29
+ </html>
@@ -5,5 +5,7 @@
5
5
  <div class="a b c">a b c</div>
6
6
  <div class="a b">a b</div>
7
7
  <div class="abc">abc</div>
8
+ <div class="first
9
+ newline tabbed last">tab</div>
8
10
  </body>
9
11
  </html>
@@ -0,0 +1,17 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Welcome Page</title>
5
+ <meta name="author" content="Software Freedom Conservancy">
6
+ <link rel="author" href="https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/common/src/web/scrolling_tests/frame_with_height_above_200.html">
7
+ <link rel="license" href="https://github.com/SeleniumHQ/selenium/blob/trunk/LICENSE">
8
+ </head>
9
+ <body>
10
+ <div>
11
+ <iframe name="nested_scrolling_frame" src="child_frame.html" width="800" height="200" ></iframe>
12
+ </div>
13
+ <div><a href="https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/common/src/web/scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html">
14
+ &copy; Software Freedom Conservancy
15
+ </a></div>
16
+ </body>
17
+ </html>
@@ -0,0 +1,18 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Welcome Page</title>
5
+ <meta name="author" content="Software Freedom Conservancy">
6
+ <link rel="author" href="https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/common/src/web/scrolling_tests/frame_with_height_above_200.html">
7
+ <link rel="license" href="https://github.com/SeleniumHQ/selenium/blob/trunk/LICENSE">
8
+ </head>
9
+ <body>
10
+ <div style="height: 5000px;"><a href="https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/common/src/web/scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html">
11
+ HTML copyright Software Freedom Conservancy
12
+ </a></div>
13
+ <div>
14
+ <iframe name="nested_scrolling_frame" src="child_frame.html" width="800" height="200" ></iframe>
15
+ </div>
16
+ <footer>IFrame Above</footer>
17
+ </body>
18
+ </html>
@@ -0,0 +1,28 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5
+ <title>Shadow DOM</title>
6
+ </head>
7
+ <body>
8
+ <div id="non_host"></div>
9
+ <div id="shadow_host"></div>
10
+ <a href="scroll.html">scroll.html</a>
11
+ <script>
12
+ let shadowRoot = document.getElementById('shadow_host').attachShadow({mode: 'open'});
13
+ shadowRoot.innerHTML = `
14
+ <span class="wrapper" id="shadow_content"><span class="info">some text</span></span>
15
+ <div id="nested_shadow_host"></div>
16
+ <div id="chrome_workaround"><a href="scroll.html">scroll.html</a></div>
17
+ <input type="text" />
18
+ <input type="checkbox" />
19
+ <input type="file" />
20
+ `;
21
+
22
+ let nestedShadowRoot = shadowRoot.getElementById('nested_shadow_host').attachShadow({mode: 'open'});
23
+ nestedShadowRoot.innerHTML = `
24
+ <div id="nested_shadow_content"><div>nested text</div></div>
25
+ `;
26
+ </script>
27
+ </body>
28
+ </html>
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'watirspec_helper'
2
4
 
3
5
  describe 'RadioSet' do
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'base64'
2
4
  require 'watirspec_helper'
3
5
 
4
6
  describe 'Watir::Screenshot' do
5
- let(:png_header) { "\211PNG".force_encoding('ASCII-8BIT') }
7
+ let(:png_header) { (+"\211PNG").force_encoding('ASCII-8BIT') }
6
8
 
7
9
  describe '#png' do
8
10
  it 'gets png representation of screenshot' do
@@ -23,7 +25,7 @@ describe 'Watir::Screenshot' do
23
25
  expect(File).to_not exist(path)
24
26
  browser.screenshot.save(path)
25
27
  expect(File).to exist(path)
26
- expect(File.open(path, 'rb', &:read)[0..3]).to eq png_header
28
+ expect(File.binread(path)[0..3]).to eq png_header
27
29
  end
28
30
  end
29
31
  end
@@ -1,8 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'watirspec_helper'
2
4
 
3
5
  describe Watir::Scrolling do
4
6
  before(:each) do
5
7
  browser.goto(WatirSpec.url_for('scroll.html'))
8
+ pause
6
9
  end
7
10
 
8
11
  def top_centered_viewport
@@ -49,32 +52,56 @@ describe Watir::Scrolling do
49
52
 
50
53
  describe '#by' do
51
54
  before do
52
- sleep(0.1)
53
55
  browser.scroll.to :top
56
+ pause
54
57
  end
55
58
 
56
59
  it 'offset from top' do
57
60
  initial_top = current_top
58
- scroll_by = top_centered_viewport
61
+ scroll_by = top_centered_viewport.round
59
62
  browser.scroll.by(0, -scroll_by)
60
-
63
+ pause
64
+ puts "scroll by #{scroll_by}"
65
+ puts "initial top #{initial_top}"
66
+ puts "current top #{current_top}"
61
67
  expect(current_top).to be_within(1).of(scroll_by + initial_top)
62
68
  end
63
69
 
64
70
  it 'offset from bottom' do
65
- browser.scroll.to :top
66
71
  initial_top = current_top
67
72
  browser.scroll.to :bottom
68
73
  scroll_by = top_centered_viewport
69
74
  browser.scroll.by(0, scroll_by)
70
-
75
+ pause
71
76
  expect(current_top).to be_within(1).of(scroll_by + initial_top)
72
77
  end
73
78
  end
79
+
80
+ describe '#from' do
81
+ it 'scrolls by given amount with offset' do
82
+ browser.goto(WatirSpec.url_for('scroll_nested.html'))
83
+
84
+ browser.scroll.from(10, 10).by(0, 225)
85
+
86
+ expect(in_viewport?(browser.iframe.checkbox(name: 'scroll_checkbox'))).to eq true
87
+ end
88
+ end
74
89
  end
75
90
 
76
91
  context 'when scrolling Element' do
77
92
  describe '#to' do
93
+ it 'scrolls element into view (viewport)',
94
+ except: {browser: %i[firefox safari], reason: 'incorrect MoveTargetOutOfBoundsError'} do
95
+ browser.goto(WatirSpec.url_for('scroll_nested_offscreen.html'))
96
+ iframe = browser.iframe
97
+
98
+ expect(in_viewport?(iframe)).to eq false
99
+
100
+ iframe.scroll.to(:viewport)
101
+
102
+ expect(in_viewport?(iframe)).to eq true
103
+ end
104
+
78
105
  it 'scrolls to element (top) by default' do
79
106
  element = browser.div(id: 'center')
80
107
  element.scroll.to
@@ -120,17 +147,58 @@ describe Watir::Scrolling do
120
147
 
121
148
  describe '#by' do
122
149
  it 'offset' do
123
- sleep 0.1
124
150
  browser.scroll.to :top
151
+ pause
125
152
  initial_top = current_top
126
153
  browser.scroll.to :bottom
154
+ pause
127
155
  scroll_by = top_centered_viewport
128
156
 
129
157
  element = browser.div(id: 'bottom')
130
158
  element.scroll.by(0, scroll_by)
131
-
159
+ pause
132
160
  expect(current_top).to be_within(1).of(scroll_by + initial_top)
133
161
  end
134
162
  end
163
+
164
+ describe '#from',
165
+ except: {browser: %i[firefox safari], reason: 'incorrect MoveTargetOutOfBoundsError'} do
166
+ it 'scrolls from element by given amount' do
167
+ browser.goto(WatirSpec.url_for('scroll_nested_offscreen.html'))
168
+ iframe = browser.iframe
169
+
170
+ iframe.scroll.from.by(0, 200)
171
+
172
+ checkbox = iframe.checkbox(name: 'scroll_checkbox')
173
+ expect(in_viewport?(checkbox)).to eq true
174
+ end
175
+
176
+ it 'scrolls from an element with an offset' do
177
+ browser.goto(WatirSpec.url_for('scroll_nested_offscreen.html'))
178
+
179
+ move_left = browser.execute_script('return arguments[0].getBoundingClientRect().width/2', browser.footer) -
180
+ browser.execute_script('return arguments[0].getBoundingClientRect().right/2', browser.iframe.we)
181
+
182
+ browser.footer.scroll.from(-move_left.round, -50).by(0, 200)
183
+
184
+ checkbox = browser.iframe.checkbox(name: 'scroll_checkbox')
185
+ expect(in_viewport?(checkbox)).to eq true
186
+ end
187
+ end
188
+ end
189
+
190
+ def in_viewport?(element)
191
+ in_viewport = <<~IN_VIEWPORT
192
+ for(var e=arguments[0],f=e.offsetTop,t=e.offsetLeft,o=e.offsetWidth,n=e.offsetHeight;
193
+ e.offsetParent;)f+=(e=e.offsetParent).offsetTop,t+=e.offsetLeft;
194
+ return f<window.pageYOffset+window.innerHeight&&t<window.pageXOffset+window.innerWidth&&f+n>
195
+ window.pageYOffset&&t+o>window.pageXOffset
196
+ IN_VIEWPORT
197
+
198
+ element.browser.execute_script(in_viewport, element.we)
199
+ end
200
+
201
+ def pause
202
+ sleep 0.2
135
203
  end
136
204
  end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'watirspec_helper'
4
+
5
+ describe 'ShadowRoot' do
6
+ before :each do
7
+ browser.goto(WatirSpec.url_for('shadow_dom.html'))
8
+ end
9
+ context 'with errors' do
10
+ it 'returns false when element does not exist' do
11
+ missing_shadow_root = browser.div(id: 'does_not_exist').shadow_root
12
+ expect(missing_shadow_root).not_to exist
13
+ end
14
+
15
+ it 'raises ArgumentError when using :xpath to locate elements directly from the shadow root' do
16
+ shadow_root = browser.div(id: 'shadow_host').shadow_root
17
+ expect { shadow_root.element(xpath: './/span').exists? }.to raise_exception(ArgumentError)
18
+ end
19
+
20
+ it 'returns false when locating element in shadow root that does not exist',
21
+ except: {browser: :safari, reason: 'shadow endpoint not recognized'} do
22
+ missing_shadow_root = browser.div(id: 'non_host').shadow_root
23
+ expect(missing_shadow_root.element).not_to exist
24
+ end
25
+ end
26
+
27
+ context 'without errors', only: {browser: %i[firefox chrome edge]} do
28
+ describe '#exists?' do
29
+ it 'returns true when element has a shadow DOM' do
30
+ shadow_root = browser.div(id: 'shadow_host').shadow_root
31
+ expect(shadow_root).to exist
32
+ end
33
+
34
+ it 'returns false when element does not have a shadow DOM' do
35
+ missing_shadow_root = browser.div(id: 'non_host').shadow_root
36
+ expect(missing_shadow_root).not_to exist
37
+ end
38
+ end
39
+
40
+ describe 'locating', except: {browser: :firefox, reason: 'location not supported yet'} do
41
+ it 'locates a nested element' do
42
+ shadow_root = browser.div(id: 'shadow_host').shadow_root
43
+ expect(shadow_root.element.id).to eq('shadow_content')
44
+ expect(shadow_root.element(id: 'nested_shadow_host').id).to eq('nested_shadow_host')
45
+ expect(shadow_root.element(id: /nested_shadow_.+/).id).to eq('nested_shadow_host')
46
+ expect(shadow_root.element(css: 'div').id).to eq('nested_shadow_host')
47
+ expect(shadow_root.div.id).to eq('nested_shadow_host')
48
+ end
49
+
50
+ it 'locates a collection of nested elements' do
51
+ shadow_root = browser.div(id: 'shadow_host').shadow_root
52
+ expect(shadow_root.elements.count).to eq(8)
53
+ expect(shadow_root.elements(id: 'nested_shadow_host').map(&:id)).to eq(['nested_shadow_host'])
54
+ expect(shadow_root.elements(id: /nested_shadow_.+/).map(&:id)).to eq(['nested_shadow_host'])
55
+ expect(shadow_root.elements(css: 'div').map(&:id)).to eq(%w[nested_shadow_host chrome_workaround])
56
+ expect(shadow_root.divs.map(&:id)).to eq(%w[nested_shadow_host chrome_workaround])
57
+ end
58
+
59
+ it 'locates a nested element within a nested shadow DOM' do
60
+ shadow_root = browser.div(id: 'shadow_host').shadow_root
61
+ nested_shadow_root = shadow_root.element(id: 'nested_shadow_host').shadow_root
62
+ expect(nested_shadow_root.element.id).to eq('nested_shadow_content')
63
+ end
64
+
65
+ it 'locates a collection of nested elements within a nested shadow DOM' do
66
+ shadow_root = browser.div(id: 'shadow_host').shadow_root
67
+ nested_shadow_root = shadow_root.element(id: 'nested_shadow_host').shadow_root
68
+ expect(nested_shadow_root.elements.count).to eq(2)
69
+ expect(nested_shadow_root.elements.map(&:id)).to include('nested_shadow_content')
70
+ end
71
+
72
+ it 'allows using :xpath to locate elements with an element of a shadow root' do
73
+ shadow_root = browser.div(id: 'shadow_host').shadow_root
74
+ expect(shadow_root.span.element(xpath: './/span')).to exist
75
+ end
76
+
77
+ it 'click elements within the shadow dom' do
78
+ shadow_root = browser.div(id: 'shadow_host').shadow_root
79
+ shadow_root.link.click
80
+ expect(browser.url).to include('scroll.html')
81
+ end
82
+
83
+ it 'click! elements within the shadow dom' do
84
+ shadow_root = browser.div(id: 'shadow_host').shadow_root
85
+ shadow_root.link.click!
86
+ expect(browser.url).to include('scroll.html')
87
+ end
88
+
89
+ it 'inputs form elements within the shadow dom' do
90
+ shadow_root = browser.div(id: 'shadow_host').shadow_root
91
+
92
+ shadow_root.text_field.set('abc')
93
+ expect(shadow_root.text_field.value).to eq('abc')
94
+
95
+ shadow_root.checkbox.set
96
+ expect(shadow_root.checkbox.set?).to eq(true)
97
+
98
+ shadow_root.file_field.set(File.expand_path(__FILE__))
99
+ expect(shadow_root.file_field.value).to include('shadow_root_spec.rb')
100
+ end
101
+ end
102
+ end
103
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'watirspec_helper'
2
4
 
3
5
  describe Watir::Browser do
@@ -1,33 +1,36 @@
1
+ # frozen_string_literal: true
2
+
1
3
  if defined?(RSpec)
2
- DEPRECATION_WARNINGS = %i[timeouts].freeze
4
+ RSpec::Matchers.define :have_deprecated do |deprecation|
5
+ match do |actual|
6
+ # Suppresses logging output to stdout while ensuring that it is still happening
7
+ default_output = Selenium::WebDriver.logger.io
8
+ io = StringIO.new
9
+ Watir.logger.output = io
3
10
 
4
- DEPRECATION_WARNINGS.each do |deprecation|
5
- RSpec::Matchers.define "have_deprecated_#{deprecation}" do
6
- match do |actual|
7
- return actual.call if ENV['IGNORE_DEPRECATIONS']
11
+ actual.call
8
12
 
9
- warning = /\[DEPRECATION\] \["#{deprecation}"/
10
- expect {
11
- actual.call
12
- @stdout_message = File.read $stdout if $stdout.is_a?(File)
13
- }.to output(warning).to_stdout_from_any_process
14
- end
13
+ Watir.logger.output = default_output
14
+ @deprecations_found = (io.rewind && io.read).scan(/DEPRECATION\] \[:([^\]]*)\]/).flatten.map(&:to_sym)
15
+ expect(Array(deprecation).sort).to eq(@deprecations_found.sort)
16
+ end
15
17
 
16
- failure_message do |_actual|
17
- return 'unexpected exception in the custom matcher block' unless @stdout_message
18
-
19
- deprecations_found = @stdout_message[/WARN Watir \[DEPRECATION\] ([^.*\ ]*)/, 1]
20
- but_message = if deprecations_found.nil?
21
- 'no Warnings were found'
22
- else
23
- "deprecation Warning of #{deprecations_found} was found instead"
24
- end
25
- "expected Warning message of \"#{deprecation}\" being deprecated, but #{but_message}"
26
- end
18
+ failure_message do
19
+ but_message = if @deprecations_found.nil? || @deprecations_found.empty?
20
+ 'no deprecations were found'
21
+ else
22
+ "instead these deprecations were found: [#{@deprecations_found.join(', ')}]"
23
+ end
24
+ "expected :#{deprecation} to have been deprecated, but #{but_message}"
25
+ end
27
26
 
28
- def supports_block_expectations?
29
- true
30
- end
27
+ failure_message_when_negated do
28
+ but_message = "it was found among these deprecations: [#{@deprecations_found.join(', ')}]"
29
+ "expected :#{deprecation} not to have been deprecated, but #{but_message}"
30
+ end
31
+
32
+ def supports_block_expectations?
33
+ true
31
34
  end
32
35
  end
33
36
 
@@ -72,11 +75,11 @@ if defined?(RSpec)
72
75
  original_timeout = Watir.default_timeout
73
76
  Watir.default_timeout = timeout
74
77
  begin
75
- start_time = ::Time.now
78
+ start_time = Time.now
76
79
  actual.call
77
80
  false
78
81
  rescue exception => e
79
- finish_time = ::Time.now
82
+ finish_time = Time.now
80
83
  unless message.nil? || e.message.match(message)
81
84
  raise exception, "expected '#{message}' to be included in: '#{e.message}'"
82
85
  end
@@ -91,7 +94,7 @@ if defined?(RSpec)
91
94
  failure_message do
92
95
  if @time_difference
93
96
  "expected action to take more than provided timeout (#{timeout} seconds), " \
94
- "instead it took #{@time_difference} seconds"
97
+ "instead it took #{@time_difference} seconds"
95
98
  else
96
99
  "expected #{exception} but nothing was raised"
97
100
  end
@@ -109,9 +112,9 @@ if defined?(RSpec)
109
112
  original_timeout = Watir.default_timeout
110
113
  Watir.default_timeout = max
111
114
  begin
112
- start_time = ::Time.now
115
+ start_time = Time.now
113
116
  actual.call
114
- @time_difference = ::Time.now - start_time
117
+ @time_difference = Time.now - start_time
115
118
  @time_difference > min && @time_difference < max
116
119
  ensure
117
120
  Watir.default_timeout = original_timeout
@@ -120,12 +123,12 @@ if defined?(RSpec)
120
123
 
121
124
  failure_message_when_negated do
122
125
  "expected action to take less than #{min} seconds or more than #{max} seconds, " \
123
- "instead it took #{@time_difference} seconds"
126
+ "instead it took #{@time_difference} seconds"
124
127
  end
125
128
 
126
129
  failure_message do
127
130
  "expected action to take more than #{min} seconds and less than #{max} seconds, " \
128
- "instead it took #{@time_difference} seconds"
131
+ "instead it took #{@time_difference} seconds"
129
132
  end
130
133
 
131
134
  def supports_block_expectations?
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'watirspec_helper'
2
4
 
3
5
  describe Watir::UserEditable do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'watirspec_helper'
2
4
 
3
5
  describe Watir do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'watirspec_helper'
2
4
 
3
5
  describe Watir::Browser do
@@ -400,13 +402,34 @@ describe Watir::Window do
400
402
  end
401
403
 
402
404
  context 'manipulating size and position', except: {headless: true} do
405
+ before(:all) do
406
+ maximized_size = browser.window.size
407
+
408
+ browser.window.resize_to(
409
+ maximized_size.width - 100,
410
+ maximized_size.height - 100
411
+ )
412
+ browser.wait_until { |b| b.window.size != maximized_size }
413
+
414
+ current_position = browser.window.position
415
+
416
+ browser.window.move_to(
417
+ current_position.x + 40,
418
+ current_position.y + 40
419
+ )
420
+ browser.wait_until { |b| b.window.position != current_position }
421
+
422
+ @initial_size = browser.window.size
423
+ @initial_position = browser.window.position
424
+ end
425
+
403
426
  before do
404
427
  browser.goto WatirSpec.url_for('window_switching.html')
405
- @initial_size = browser.window.size
406
428
  end
407
429
 
408
430
  after do
409
431
  browser.window.resize_to @initial_size.width, @initial_size.height
432
+ browser.window.move_to @initial_position.x, @initial_position.y
410
433
  end
411
434
 
412
435
  it 'should get the size of the current window' do
@@ -415,10 +438,8 @@ describe Watir::Window do
415
438
  end
416
439
 
417
440
  it 'should get the position of the current window' do
418
- pos = browser.window.position
419
-
420
- expect(pos.x).to eq browser.execute_script('return window.screenX;')
421
- expect(pos.y).to eq browser.execute_script('return window.screenY;')
441
+ expect(@initial_position.x).to eq browser.execute_script('return window.screenX;')
442
+ expect(@initial_position.y).to eq browser.execute_script('return window.screenY;')
422
443
  end
423
444
 
424
445
  it 'should resize the window' do
@@ -427,57 +448,45 @@ describe Watir::Window do
427
448
  @initial_size.height - 20
428
449
  )
429
450
 
430
- new_size = browser.window.size
451
+ browser.wait_until { |b| b.window.size != @initial_size }
431
452
 
453
+ new_size = browser.window.size
432
454
  expect(new_size.width).to eq @initial_size.width - 20
433
455
  expect(new_size.height).to eq @initial_size.height - 20
434
456
  end
435
457
 
436
458
  it 'should move the window' do
437
- initial_pos = browser.window.position
438
-
439
459
  browser.window.move_to(
440
- initial_pos.x + 2,
441
- initial_pos.y + 2
460
+ @initial_position.x + 5,
461
+ @initial_position.y + 5
442
462
  )
443
463
 
444
- new_pos = browser.window.position
445
- expect(new_pos.x).to eq initial_pos.x + 2
446
- expect(new_pos.y).to eq initial_pos.y + 2
447
- end
464
+ browser.wait_until { |b| b.window.position != @initial_position }
448
465
 
449
- it 'should maximize the window', except: {browser: :firefox, window_manager: false} do
450
- browser.window.resize_to(
451
- @initial_size.width - 40,
452
- @initial_size.height - 40
453
- )
454
- browser.wait_until { |b| b.window.size != @initial_size }
455
- new_size = browser.window.size
466
+ new_position = browser.window.position
467
+ expect(new_position.x).to eq @initial_position.x + 5
468
+ expect(new_position.y).to eq @initial_position.y + 5
469
+ end
456
470
 
471
+ it 'should maximize the window' do
457
472
  browser.window.maximize
458
- browser.wait_until { |b| b.window.size != new_size }
459
-
460
- final_size = browser.window.size
461
- expect(final_size.width).to be >= new_size.width
462
- expect(final_size.height).to be > new_size.height
463
- end
473
+ browser.wait_until { |b| b.window.size != @initial_size }
464
474
 
465
- it 'should make the window full screen', except: {browser: :firefox, window_manager: false} do
466
- browser.window.resize_to(
467
- @initial_size.width - 40,
468
- @initial_size.height - 40
469
- )
470
475
  new_size = browser.window.size
476
+ expect(new_size.width).to be >= @initial_size.width
477
+ expect(new_size.height).to be > @initial_size.height
478
+ end
471
479
 
480
+ it 'should make the window full screen' do
472
481
  browser.window.full_screen
473
- browser.wait_until { |b| b.window.size != new_size }
482
+ browser.wait_until { |b| b.window.size != @initial_size }
474
483
 
475
- final_size = browser.window.size
476
- expect(final_size.width).to be >= new_size.width
477
- expect(final_size.height).to be > new_size.height
484
+ new_size = browser.window.size
485
+ expect(new_size.width).to be >= @initial_size.width
486
+ expect(new_size.height).to be > @initial_size.height
478
487
  end
479
488
 
480
- it 'should minimize the window', except: {window_manager: false} do
489
+ it 'should minimize the window' do
481
490
  expect(browser.execute_script('return document.visibilityState;')).to eq 'visible'
482
491
 
483
492
  browser.window.minimize
@@ -485,6 +494,7 @@ describe Watir::Window do
485
494
  browser.wait_until { |b| b.execute_script('return document.visibilityState;') != 'visible' }
486
495
 
487
496
  expect(browser.execute_script('return document.visibilityState;')).to eq 'hidden'
497
+ browser.window.maximize
488
498
  end
489
499
  end
490
500
  end
@@ -557,7 +567,7 @@ describe Watir::WindowCollection do
557
567
  wins = browser.windows
558
568
  expect(wins.size).to eq 2
559
569
  wins.reset!
560
- expect(wins.instance_variable_get('@window_list')).to be_nil
570
+ expect(wins.instance_variable_get(:@window_list)).to be_nil
561
571
  end
562
572
 
563
573
  describe '#restore!' do