watir 1.4.1 → 7.3.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 (422) hide show
  1. checksums.yaml +7 -0
  2. data/.document +4 -0
  3. data/.github/ISSUE_TEMPLATE.md +16 -0
  4. data/.github/workflows/chrome.yml +55 -0
  5. data/.github/workflows/edge.yml +44 -0
  6. data/.github/workflows/firefox.yml +55 -0
  7. data/.github/workflows/ie.yml +30 -0
  8. data/.github/workflows/safari.yml +38 -0
  9. data/.github/workflows/unit.yml +60 -0
  10. data/.gitignore +21 -0
  11. data/.rubocop.yml +114 -0
  12. data/.rubocop_todo.yml +17 -0
  13. data/CHANGES.md +2212 -0
  14. data/Gemfile +15 -0
  15. data/LICENSE +24 -0
  16. data/README.md +113 -0
  17. data/Rakefile +173 -0
  18. data/lib/watir/adjacent.rb +128 -0
  19. data/lib/watir/after_hooks.rb +135 -0
  20. data/lib/watir/alert.rb +113 -0
  21. data/lib/watir/aliases.rb +8 -0
  22. data/lib/watir/attribute_helper.rb +97 -0
  23. data/lib/watir/browser.rb +323 -0
  24. data/lib/watir/capabilities.rb +179 -0
  25. data/lib/watir/cell_container.rb +25 -0
  26. data/lib/watir/container.rb +33 -0
  27. data/lib/watir/cookies.rb +130 -0
  28. data/lib/watir/element_collection.rb +223 -0
  29. data/lib/watir/elements/button.rb +28 -0
  30. data/lib/watir/elements/cell.rb +18 -0
  31. data/lib/watir/elements/checkbox.rb +56 -0
  32. data/lib/watir/elements/date_field.rb +42 -0
  33. data/lib/watir/elements/date_time_field.rb +42 -0
  34. data/lib/watir/elements/dlist.rb +12 -0
  35. data/lib/watir/elements/element.rb +807 -0
  36. data/lib/watir/elements/file_field.rb +43 -0
  37. data/lib/watir/elements/font.rb +26 -0
  38. data/lib/watir/elements/form.rb +16 -0
  39. data/lib/watir/elements/hidden.rb +26 -0
  40. data/lib/watir/elements/html_elements.rb +1981 -0
  41. data/lib/watir/elements/iframe.rb +156 -0
  42. data/lib/watir/elements/image.rb +22 -0
  43. data/lib/watir/elements/input.rb +15 -0
  44. data/lib/watir/elements/link.rb +8 -0
  45. data/lib/watir/elements/list.rb +51 -0
  46. data/lib/watir/elements/option.rb +60 -0
  47. data/lib/watir/elements/radio.rb +65 -0
  48. data/lib/watir/elements/row.rb +18 -0
  49. data/lib/watir/elements/select.rb +214 -0
  50. data/lib/watir/elements/svg_elements.rb +497 -0
  51. data/lib/watir/elements/table.rb +77 -0
  52. data/lib/watir/elements/table_cell.rb +32 -0
  53. data/lib/watir/elements/table_row.rb +34 -0
  54. data/lib/watir/elements/table_section.rb +17 -0
  55. data/lib/watir/elements/text_area.rb +7 -0
  56. data/lib/watir/elements/text_field.rb +39 -0
  57. data/lib/watir/exception.rb +16 -0
  58. data/lib/watir/extensions/nokogiri.rb +14 -0
  59. data/lib/watir/generator/base/generator.rb +114 -0
  60. data/lib/watir/generator/base/idl_sorter.rb +51 -0
  61. data/lib/watir/generator/base/spec_extractor.rb +158 -0
  62. data/lib/watir/generator/base/util.rb +21 -0
  63. data/lib/watir/generator/base/visitor.rb +133 -0
  64. data/lib/watir/generator/base.rb +12 -0
  65. data/lib/watir/generator/html/generator.rb +36 -0
  66. data/lib/watir/generator/html/spec_extractor.rb +52 -0
  67. data/lib/watir/generator/html/visitor.rb +23 -0
  68. data/lib/watir/generator/html.rb +17 -0
  69. data/lib/watir/generator/svg/generator.rb +38 -0
  70. data/lib/watir/generator/svg/spec_extractor.rb +55 -0
  71. data/lib/watir/generator/svg/visitor.rb +23 -0
  72. data/lib/watir/generator/svg.rb +9 -0
  73. data/lib/watir/generator.rb +5 -0
  74. data/lib/watir/has_window.rb +72 -0
  75. data/lib/watir/http_client.rb +11 -0
  76. data/lib/watir/js_execution.rb +165 -0
  77. data/lib/watir/js_snippets/attributeValues.js +11 -0
  78. data/lib/watir/js_snippets/backgroundColor.js +7 -0
  79. data/lib/watir/js_snippets/elementObscured.js +14 -0
  80. data/lib/watir/js_snippets/fireEvent.js +31 -0
  81. data/lib/watir/js_snippets/focus.js +3 -0
  82. data/lib/watir/js_snippets/getElementTags.js +3 -0
  83. data/lib/watir/js_snippets/getInnerHtml.js +19 -0
  84. data/lib/watir/js_snippets/getInnerText.js +19 -0
  85. data/lib/watir/js_snippets/getOuterHtml.js +20 -0
  86. data/lib/watir/js_snippets/getTextContent.js +19 -0
  87. data/lib/watir/js_snippets/isElementInViewport.js +20 -0
  88. data/lib/watir/js_snippets/isImageLoaded.js +3 -0
  89. data/lib/watir/js_snippets/selectOptionsLabel.js +10 -0
  90. data/lib/watir/js_snippets/selectOptionsText.js +10 -0
  91. data/lib/watir/js_snippets/selectOptionsValue.js +10 -0
  92. data/lib/watir/js_snippets/selectText.js +64 -0
  93. data/lib/watir/js_snippets/selectedOptions.js +11 -0
  94. data/lib/watir/js_snippets/selectedText.js +17 -0
  95. data/lib/watir/js_snippets/setText.js +3 -0
  96. data/lib/watir/js_snippets/setValue.js +3 -0
  97. data/lib/watir/js_snippets.rb +18 -0
  98. data/lib/watir/locators/anchor/selector_builder.rb +43 -0
  99. data/lib/watir/locators/button/matcher.rb +19 -0
  100. data/lib/watir/locators/button/selector_builder/xpath.rb +69 -0
  101. data/lib/watir/locators/button/selector_builder.rb +10 -0
  102. data/lib/watir/locators/cell/selector_builder/xpath.rb +23 -0
  103. data/lib/watir/locators/cell/selector_builder.rb +13 -0
  104. data/lib/watir/locators/element/locator.rb +81 -0
  105. data/lib/watir/locators/element/matcher.rb +118 -0
  106. data/lib/watir/locators/element/selector_builder/regexp_disassembler.rb +69 -0
  107. data/lib/watir/locators/element/selector_builder/xpath.rb +268 -0
  108. data/lib/watir/locators/element/selector_builder/xpath_support.rb +29 -0
  109. data/lib/watir/locators/element/selector_builder.rb +164 -0
  110. data/lib/watir/locators/option/matcher.rb +26 -0
  111. data/lib/watir/locators/option/selector_builder/xpath.rb +39 -0
  112. data/lib/watir/locators/option/selector_builder.rb +10 -0
  113. data/lib/watir/locators/row/selector_builder/xpath.rb +53 -0
  114. data/lib/watir/locators/row/selector_builder.rb +18 -0
  115. data/lib/watir/locators/text_area/selector_builder/xpath.rb +21 -0
  116. data/lib/watir/locators/text_area/selector_builder.rb +10 -0
  117. data/lib/watir/locators/text_field/matcher.rb +37 -0
  118. data/lib/watir/locators/text_field/selector_builder/xpath.rb +50 -0
  119. data/lib/watir/locators/text_field/selector_builder.rb +10 -0
  120. data/lib/watir/locators.rb +77 -0
  121. data/lib/watir/logger.rb +30 -0
  122. data/lib/watir/navigation.rb +51 -0
  123. data/lib/watir/radio_set.rb +230 -0
  124. data/lib/watir/row_container.rb +36 -0
  125. data/lib/watir/screenshot.rb +51 -0
  126. data/lib/watir/scroll.rb +95 -0
  127. data/lib/watir/search_context.rb +96 -0
  128. data/lib/watir/shadow_root.rb +60 -0
  129. data/lib/watir/user_editable.rb +85 -0
  130. data/lib/watir/version.rb +5 -0
  131. data/lib/watir/wait/timer.rb +52 -0
  132. data/lib/watir/wait.rb +171 -0
  133. data/lib/watir/window.rb +276 -0
  134. data/lib/watir/window_collection.rb +82 -0
  135. data/lib/watir.rb +108 -0
  136. data/lib/watirspec/guards.rb +65 -0
  137. data/lib/watirspec/implementation.rb +56 -0
  138. data/lib/watirspec/rake_tasks.rb +118 -0
  139. data/lib/watirspec/remote_server.rb +39 -0
  140. data/lib/watirspec/runner.rb +64 -0
  141. data/lib/watirspec/server/app.rb +86 -0
  142. data/lib/watirspec/server.rb +104 -0
  143. data/lib/watirspec.rb +93 -0
  144. data/spec/locator_spec_helper.rb +88 -0
  145. data/spec/spec_helper.rb +24 -0
  146. data/spec/unit/capabilities_spec.rb +670 -0
  147. data/spec/unit/element_locator_spec.rb +97 -0
  148. data/spec/unit/match_elements/button_spec.rb +76 -0
  149. data/spec/unit/match_elements/element_spec.rb +424 -0
  150. data/spec/unit/match_elements/text_field_spec.rb +84 -0
  151. data/spec/unit/selector_builder/anchor_spec.rb +59 -0
  152. data/spec/unit/selector_builder/button_spec.rb +217 -0
  153. data/spec/unit/selector_builder/cell_spec.rb +71 -0
  154. data/spec/unit/selector_builder/element_spec.rb +804 -0
  155. data/spec/unit/selector_builder/row_spec.rb +128 -0
  156. data/spec/unit/selector_builder/text_field_spec.rb +203 -0
  157. data/spec/unit/selector_builder/textarea_spec.rb +35 -0
  158. data/spec/unit/unit_helper.rb +4 -0
  159. data/spec/unit/wait_spec.rb +99 -0
  160. data/spec/watirspec/adjacent_spec.rb +256 -0
  161. data/spec/watirspec/after_hooks_spec.rb +204 -0
  162. data/spec/watirspec/alert_spec.rb +89 -0
  163. data/spec/watirspec/browser_spec.rb +536 -0
  164. data/spec/watirspec/capabilities_spec.rb +556 -0
  165. data/spec/watirspec/cookies_spec.rb +196 -0
  166. data/spec/watirspec/drag_and_drop_spec.rb +38 -0
  167. data/spec/watirspec/element_hidden_spec.rb +86 -0
  168. data/spec/watirspec/elements/area_spec.rb +69 -0
  169. data/spec/watirspec/elements/areas_spec.rb +44 -0
  170. data/spec/watirspec/elements/button_spec.rb +265 -0
  171. data/spec/watirspec/elements/buttons_spec.rb +57 -0
  172. data/spec/watirspec/elements/checkbox_spec.rb +290 -0
  173. data/spec/watirspec/elements/checkboxes_spec.rb +46 -0
  174. data/spec/watirspec/elements/collections_spec.rb +132 -0
  175. data/spec/watirspec/elements/date_field_spec.rb +209 -0
  176. data/spec/watirspec/elements/date_fields_spec.rb +46 -0
  177. data/spec/watirspec/elements/date_time_field_spec.rb +223 -0
  178. data/spec/watirspec/elements/date_time_fields_spec.rb +47 -0
  179. data/spec/watirspec/elements/dd_spec.rb +108 -0
  180. data/spec/watirspec/elements/dds_spec.rb +44 -0
  181. data/spec/watirspec/elements/del_spec.rb +113 -0
  182. data/spec/watirspec/elements/dels_spec.rb +42 -0
  183. data/spec/watirspec/elements/div_spec.rb +232 -0
  184. data/spec/watirspec/elements/divs_spec.rb +56 -0
  185. data/spec/watirspec/elements/dl_spec.rb +117 -0
  186. data/spec/watirspec/elements/dls_spec.rb +45 -0
  187. data/spec/watirspec/elements/dt_spec.rb +107 -0
  188. data/spec/watirspec/elements/dts_spec.rb +44 -0
  189. data/spec/watirspec/elements/element_spec.rb +1069 -0
  190. data/spec/watirspec/elements/elements_spec.rb +60 -0
  191. data/spec/watirspec/elements/em_spec.rb +85 -0
  192. data/spec/watirspec/elements/ems_spec.rb +45 -0
  193. data/spec/watirspec/elements/filefield_spec.rb +135 -0
  194. data/spec/watirspec/elements/filefields_spec.rb +45 -0
  195. data/spec/watirspec/elements/font_spec.rb +31 -0
  196. data/spec/watirspec/elements/form_spec.rb +70 -0
  197. data/spec/watirspec/elements/forms_spec.rb +46 -0
  198. data/spec/watirspec/elements/frame_spec.rb +117 -0
  199. data/spec/watirspec/elements/frames_spec.rb +43 -0
  200. data/spec/watirspec/elements/hidden_spec.rb +106 -0
  201. data/spec/watirspec/elements/hiddens_spec.rb +45 -0
  202. data/spec/watirspec/elements/hn_spec.rb +80 -0
  203. data/spec/watirspec/elements/hns_spec.rb +42 -0
  204. data/spec/watirspec/elements/iframe_spec.rb +244 -0
  205. data/spec/watirspec/elements/iframes_spec.rb +49 -0
  206. data/spec/watirspec/elements/image_spec.rb +160 -0
  207. data/spec/watirspec/elements/images_spec.rb +42 -0
  208. data/spec/watirspec/elements/input_spec.rb +17 -0
  209. data/spec/watirspec/elements/ins_spec.rb +113 -0
  210. data/spec/watirspec/elements/inses_spec.rb +42 -0
  211. data/spec/watirspec/elements/label_spec.rb +77 -0
  212. data/spec/watirspec/elements/labels_spec.rb +42 -0
  213. data/spec/watirspec/elements/li_spec.rb +99 -0
  214. data/spec/watirspec/elements/link_spec.rb +180 -0
  215. data/spec/watirspec/elements/links_spec.rb +66 -0
  216. data/spec/watirspec/elements/lis_spec.rb +44 -0
  217. data/spec/watirspec/elements/list_spec.rb +50 -0
  218. data/spec/watirspec/elements/map_spec.rb +78 -0
  219. data/spec/watirspec/elements/maps_spec.rb +43 -0
  220. data/spec/watirspec/elements/meta_spec.rb +27 -0
  221. data/spec/watirspec/elements/metas_spec.rb +42 -0
  222. data/spec/watirspec/elements/ol_spec.rb +63 -0
  223. data/spec/watirspec/elements/ols_spec.rb +42 -0
  224. data/spec/watirspec/elements/option_spec.rb +113 -0
  225. data/spec/watirspec/elements/p_spec.rb +102 -0
  226. data/spec/watirspec/elements/pre_spec.rb +100 -0
  227. data/spec/watirspec/elements/pres_spec.rb +42 -0
  228. data/spec/watirspec/elements/ps_spec.rb +42 -0
  229. data/spec/watirspec/elements/radio_spec.rb +259 -0
  230. data/spec/watirspec/elements/radios_spec.rb +45 -0
  231. data/spec/watirspec/elements/select_list_spec.rb +701 -0
  232. data/spec/watirspec/elements/select_lists_spec.rb +49 -0
  233. data/spec/watirspec/elements/span_spec.rb +119 -0
  234. data/spec/watirspec/elements/spans_spec.rb +42 -0
  235. data/spec/watirspec/elements/strong_spec.rb +78 -0
  236. data/spec/watirspec/elements/strongs_spec.rb +45 -0
  237. data/spec/watirspec/elements/table_spec.rb +210 -0
  238. data/spec/watirspec/elements/tables_spec.rb +44 -0
  239. data/spec/watirspec/elements/tbody_spec.rb +94 -0
  240. data/spec/watirspec/elements/tbodys_spec.rb +64 -0
  241. data/spec/watirspec/elements/td_spec.rb +92 -0
  242. data/spec/watirspec/elements/tds_spec.rb +55 -0
  243. data/spec/watirspec/elements/text_field_spec.rb +223 -0
  244. data/spec/watirspec/elements/text_fields_spec.rb +47 -0
  245. data/spec/watirspec/elements/textarea_spec.rb +30 -0
  246. data/spec/watirspec/elements/textareas_spec.rb +28 -0
  247. data/spec/watirspec/elements/tfoot_spec.rb +89 -0
  248. data/spec/watirspec/elements/tfoots_spec.rb +72 -0
  249. data/spec/watirspec/elements/thead_spec.rb +88 -0
  250. data/spec/watirspec/elements/theads_spec.rb +72 -0
  251. data/spec/watirspec/elements/tr_spec.rb +69 -0
  252. data/spec/watirspec/elements/trs_spec.rb +63 -0
  253. data/spec/watirspec/elements/ul_spec.rb +63 -0
  254. data/spec/watirspec/elements/uls_spec.rb +42 -0
  255. data/spec/watirspec/html/alerts.html +12 -0
  256. data/spec/watirspec/html/aria_attributes.html +9 -0
  257. data/spec/watirspec/html/child_frame.html +29 -0
  258. data/spec/watirspec/html/class_locator.html +11 -0
  259. data/spec/watirspec/html/clicks.html +19 -0
  260. data/spec/watirspec/html/closeable.html +21 -0
  261. data/spec/watirspec/html/collections.html +15 -0
  262. data/spec/watirspec/html/css/jquery-ui-1.8.17.custom.css +287 -0
  263. data/spec/watirspec/html/data_attributes.html +10 -0
  264. data/spec/watirspec/html/definition_lists.html +48 -0
  265. data/spec/watirspec/html/drag_and_drop.html +106 -0
  266. data/spec/watirspec/html/font.html +10 -0
  267. data/spec/watirspec/html/forms_with_input_elements.html +194 -0
  268. data/spec/watirspec/html/frame_1.html +22 -0
  269. data/spec/watirspec/html/frame_2.html +16 -0
  270. data/spec/watirspec/html/frames.html +11 -0
  271. data/spec/watirspec/html/iframe_1.html +22 -0
  272. data/spec/watirspec/html/iframes.html +15 -0
  273. data/spec/watirspec/html/images/button.png +0 -0
  274. data/spec/watirspec/html/images/circle.png +0 -0
  275. data/spec/watirspec/html/images/map.gif +0 -0
  276. data/spec/watirspec/html/images/map2.gif +0 -0
  277. data/spec/watirspec/html/images/originaltriangle.png +0 -0
  278. data/spec/watirspec/html/images/square.png +0 -0
  279. data/spec/watirspec/html/images/triangle.png +0 -0
  280. data/spec/watirspec/html/images.html +28 -0
  281. data/spec/watirspec/html/inner_outer.html +5 -0
  282. data/spec/watirspec/html/javascript/angular.min.js +332 -0
  283. data/spec/watirspec/html/javascript/helpers.js +16 -0
  284. data/spec/watirspec/html/javascript/jquery-1.7.1.min.js +4 -0
  285. data/spec/watirspec/html/javascript/jquery-ui-1.8.17.custom.min.js +68 -0
  286. data/spec/watirspec/html/keylogger.html +15 -0
  287. data/spec/watirspec/html/modal_dialog.html +9 -0
  288. data/spec/watirspec/html/multiple_ids.html +15 -0
  289. data/spec/watirspec/html/nested_elements.html +44 -0
  290. data/spec/watirspec/html/nested_frame_1.html +1 -0
  291. data/spec/watirspec/html/nested_frame_2.html +9 -0
  292. data/spec/watirspec/html/nested_frame_3.html +14 -0
  293. data/spec/watirspec/html/nested_frames.html +10 -0
  294. data/spec/watirspec/html/nested_iframe_2.html +12 -0
  295. data/spec/watirspec/html/nested_iframes.html +13 -0
  296. data/spec/watirspec/html/nested_tables.html +203 -0
  297. data/spec/watirspec/html/non_control_elements.html +145 -0
  298. data/spec/watirspec/html/obscured.html +36 -0
  299. data/spec/watirspec/html/removed_element.html +24 -0
  300. data/spec/watirspec/html/right_click.html +23 -0
  301. data/spec/watirspec/html/scroll.html +15 -0
  302. data/spec/watirspec/html/scroll_nested.html +17 -0
  303. data/spec/watirspec/html/scroll_nested_offscreen.html +18 -0
  304. data/spec/watirspec/html/shadow_dom.html +28 -0
  305. data/spec/watirspec/html/special_chars.html +15 -0
  306. data/spec/watirspec/html/sticky_elements.html +10 -0
  307. data/spec/watirspec/html/tables.html +121 -0
  308. data/spec/watirspec/html/timeout_window_location.html +19 -0
  309. data/spec/watirspec/html/uneven_table.html +20 -0
  310. data/spec/watirspec/html/wait.html +99 -0
  311. data/spec/watirspec/html/watirspec.css +0 -0
  312. data/spec/watirspec/html/window_switching.html +22 -0
  313. data/spec/watirspec/radio_set_spec.rb +346 -0
  314. data/spec/watirspec/screenshot_spec.rb +33 -0
  315. data/spec/watirspec/scroll_spec.rb +208 -0
  316. data/spec/watirspec/shadow_root_spec.rb +108 -0
  317. data/spec/watirspec/support/rspec_matchers.rb +161 -0
  318. data/spec/watirspec/user_editable_spec.rb +207 -0
  319. data/spec/watirspec/wait_spec.rb +345 -0
  320. data/spec/watirspec/window_switching_spec.rb +580 -0
  321. data/spec/watirspec_helper.rb +163 -0
  322. data/support/doctest_helper.rb +101 -0
  323. data/support/version_differ.rb +60 -0
  324. data/watir.gemspec +50 -0
  325. metadata +652 -148
  326. data/readme.rb +0 -211
  327. data/unittests/WindowLogonExample.rb +0 -30
  328. data/unittests/WindowLogonExtra.rb +0 -7
  329. data/unittests/all_tests.rb +0 -10
  330. data/unittests/all_tests_concurrent.rb +0 -57
  331. data/unittests/attachToExistingWindow_test.rb +0 -40
  332. data/unittests/buttons_test.rb +0 -131
  333. data/unittests/checkbox_test.rb +0 -149
  334. data/unittests/core_tests.rb +0 -9
  335. data/unittests/css_test.rb +0 -60
  336. data/unittests/div_test.rb +0 -179
  337. data/unittests/errorchecker_test.rb +0 -29
  338. data/unittests/filefield_test.rb +0 -35
  339. data/unittests/form_test.rb +0 -279
  340. data/unittests/frame_test.rb +0 -141
  341. data/unittests/html/blankpage.html +0 -12
  342. data/unittests/html/buttons1.html +0 -40
  343. data/unittests/html/checkboxes1.html +0 -69
  344. data/unittests/html/complex_table.html +0 -36
  345. data/unittests/html/cssTest.html +0 -42
  346. data/unittests/html/div.html +0 -105
  347. data/unittests/html/fileupload.html +0 -45
  348. data/unittests/html/formTest1.html +0 -39
  349. data/unittests/html/forms2.html +0 -45
  350. data/unittests/html/forms3.html +0 -132
  351. data/unittests/html/forms4.html +0 -27
  352. data/unittests/html/frame_buttons.html +0 -4
  353. data/unittests/html/frame_links.html +0 -4
  354. data/unittests/html/frame_multi.html +0 -5
  355. data/unittests/html/iframeTest.html +0 -13
  356. data/unittests/html/iframeTest1.html +0 -7
  357. data/unittests/html/iframeTest2.html +0 -6
  358. data/unittests/html/images/button.jpg +0 -0
  359. data/unittests/html/images/circle.jpg +0 -0
  360. data/unittests/html/images/originaltriangle.jpg +0 -0
  361. data/unittests/html/images/square.jpg +0 -0
  362. data/unittests/html/images/triangle.jpg +0 -0
  363. data/unittests/html/images1.html +0 -52
  364. data/unittests/html/javascriptevents.html +0 -39
  365. data/unittests/html/link_pass.html +0 -11
  366. data/unittests/html/links1.html +0 -37
  367. data/unittests/html/links2.html +0 -11
  368. data/unittests/html/nestedFrames.html +0 -6
  369. data/unittests/html/pass.html +0 -10
  370. data/unittests/html/popups1.html +0 -60
  371. data/unittests/html/radioButtons1.html +0 -71
  372. data/unittests/html/select_tealeaf.html +0 -54
  373. data/unittests/html/selectboxes1.html +0 -55
  374. data/unittests/html/simple_table.html +0 -26
  375. data/unittests/html/simple_table_buttons.html +0 -104
  376. data/unittests/html/simple_table_columns.html +0 -76
  377. data/unittests/html/table1.html +0 -142
  378. data/unittests/html/textarea.html +0 -30
  379. data/unittests/html/textfields1.html +0 -87
  380. data/unittests/html/textsearch.html +0 -44
  381. data/unittests/ie_mock.rb +0 -93
  382. data/unittests/ie_test.rb +0 -50
  383. data/unittests/images_test.rb +0 -179
  384. data/unittests/iostring.rb +0 -30
  385. data/unittests/iostring_test.rb +0 -48
  386. data/unittests/js_events_test.rb +0 -77
  387. data/unittests/jscriptExtraAlert.rb +0 -6
  388. data/unittests/jscriptExtraConfirmCancel.rb +0 -7
  389. data/unittests/jscriptExtraConfirmOk.rb +0 -7
  390. data/unittests/jscriptPushButton.rb +0 -5
  391. data/unittests/jscript_test.rb +0 -57
  392. data/unittests/links_test.rb +0 -169
  393. data/unittests/minmax_test.rb +0 -31
  394. data/unittests/navigate_test.rb +0 -56
  395. data/unittests/non_core_tests.rb +0 -9
  396. data/unittests/pagecontainstext_test.rb +0 -49
  397. data/unittests/popups_test.rb +0 -44
  398. data/unittests/radios_test.rb +0 -164
  399. data/unittests/screen_capture_test.rb +0 -53
  400. data/unittests/selectbox_test.rb +0 -197
  401. data/unittests/send_keys_test.rb +0 -29
  402. data/unittests/setup.rb +0 -47
  403. data/unittests/table_test.rb +0 -306
  404. data/unittests/textAreafields_test.rb +0 -81
  405. data/unittests/textfields_test.rb +0 -239
  406. data/watir/AutoItX3.dll +0 -0
  407. data/watir/WindowHelper.rb +0 -47
  408. data/watir/camel_case.rb +0 -37
  409. data/watir/clickJSDialog.rb +0 -19
  410. data/watir/cookiemanager.rb +0 -53
  411. data/watir/exceptions.rb +0 -60
  412. data/watir/screen_capture.rb +0 -115
  413. data/watir/setFileDialog.rb +0 -16
  414. data/watir/testUnitAddons.rb +0 -47
  415. data/watir/watir_simple.rb +0 -475
  416. data/watir/winClicker.rb +0 -505
  417. data/watir.rb +0 -3744
  418. /data/{unittests → spec/watirspec}/html/images/1.gif +0 -0
  419. /data/{unittests/html/images/2.GIF → spec/watirspec/html/images/2.gif} +0 -0
  420. /data/{unittests/html/images/3.GIF → spec/watirspec/html/images/3.gif} +0 -0
  421. /data/{unittests/html/images/minus.GIF → spec/watirspec/html/images/minus.gif} +0 -0
  422. /data/{unittests → spec/watirspec}/html/images/plus.gif +0 -0
@@ -0,0 +1,807 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Watir
4
+ #
5
+ # Base class for HTML elements.
6
+ #
7
+
8
+ class Element
9
+ extend AttributeHelper
10
+
11
+ include Exception
12
+ include Container
13
+ include Waitable
14
+ include Adjacent
15
+ include JSExecution
16
+ include Locators::ClassHelpers
17
+ include Scrolling
18
+ include SearchContext
19
+
20
+ attr_accessor :keyword
21
+ attr_reader :selector
22
+
23
+ # https://www.w3.org/TR/html52/single-page.html#casesensitivity
24
+ CASE_INSENSITIVE_ATTRIBUTES = %i[accept accept_charset align alink axis
25
+ bgcolor charset checked clear codetype
26
+ color compact declare defer dir direction
27
+ disabled enctype face frame hreflang
28
+ http_equiv lang language link media
29
+ method multiple nohref noresize noshade
30
+ nowrap readonly rel rev rules scope
31
+ scrolling selected shape target text
32
+ type valign valuetype vlink].freeze
33
+
34
+ #
35
+ # temporarily add :id and :class_name manually since they're no longer specified in the HTML spec.
36
+ #
37
+ # @see http://html5.org/r/6605
38
+ # @see http://html5.org/r/7174
39
+ #
40
+ # TODO: use IDL from DOM core - http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
41
+ #
42
+ attribute String, :id, :id
43
+ attribute String, :class_name, :className
44
+
45
+ def initialize(query_scope, selector)
46
+ @query_scope = query_scope
47
+
48
+ raise ArgumentError, "invalid argument: #{selector.inspect}" unless selector.is_a? Hash
49
+
50
+ selector[:index] = 0 if selector.empty?
51
+ @element = selector.delete(:element)
52
+
53
+ selector = {} if @element && !(selector.keys - [:tag_name]).empty?
54
+
55
+ @selector = selector
56
+
57
+ build unless @element
58
+ end
59
+
60
+ def inspect
61
+ keyword_string = keyword ? "keyword: #{keyword} " : ''
62
+ located = "located: #{located?}; "
63
+ element_string = @selector.empty? ? '{element: (selenium element)}' : selector_string
64
+ "#<#{self.class}: #{keyword_string}#{located}#{element_string}>"
65
+ end
66
+
67
+ #
68
+ # Returns true if two elements are equal.
69
+ #
70
+ # TODO: Address how this is affected by stale elements
71
+ # TODO: Address how this is affected by HTMLElement vs subclass
72
+ # TODO: Address how this is affected by a non-located element
73
+ #
74
+ # @example
75
+ # browser.text_field(name: "new_user_first_name") == browser.text_field(name: "new_user_first_name")
76
+ # #=> true
77
+ #
78
+
79
+ def ==(other)
80
+ other.is_a?(self.class) && wd == other.wd
81
+ end
82
+ alias eql? ==
83
+
84
+ def hash
85
+ located? ? @element.hash : super
86
+ end
87
+
88
+ #
89
+ # Returns the text of the element.
90
+ #
91
+ # @return [String]
92
+ #
93
+
94
+ def text
95
+ element_call { @element.text }
96
+ end
97
+
98
+ #
99
+ # Returns tag name of the element.
100
+ #
101
+ # @return [String]
102
+ #
103
+
104
+ def tag_name
105
+ element_call { @element.tag_name.downcase }
106
+ end
107
+
108
+ #
109
+ # Clicks the element, optionally while pressing the given modifier keys.
110
+ # Note that support for holding a modifier key is currently experimental,
111
+ # and may not work at all.
112
+ #
113
+ # @example Click an element
114
+ # browser.element(name: "new_user_button").click
115
+ #
116
+ # @example Click an element with shift key pressed
117
+ # browser.element(name: "new_user_button").click(:shift)
118
+ #
119
+ # @example Click an element with several modifier keys pressed
120
+ # browser.element(name: "new_user_button").click(:shift, :control)
121
+ #
122
+ # @param [:shift, :alt, :control, :command, :meta] modifiers to press while clicking.
123
+ #
124
+
125
+ def click(*modifiers, scroll_to: :center)
126
+ element_call(:wait_for_enabled) do
127
+ if modifiers.any?
128
+ scroll.to(scroll_to) if scroll_to
129
+ action = driver.action
130
+ modifiers.each { |mod| action.key_down mod }
131
+ action.click @element
132
+ modifiers.each { |mod| action.key_up mod }
133
+
134
+ action.perform
135
+ else
136
+ @element.click
137
+ end
138
+ end
139
+
140
+ browser.after_hooks.run
141
+ end
142
+
143
+ #
144
+ # Determines the correct action based on subtype and takes it.
145
+ # Default is to click element
146
+ #
147
+
148
+ def set(*args)
149
+ subtype = to_subtype
150
+ if subtype.is_a?(Radio) && [String, Regexp].include?(args.first.class)
151
+ RadioSet.new(@query_scope, selector).set(*args)
152
+ elsif subtype.class.included_modules.include?(UserEditable) || subtype.public_methods(false).include?(:set)
153
+ subtype.set(*args)
154
+ elsif @content_editable || content_editable?
155
+ @content_editable = true
156
+ extend UserEditable
157
+ set(*args)
158
+ elsif args.empty? || args.first
159
+ click(*args)
160
+ end
161
+ end
162
+
163
+ #
164
+ # Simulates JavaScript click event on element.
165
+ #
166
+ # @example Click an element
167
+ # browser.element(name: "new_user_button").click!
168
+ #
169
+
170
+ def click!
171
+ fire_event :click
172
+ browser.after_hooks.run
173
+ end
174
+
175
+ #
176
+ # Double clicks the element.
177
+ # Note that browser support may vary.
178
+ #
179
+ # @example
180
+ # browser.element(name: "new_user_button").double_click
181
+ #
182
+ # @example
183
+ # browser.element(name: "new_user_button").double_click(scroll_to: :center)
184
+ #
185
+
186
+ def double_click(scroll_to: :center)
187
+ element_call(:wait_for_present) do
188
+ scroll.to(scroll_to) if scroll_to
189
+ driver.action.double_click(@element).perform
190
+ end
191
+ browser.after_hooks.run
192
+ end
193
+
194
+ #
195
+ # Simulates JavaScript double click event on element.
196
+ #
197
+ # @example
198
+ # browser.element(name: "new_user_button").double_click!
199
+ #
200
+
201
+ def double_click!
202
+ fire_event :dblclick
203
+ browser.after_hooks.run
204
+ end
205
+
206
+ #
207
+ # Right clicks the element, optionally while pressing the given modifier keys.
208
+ # Note that support for holding a modifier key is currently experimental,
209
+ # and may not work at all. Also, the browser support may vary.
210
+ #
211
+ # @example
212
+ # browser.element(name: "new_user_button").right_click
213
+ #
214
+ # @example Right click an element with shift key pressed
215
+ # browser.element(name: "new_user_button").right_click(:shift)
216
+ #
217
+ # @example Click an element with several modifier keys pressed
218
+ # browser.element(name: "new_user_button").right_click(:shift, :alt)
219
+ #
220
+ # @example Click an element with several modifier keys pressed and scroll position
221
+ # browser.element(name: "new_user_button").right_click(:shift, :alt, scroll_to: :center)
222
+ #
223
+ # @param [:shift, :alt, :control, :command, :meta, scroll_to: :center]
224
+ # modifiers to press while right clicking and scroll position.
225
+ #
226
+
227
+ def right_click(*modifiers, scroll_to: :center)
228
+ element_call(:wait_for_present) do
229
+ scroll.to(scroll_to) if scroll_to
230
+ action = driver.action
231
+ if modifiers.any?
232
+ modifiers.each { |mod| action.key_down mod }
233
+ action.context_click(@element)
234
+ modifiers.each { |mod| action.key_up mod }
235
+ action.perform
236
+ else
237
+ action.context_click(@element).perform
238
+ end
239
+ end
240
+
241
+ browser.after_hooks.run
242
+ end
243
+
244
+ #
245
+ # Moves the mouse to the middle of this element.
246
+ # Note that browser support may vary.
247
+ #
248
+ # @example
249
+ # browser.element(name: "new_user_button").hover
250
+ #
251
+ # @example
252
+ # browser.element(name: "new_user_button").hover(scroll_to: :center)
253
+ #
254
+
255
+ def hover(scroll_to: :center)
256
+ element_call(:wait_for_present) do
257
+ scroll.to(scroll_to) if scroll_to
258
+ driver.action.move_to(@element).perform
259
+ end
260
+ end
261
+
262
+ #
263
+ # Drag and drop this element on to another element instance.
264
+ # Note that browser support may vary.
265
+ #
266
+ # @example
267
+ # a = browser.div(id: "draggable")
268
+ # b = browser.div(id: "droppable")
269
+ # a.drag_and_drop_on b
270
+ # a.drag_and_drop_on b, scroll_to: :center
271
+ #
272
+
273
+ def drag_and_drop_on(other, scroll_to: :center)
274
+ assert_is_element other
275
+
276
+ value = element_call(:wait_for_present) do
277
+ scroll.to(scroll_to) if scroll_to
278
+ driver.action
279
+ .drag_and_drop(@element, other.wd)
280
+ .perform
281
+ end
282
+ browser.after_hooks.run
283
+ value
284
+ end
285
+
286
+ #
287
+ # Drag and drop this element by the given offsets.
288
+ # Note that browser support may vary.
289
+ #
290
+ # @example
291
+ # browser.div(id: "draggable").drag_and_drop_by 100, 25
292
+ #
293
+ # @example
294
+ # browser.div(id: "draggable").drag_and_drop_by 100, 25, scroll_to: :center
295
+ #
296
+ # @param [Integer] right_by
297
+ # @param [Integer] down_by
298
+ # @param [Symbol] scroll_to
299
+ #
300
+
301
+ def drag_and_drop_by(right_by, down_by, scroll_to: :center)
302
+ element_call(:wait_for_present) do
303
+ scroll.to(scroll_to) if scroll_to
304
+ driver.action
305
+ .drag_and_drop_by(@element, right_by, down_by)
306
+ .perform
307
+ end
308
+ end
309
+
310
+ #
311
+ # Returns list of class values.
312
+ #
313
+ # @return [Array]
314
+ #
315
+
316
+ def classes
317
+ class_name.split
318
+ end
319
+
320
+ #
321
+ # Returns given attribute value of element.
322
+ #
323
+ # @example
324
+ # browser.a(id: "link_2").attribute_value "title"
325
+ # #=> "link_title_2"
326
+ #
327
+ # @param [String, ::Symbol] attribute_name
328
+ # @return [String, nil]
329
+ #
330
+
331
+ def attribute_value(attribute_name)
332
+ attribute_name = attribute_name.to_s.tr('_', '-') if attribute_name.is_a?(::Symbol)
333
+ element_call { @element.attribute attribute_name }
334
+ end
335
+ alias attribute attribute_value
336
+
337
+ #
338
+ # Returns all attribute values. Attributes with special characters are returned as String,
339
+ # rest are returned as a Symbol.
340
+ #
341
+ # @return [Hash]
342
+ #
343
+ # @example
344
+ # browser.pre(id: 'rspec').attribute_values
345
+ # #=> {class:'ruby', id: 'rspec' }
346
+ #
347
+
348
+ def attribute_values
349
+ result = element_call { execute_js(:attributeValues, @element) }
350
+ result.keys.each do |key|
351
+ next unless key == key[/[a-zA-Z-]*/]
352
+
353
+ result[key.tr('-', '_').to_sym] = result.delete(key)
354
+ end
355
+ result
356
+ end
357
+ alias attributes attribute_values
358
+
359
+ #
360
+ # Returns list of all attributes. Attributes with special characters are returned as String,
361
+ # rest are returned as a Symbol.
362
+ #
363
+ # @return [Array]
364
+ #
365
+ # @example
366
+ # browser.pre(id: 'rspec').attribute_list
367
+ # #=> [:class, :id]
368
+ #
369
+
370
+ def attribute_list
371
+ attribute_values.keys
372
+ end
373
+
374
+ #
375
+ # Sends sequence of keystrokes to element.
376
+ #
377
+ # @example
378
+ # browser.text_field(name: "new_user_first_name").send_keys "Watir", :return
379
+ #
380
+ # @param [String, Symbol] args
381
+ #
382
+
383
+ def send_keys(*args)
384
+ element_call(:wait_for_writable) { @element.send_keys(*args) }
385
+ end
386
+
387
+ #
388
+ # Returns true if this element is focused.
389
+ #
390
+ # @return [Boolean]
391
+ #
392
+
393
+ def focused?
394
+ element_call { @element == driver.switch_to.active_element }
395
+ end
396
+
397
+ #
398
+ # location of element (x, y)
399
+ #
400
+ # @example
401
+ # browser.button(name: "new_user_button").location
402
+ #
403
+ # @return [Selenium::WebDriver::Point]
404
+ #
405
+
406
+ def location
407
+ element_call { @element.location }
408
+ end
409
+
410
+ #
411
+ # size of element (width, height)
412
+ #
413
+ # @example
414
+ # browser.button(name: "new_user_button").size
415
+ #
416
+ # @return [Selenium::WebDriver::Dimension]
417
+ #
418
+
419
+ def size
420
+ element_call { @element.size }
421
+ end
422
+
423
+ #
424
+ # Get height of element
425
+ #
426
+ # @example
427
+ # browser.button(name: "new_user_button").height
428
+ #
429
+ # @return [Selenium::WebDriver::Dimension]
430
+ #
431
+
432
+ def height
433
+ size['height']
434
+ end
435
+
436
+ #
437
+ # Get width of element
438
+ #
439
+ # @example
440
+ # browser.button(name: "new_user_button").width
441
+ #
442
+ # @return [Selenium::WebDriver::Dimension]
443
+ #
444
+
445
+ def width
446
+ size['width']
447
+ end
448
+
449
+ #
450
+ # Get centre coordinates of element
451
+ #
452
+ # @example
453
+ # browser.button(name: "new_user_button").centre
454
+ #
455
+ # @return [Selenium::WebDriver::Point]
456
+ #
457
+
458
+ def center
459
+ point = location
460
+ dimensions = size
461
+ Selenium::WebDriver::Point.new(point.x + (dimensions['width'] / 2),
462
+ point.y + (dimensions['height'] / 2))
463
+ end
464
+ alias centre center
465
+
466
+ #
467
+ # @api private
468
+ #
469
+
470
+ def driver
471
+ @query_scope.driver
472
+ end
473
+
474
+ #
475
+ # Returns underlying Selenium object of the Watir Element
476
+ #
477
+ # @return [Selenium::WebDriver::Element]
478
+ #
479
+
480
+ def wd
481
+ assert_exists
482
+ @element
483
+ end
484
+ alias we wd
485
+
486
+ #
487
+ # Returns shadow root of element
488
+ #
489
+ # @return [Watir::ShadowRoot]
490
+ #
491
+
492
+ def shadow_root
493
+ ShadowRoot.new(self)
494
+ end
495
+
496
+ #
497
+ # Returns true if this element is present and enabled on the page.
498
+ #
499
+ # @return [Boolean]
500
+ # @see Watir::Wait
501
+ #
502
+
503
+ def enabled?
504
+ element_call(:assert_exists) { @element.enabled? }
505
+ end
506
+
507
+ #
508
+ # Returns true if the element exists and is visible on the page.
509
+ # Returns false if element does not exist or exists but is not visible
510
+ #
511
+ # @return [Boolean]
512
+ # @see Watir::Wait
513
+ #
514
+
515
+ def present?
516
+ assert_exists
517
+ @element.displayed?
518
+ rescue UnknownObjectException, UnknownFrameException
519
+ false
520
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError
521
+ reset!
522
+ retry
523
+ end
524
+ alias visible? present?
525
+
526
+ #
527
+ # Returns true if the element's center point is covered by a non-descendant element.
528
+ #
529
+ # @return [Boolean]
530
+ #
531
+
532
+ def obscured?
533
+ element_call do
534
+ return true unless present?
535
+
536
+ scroll.to :bottom unless in_viewport?
537
+ execute_js(:elementObscured, self)
538
+ end
539
+ end
540
+
541
+ #
542
+ # Returns true if the top of the element is visible in the viewport.
543
+ #
544
+ # @return [Boolean]
545
+ #
546
+
547
+ def in_viewport?
548
+ element_call { execute_js(:isElementInViewport, @element) }
549
+ end
550
+
551
+ #
552
+ # Returns given style property of this element.
553
+ #
554
+ # @example
555
+ # browser.button(value: "Delete").style #=> "border: 4px solid red;"
556
+ # browser.button(value: "Delete").style("border") #=> "4px solid rgb(255, 0, 0)"
557
+ #
558
+ # @param [String] property
559
+ # @return [String]
560
+ #
561
+
562
+ def style(property = nil)
563
+ if property
564
+ element_call { @element.style property }
565
+ else
566
+ attribute_value('style').to_s.strip
567
+ end
568
+ end
569
+
570
+ #
571
+ # Cast this Element instance to a more specific subtype.
572
+ #
573
+ # @example
574
+ # browser.element(xpath: "//input[@type='submit']").to_subtype
575
+ # #=> #<Watir::Button>
576
+ #
577
+
578
+ def to_subtype
579
+ tag = tag_name
580
+ klass = if tag == 'input'
581
+ case attribute_value(:type)
582
+ when 'checkbox'
583
+ CheckBox
584
+ when 'radio'
585
+ Radio
586
+ when 'file'
587
+ FileField
588
+ when *Button::VALID_TYPES
589
+ Button
590
+ else
591
+ TextField
592
+ end
593
+ else
594
+ Watir.element_class_for(tag)
595
+ end
596
+
597
+ klass.new(@query_scope, @selector).tap { |el| el.cache = wd }
598
+ end
599
+
600
+ #
601
+ # Returns browser.
602
+ #
603
+ # @return [Watir::Browser]
604
+ #
605
+
606
+ def browser
607
+ @query_scope.browser
608
+ end
609
+
610
+ #
611
+ # Returns true if a previously located element is no longer attached to DOM.
612
+ #
613
+ # @return [Boolean]
614
+ # @see Watir::Wait
615
+ #
616
+
617
+ def stale?
618
+ raise Error, 'Can not check staleness of unused element' unless @element
619
+
620
+ ensure_context
621
+ stale_in_context?
622
+ end
623
+
624
+ def stale_in_context?
625
+ @element.css_value('staleness_check') # any wire call will check for staleness
626
+ false
627
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError
628
+ true
629
+ end
630
+
631
+ def reset!
632
+ @element = nil
633
+ end
634
+
635
+ #
636
+ # @api private
637
+ #
638
+
639
+ def locate
640
+ msg = 'Can not relocate a Watir element initialized by a Selenium element'
641
+ raise LocatorException, msg if @selector.empty?
642
+
643
+ ensure_context
644
+ locate_in_context
645
+ self
646
+ end
647
+
648
+ #
649
+ # @api private
650
+ #
651
+
652
+ def build
653
+ selector_builder.build(@selector.dup)
654
+ end
655
+
656
+ #
657
+ # @api private
658
+ #
659
+ # Returns true if element has been previously located.
660
+ #
661
+ # @return [Boolean]
662
+ #
663
+
664
+ def located?
665
+ !!@element
666
+ end
667
+
668
+ #
669
+ # @api private
670
+ #
671
+ # Set the cached element. For use when element can be relocated with the provided selector.
672
+ #
673
+
674
+ def cache=(element)
675
+ @element = element
676
+ end
677
+
678
+ #
679
+ # @api private
680
+ #
681
+
682
+ def selector_string
683
+ return @selector.inspect if @query_scope.is_a?(Browser)
684
+
685
+ "#{@query_scope.selector_string} --> #{@selector.inspect}"
686
+ end
687
+
688
+ protected
689
+
690
+ def wait_for_present
691
+ return true if present?
692
+
693
+ begin
694
+ @query_scope.wait_for_present unless @query_scope.is_a? Browser
695
+ wait_until(&:present?)
696
+ rescue Wait::TimeoutError
697
+ msg = "element located, but timed out after #{Watir.default_timeout} seconds, " \
698
+ "waiting for #{inspect} to be present"
699
+ raise unknown_exception, msg
700
+ end
701
+ end
702
+
703
+ def wait_for_enabled
704
+ wait_for_exists
705
+ return unless [Input, Button, Select, Option].any? { |c| is_a? c } || @content_editable
706
+ return if enabled?
707
+
708
+ begin
709
+ wait_until(&:enabled?)
710
+ rescue Wait::TimeoutError
711
+ raise_disabled
712
+ end
713
+ end
714
+
715
+ def wait_for_writable
716
+ wait_for_enabled
717
+
718
+ return if !respond_to?(:readonly?) || !readonly?
719
+
720
+ begin
721
+ wait_until { !respond_to?(:readonly?) || !readonly? }
722
+ rescue Wait::TimeoutError
723
+ raise_writable
724
+ end
725
+ end
726
+
727
+ # Locates if not previously found; does not check for staleness for performance reasons
728
+ def assert_exists
729
+ locate unless located?
730
+ return if located?
731
+
732
+ raise unknown_exception, "unable to locate element: #{inspect}"
733
+ end
734
+
735
+ def ensure_context
736
+ if @query_scope.is_a?(Browser) || (!@query_scope.located? && @query_scope.is_a?(IFrame))
737
+ @query_scope.browser.locate
738
+ elsif @query_scope.located? && @query_scope.stale?
739
+ @query_scope.locate
740
+ end
741
+ @query_scope.switch_to! if @query_scope.is_a?(IFrame)
742
+ end
743
+
744
+ def locate_in_context
745
+ @element = locator.locate(selector_builder.built)
746
+ end
747
+
748
+ private
749
+
750
+ def raise_writable
751
+ message = "element present and enabled, but timed out after #{Watir.default_timeout} seconds, " \
752
+ "waiting for #{inspect} to not be readonly"
753
+ raise ObjectReadOnlyException, message
754
+ end
755
+
756
+ def raise_disabled
757
+ message = "element present, but timed out after #{Watir.default_timeout} seconds, " \
758
+ "waiting for #{inspect} to be enabled"
759
+ raise ObjectDisabledException, message
760
+ end
761
+
762
+ def raise_present
763
+ message = "element located, but timed out after #{Watir.default_timeout} seconds, " \
764
+ "waiting for #{inspect} to be present"
765
+ raise unknown_exception, message
766
+ end
767
+
768
+ def element_class
769
+ self.class
770
+ end
771
+
772
+ def assert_enabled
773
+ raise ObjectDisabledException, "object is disabled #{inspect}" unless element_call { @element.enabled? }
774
+ end
775
+
776
+ def assert_is_element(obj)
777
+ raise TypeError, "expected Watir::Element, got #{obj.inspect}:#{obj.class}" unless obj.is_a? Element
778
+ end
779
+
780
+ def custom_message
781
+ msg = ''
782
+ msg += '; Maybe look in an iframe?' if @query_scope.iframe.exists?
783
+ custom_attributes = !defined?(@locator) || @locator.nil? ? [] : selector_builder.custom_attributes
784
+ unless custom_attributes.empty?
785
+ msg += "; Watir treated #{custom_attributes} as a non-HTML compliant attribute, ensure that was intended"
786
+ end
787
+ msg
788
+ end
789
+
790
+ def method_missing(meth, *args, &blk)
791
+ method = meth.to_s
792
+ if Locators::Element::SelectorBuilder::WILDCARD_ATTRIBUTE.match?(method)
793
+ attribute_value(meth, *args)
794
+ elsif UserEditable.instance_methods(false).include?(meth) && content_editable?
795
+ @content_editable = true
796
+ extend UserEditable
797
+ send(meth, *args, &blk)
798
+ else
799
+ super
800
+ end
801
+ end
802
+
803
+ def respond_to_missing?(meth, *)
804
+ meth.to_s =~ Locators::Element::SelectorBuilder::WILDCARD_ATTRIBUTE || super
805
+ end
806
+ end # Element
807
+ end # Watir