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.
- checksums.yaml +7 -0
- data/.document +4 -0
- data/.github/ISSUE_TEMPLATE.md +16 -0
- data/.github/workflows/chrome.yml +55 -0
- data/.github/workflows/edge.yml +44 -0
- data/.github/workflows/firefox.yml +55 -0
- data/.github/workflows/ie.yml +30 -0
- data/.github/workflows/safari.yml +38 -0
- data/.github/workflows/unit.yml +60 -0
- data/.gitignore +21 -0
- data/.rubocop.yml +114 -0
- data/.rubocop_todo.yml +17 -0
- data/CHANGES.md +2212 -0
- data/Gemfile +15 -0
- data/LICENSE +24 -0
- data/README.md +113 -0
- data/Rakefile +173 -0
- data/lib/watir/adjacent.rb +128 -0
- data/lib/watir/after_hooks.rb +135 -0
- data/lib/watir/alert.rb +113 -0
- data/lib/watir/aliases.rb +8 -0
- data/lib/watir/attribute_helper.rb +97 -0
- data/lib/watir/browser.rb +323 -0
- data/lib/watir/capabilities.rb +179 -0
- data/lib/watir/cell_container.rb +25 -0
- data/lib/watir/container.rb +33 -0
- data/lib/watir/cookies.rb +130 -0
- data/lib/watir/element_collection.rb +223 -0
- data/lib/watir/elements/button.rb +28 -0
- data/lib/watir/elements/cell.rb +18 -0
- data/lib/watir/elements/checkbox.rb +56 -0
- data/lib/watir/elements/date_field.rb +42 -0
- data/lib/watir/elements/date_time_field.rb +42 -0
- data/lib/watir/elements/dlist.rb +12 -0
- data/lib/watir/elements/element.rb +807 -0
- data/lib/watir/elements/file_field.rb +43 -0
- data/lib/watir/elements/font.rb +26 -0
- data/lib/watir/elements/form.rb +16 -0
- data/lib/watir/elements/hidden.rb +26 -0
- data/lib/watir/elements/html_elements.rb +1981 -0
- data/lib/watir/elements/iframe.rb +156 -0
- data/lib/watir/elements/image.rb +22 -0
- data/lib/watir/elements/input.rb +15 -0
- data/lib/watir/elements/link.rb +8 -0
- data/lib/watir/elements/list.rb +51 -0
- data/lib/watir/elements/option.rb +60 -0
- data/lib/watir/elements/radio.rb +65 -0
- data/lib/watir/elements/row.rb +18 -0
- data/lib/watir/elements/select.rb +214 -0
- data/lib/watir/elements/svg_elements.rb +497 -0
- data/lib/watir/elements/table.rb +77 -0
- data/lib/watir/elements/table_cell.rb +32 -0
- data/lib/watir/elements/table_row.rb +34 -0
- data/lib/watir/elements/table_section.rb +17 -0
- data/lib/watir/elements/text_area.rb +7 -0
- data/lib/watir/elements/text_field.rb +39 -0
- data/lib/watir/exception.rb +16 -0
- data/lib/watir/extensions/nokogiri.rb +14 -0
- data/lib/watir/generator/base/generator.rb +114 -0
- data/lib/watir/generator/base/idl_sorter.rb +51 -0
- data/lib/watir/generator/base/spec_extractor.rb +158 -0
- data/lib/watir/generator/base/util.rb +21 -0
- data/lib/watir/generator/base/visitor.rb +133 -0
- data/lib/watir/generator/base.rb +12 -0
- data/lib/watir/generator/html/generator.rb +36 -0
- data/lib/watir/generator/html/spec_extractor.rb +52 -0
- data/lib/watir/generator/html/visitor.rb +23 -0
- data/lib/watir/generator/html.rb +17 -0
- data/lib/watir/generator/svg/generator.rb +38 -0
- data/lib/watir/generator/svg/spec_extractor.rb +55 -0
- data/lib/watir/generator/svg/visitor.rb +23 -0
- data/lib/watir/generator/svg.rb +9 -0
- data/lib/watir/generator.rb +5 -0
- data/lib/watir/has_window.rb +72 -0
- data/lib/watir/http_client.rb +11 -0
- data/lib/watir/js_execution.rb +165 -0
- data/lib/watir/js_snippets/attributeValues.js +11 -0
- data/lib/watir/js_snippets/backgroundColor.js +7 -0
- data/lib/watir/js_snippets/elementObscured.js +14 -0
- data/lib/watir/js_snippets/fireEvent.js +31 -0
- data/lib/watir/js_snippets/focus.js +3 -0
- data/lib/watir/js_snippets/getElementTags.js +3 -0
- data/lib/watir/js_snippets/getInnerHtml.js +19 -0
- data/lib/watir/js_snippets/getInnerText.js +19 -0
- data/lib/watir/js_snippets/getOuterHtml.js +20 -0
- data/lib/watir/js_snippets/getTextContent.js +19 -0
- data/lib/watir/js_snippets/isElementInViewport.js +20 -0
- data/lib/watir/js_snippets/isImageLoaded.js +3 -0
- data/lib/watir/js_snippets/selectOptionsLabel.js +10 -0
- data/lib/watir/js_snippets/selectOptionsText.js +10 -0
- data/lib/watir/js_snippets/selectOptionsValue.js +10 -0
- data/lib/watir/js_snippets/selectText.js +64 -0
- data/lib/watir/js_snippets/selectedOptions.js +11 -0
- data/lib/watir/js_snippets/selectedText.js +17 -0
- data/lib/watir/js_snippets/setText.js +3 -0
- data/lib/watir/js_snippets/setValue.js +3 -0
- data/lib/watir/js_snippets.rb +18 -0
- data/lib/watir/locators/anchor/selector_builder.rb +43 -0
- data/lib/watir/locators/button/matcher.rb +19 -0
- data/lib/watir/locators/button/selector_builder/xpath.rb +69 -0
- data/lib/watir/locators/button/selector_builder.rb +10 -0
- data/lib/watir/locators/cell/selector_builder/xpath.rb +23 -0
- data/lib/watir/locators/cell/selector_builder.rb +13 -0
- data/lib/watir/locators/element/locator.rb +81 -0
- data/lib/watir/locators/element/matcher.rb +118 -0
- data/lib/watir/locators/element/selector_builder/regexp_disassembler.rb +69 -0
- data/lib/watir/locators/element/selector_builder/xpath.rb +268 -0
- data/lib/watir/locators/element/selector_builder/xpath_support.rb +29 -0
- data/lib/watir/locators/element/selector_builder.rb +164 -0
- data/lib/watir/locators/option/matcher.rb +26 -0
- data/lib/watir/locators/option/selector_builder/xpath.rb +39 -0
- data/lib/watir/locators/option/selector_builder.rb +10 -0
- data/lib/watir/locators/row/selector_builder/xpath.rb +53 -0
- data/lib/watir/locators/row/selector_builder.rb +18 -0
- data/lib/watir/locators/text_area/selector_builder/xpath.rb +21 -0
- data/lib/watir/locators/text_area/selector_builder.rb +10 -0
- data/lib/watir/locators/text_field/matcher.rb +37 -0
- data/lib/watir/locators/text_field/selector_builder/xpath.rb +50 -0
- data/lib/watir/locators/text_field/selector_builder.rb +10 -0
- data/lib/watir/locators.rb +77 -0
- data/lib/watir/logger.rb +30 -0
- data/lib/watir/navigation.rb +51 -0
- data/lib/watir/radio_set.rb +230 -0
- data/lib/watir/row_container.rb +36 -0
- data/lib/watir/screenshot.rb +51 -0
- data/lib/watir/scroll.rb +95 -0
- data/lib/watir/search_context.rb +96 -0
- data/lib/watir/shadow_root.rb +60 -0
- data/lib/watir/user_editable.rb +85 -0
- data/lib/watir/version.rb +5 -0
- data/lib/watir/wait/timer.rb +52 -0
- data/lib/watir/wait.rb +171 -0
- data/lib/watir/window.rb +276 -0
- data/lib/watir/window_collection.rb +82 -0
- data/lib/watir.rb +108 -0
- data/lib/watirspec/guards.rb +65 -0
- data/lib/watirspec/implementation.rb +56 -0
- data/lib/watirspec/rake_tasks.rb +118 -0
- data/lib/watirspec/remote_server.rb +39 -0
- data/lib/watirspec/runner.rb +64 -0
- data/lib/watirspec/server/app.rb +86 -0
- data/lib/watirspec/server.rb +104 -0
- data/lib/watirspec.rb +93 -0
- data/spec/locator_spec_helper.rb +88 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/unit/capabilities_spec.rb +670 -0
- data/spec/unit/element_locator_spec.rb +97 -0
- data/spec/unit/match_elements/button_spec.rb +76 -0
- data/spec/unit/match_elements/element_spec.rb +424 -0
- data/spec/unit/match_elements/text_field_spec.rb +84 -0
- data/spec/unit/selector_builder/anchor_spec.rb +59 -0
- data/spec/unit/selector_builder/button_spec.rb +217 -0
- data/spec/unit/selector_builder/cell_spec.rb +71 -0
- data/spec/unit/selector_builder/element_spec.rb +804 -0
- data/spec/unit/selector_builder/row_spec.rb +128 -0
- data/spec/unit/selector_builder/text_field_spec.rb +203 -0
- data/spec/unit/selector_builder/textarea_spec.rb +35 -0
- data/spec/unit/unit_helper.rb +4 -0
- data/spec/unit/wait_spec.rb +99 -0
- data/spec/watirspec/adjacent_spec.rb +256 -0
- data/spec/watirspec/after_hooks_spec.rb +204 -0
- data/spec/watirspec/alert_spec.rb +89 -0
- data/spec/watirspec/browser_spec.rb +536 -0
- data/spec/watirspec/capabilities_spec.rb +556 -0
- data/spec/watirspec/cookies_spec.rb +196 -0
- data/spec/watirspec/drag_and_drop_spec.rb +38 -0
- data/spec/watirspec/element_hidden_spec.rb +86 -0
- data/spec/watirspec/elements/area_spec.rb +69 -0
- data/spec/watirspec/elements/areas_spec.rb +44 -0
- data/spec/watirspec/elements/button_spec.rb +265 -0
- data/spec/watirspec/elements/buttons_spec.rb +57 -0
- data/spec/watirspec/elements/checkbox_spec.rb +290 -0
- data/spec/watirspec/elements/checkboxes_spec.rb +46 -0
- data/spec/watirspec/elements/collections_spec.rb +132 -0
- data/spec/watirspec/elements/date_field_spec.rb +209 -0
- data/spec/watirspec/elements/date_fields_spec.rb +46 -0
- data/spec/watirspec/elements/date_time_field_spec.rb +223 -0
- data/spec/watirspec/elements/date_time_fields_spec.rb +47 -0
- data/spec/watirspec/elements/dd_spec.rb +108 -0
- data/spec/watirspec/elements/dds_spec.rb +44 -0
- data/spec/watirspec/elements/del_spec.rb +113 -0
- data/spec/watirspec/elements/dels_spec.rb +42 -0
- data/spec/watirspec/elements/div_spec.rb +232 -0
- data/spec/watirspec/elements/divs_spec.rb +56 -0
- data/spec/watirspec/elements/dl_spec.rb +117 -0
- data/spec/watirspec/elements/dls_spec.rb +45 -0
- data/spec/watirspec/elements/dt_spec.rb +107 -0
- data/spec/watirspec/elements/dts_spec.rb +44 -0
- data/spec/watirspec/elements/element_spec.rb +1069 -0
- data/spec/watirspec/elements/elements_spec.rb +60 -0
- data/spec/watirspec/elements/em_spec.rb +85 -0
- data/spec/watirspec/elements/ems_spec.rb +45 -0
- data/spec/watirspec/elements/filefield_spec.rb +135 -0
- data/spec/watirspec/elements/filefields_spec.rb +45 -0
- data/spec/watirspec/elements/font_spec.rb +31 -0
- data/spec/watirspec/elements/form_spec.rb +70 -0
- data/spec/watirspec/elements/forms_spec.rb +46 -0
- data/spec/watirspec/elements/frame_spec.rb +117 -0
- data/spec/watirspec/elements/frames_spec.rb +43 -0
- data/spec/watirspec/elements/hidden_spec.rb +106 -0
- data/spec/watirspec/elements/hiddens_spec.rb +45 -0
- data/spec/watirspec/elements/hn_spec.rb +80 -0
- data/spec/watirspec/elements/hns_spec.rb +42 -0
- data/spec/watirspec/elements/iframe_spec.rb +244 -0
- data/spec/watirspec/elements/iframes_spec.rb +49 -0
- data/spec/watirspec/elements/image_spec.rb +160 -0
- data/spec/watirspec/elements/images_spec.rb +42 -0
- data/spec/watirspec/elements/input_spec.rb +17 -0
- data/spec/watirspec/elements/ins_spec.rb +113 -0
- data/spec/watirspec/elements/inses_spec.rb +42 -0
- data/spec/watirspec/elements/label_spec.rb +77 -0
- data/spec/watirspec/elements/labels_spec.rb +42 -0
- data/spec/watirspec/elements/li_spec.rb +99 -0
- data/spec/watirspec/elements/link_spec.rb +180 -0
- data/spec/watirspec/elements/links_spec.rb +66 -0
- data/spec/watirspec/elements/lis_spec.rb +44 -0
- data/spec/watirspec/elements/list_spec.rb +50 -0
- data/spec/watirspec/elements/map_spec.rb +78 -0
- data/spec/watirspec/elements/maps_spec.rb +43 -0
- data/spec/watirspec/elements/meta_spec.rb +27 -0
- data/spec/watirspec/elements/metas_spec.rb +42 -0
- data/spec/watirspec/elements/ol_spec.rb +63 -0
- data/spec/watirspec/elements/ols_spec.rb +42 -0
- data/spec/watirspec/elements/option_spec.rb +113 -0
- data/spec/watirspec/elements/p_spec.rb +102 -0
- data/spec/watirspec/elements/pre_spec.rb +100 -0
- data/spec/watirspec/elements/pres_spec.rb +42 -0
- data/spec/watirspec/elements/ps_spec.rb +42 -0
- data/spec/watirspec/elements/radio_spec.rb +259 -0
- data/spec/watirspec/elements/radios_spec.rb +45 -0
- data/spec/watirspec/elements/select_list_spec.rb +701 -0
- data/spec/watirspec/elements/select_lists_spec.rb +49 -0
- data/spec/watirspec/elements/span_spec.rb +119 -0
- data/spec/watirspec/elements/spans_spec.rb +42 -0
- data/spec/watirspec/elements/strong_spec.rb +78 -0
- data/spec/watirspec/elements/strongs_spec.rb +45 -0
- data/spec/watirspec/elements/table_spec.rb +210 -0
- data/spec/watirspec/elements/tables_spec.rb +44 -0
- data/spec/watirspec/elements/tbody_spec.rb +94 -0
- data/spec/watirspec/elements/tbodys_spec.rb +64 -0
- data/spec/watirspec/elements/td_spec.rb +92 -0
- data/spec/watirspec/elements/tds_spec.rb +55 -0
- data/spec/watirspec/elements/text_field_spec.rb +223 -0
- data/spec/watirspec/elements/text_fields_spec.rb +47 -0
- data/spec/watirspec/elements/textarea_spec.rb +30 -0
- data/spec/watirspec/elements/textareas_spec.rb +28 -0
- data/spec/watirspec/elements/tfoot_spec.rb +89 -0
- data/spec/watirspec/elements/tfoots_spec.rb +72 -0
- data/spec/watirspec/elements/thead_spec.rb +88 -0
- data/spec/watirspec/elements/theads_spec.rb +72 -0
- data/spec/watirspec/elements/tr_spec.rb +69 -0
- data/spec/watirspec/elements/trs_spec.rb +63 -0
- data/spec/watirspec/elements/ul_spec.rb +63 -0
- data/spec/watirspec/elements/uls_spec.rb +42 -0
- data/spec/watirspec/html/alerts.html +12 -0
- data/spec/watirspec/html/aria_attributes.html +9 -0
- data/spec/watirspec/html/child_frame.html +29 -0
- data/spec/watirspec/html/class_locator.html +11 -0
- data/spec/watirspec/html/clicks.html +19 -0
- data/spec/watirspec/html/closeable.html +21 -0
- data/spec/watirspec/html/collections.html +15 -0
- data/spec/watirspec/html/css/jquery-ui-1.8.17.custom.css +287 -0
- data/spec/watirspec/html/data_attributes.html +10 -0
- data/spec/watirspec/html/definition_lists.html +48 -0
- data/spec/watirspec/html/drag_and_drop.html +106 -0
- data/spec/watirspec/html/font.html +10 -0
- data/spec/watirspec/html/forms_with_input_elements.html +194 -0
- data/spec/watirspec/html/frame_1.html +22 -0
- data/spec/watirspec/html/frame_2.html +16 -0
- data/spec/watirspec/html/frames.html +11 -0
- data/spec/watirspec/html/iframe_1.html +22 -0
- data/spec/watirspec/html/iframes.html +15 -0
- data/spec/watirspec/html/images/button.png +0 -0
- data/spec/watirspec/html/images/circle.png +0 -0
- data/spec/watirspec/html/images/map.gif +0 -0
- data/spec/watirspec/html/images/map2.gif +0 -0
- data/spec/watirspec/html/images/originaltriangle.png +0 -0
- data/spec/watirspec/html/images/square.png +0 -0
- data/spec/watirspec/html/images/triangle.png +0 -0
- data/spec/watirspec/html/images.html +28 -0
- data/spec/watirspec/html/inner_outer.html +5 -0
- data/spec/watirspec/html/javascript/angular.min.js +332 -0
- data/spec/watirspec/html/javascript/helpers.js +16 -0
- data/spec/watirspec/html/javascript/jquery-1.7.1.min.js +4 -0
- data/spec/watirspec/html/javascript/jquery-ui-1.8.17.custom.min.js +68 -0
- data/spec/watirspec/html/keylogger.html +15 -0
- data/spec/watirspec/html/modal_dialog.html +9 -0
- data/spec/watirspec/html/multiple_ids.html +15 -0
- data/spec/watirspec/html/nested_elements.html +44 -0
- data/spec/watirspec/html/nested_frame_1.html +1 -0
- data/spec/watirspec/html/nested_frame_2.html +9 -0
- data/spec/watirspec/html/nested_frame_3.html +14 -0
- data/spec/watirspec/html/nested_frames.html +10 -0
- data/spec/watirspec/html/nested_iframe_2.html +12 -0
- data/spec/watirspec/html/nested_iframes.html +13 -0
- data/spec/watirspec/html/nested_tables.html +203 -0
- data/spec/watirspec/html/non_control_elements.html +145 -0
- data/spec/watirspec/html/obscured.html +36 -0
- data/spec/watirspec/html/removed_element.html +24 -0
- data/spec/watirspec/html/right_click.html +23 -0
- data/spec/watirspec/html/scroll.html +15 -0
- data/spec/watirspec/html/scroll_nested.html +17 -0
- data/spec/watirspec/html/scroll_nested_offscreen.html +18 -0
- data/spec/watirspec/html/shadow_dom.html +28 -0
- data/spec/watirspec/html/special_chars.html +15 -0
- data/spec/watirspec/html/sticky_elements.html +10 -0
- data/spec/watirspec/html/tables.html +121 -0
- data/spec/watirspec/html/timeout_window_location.html +19 -0
- data/spec/watirspec/html/uneven_table.html +20 -0
- data/spec/watirspec/html/wait.html +99 -0
- data/spec/watirspec/html/watirspec.css +0 -0
- data/spec/watirspec/html/window_switching.html +22 -0
- data/spec/watirspec/radio_set_spec.rb +346 -0
- data/spec/watirspec/screenshot_spec.rb +33 -0
- data/spec/watirspec/scroll_spec.rb +208 -0
- data/spec/watirspec/shadow_root_spec.rb +108 -0
- data/spec/watirspec/support/rspec_matchers.rb +161 -0
- data/spec/watirspec/user_editable_spec.rb +207 -0
- data/spec/watirspec/wait_spec.rb +345 -0
- data/spec/watirspec/window_switching_spec.rb +580 -0
- data/spec/watirspec_helper.rb +163 -0
- data/support/doctest_helper.rb +101 -0
- data/support/version_differ.rb +60 -0
- data/watir.gemspec +50 -0
- metadata +652 -148
- data/readme.rb +0 -211
- data/unittests/WindowLogonExample.rb +0 -30
- data/unittests/WindowLogonExtra.rb +0 -7
- data/unittests/all_tests.rb +0 -10
- data/unittests/all_tests_concurrent.rb +0 -57
- data/unittests/attachToExistingWindow_test.rb +0 -40
- data/unittests/buttons_test.rb +0 -131
- data/unittests/checkbox_test.rb +0 -149
- data/unittests/core_tests.rb +0 -9
- data/unittests/css_test.rb +0 -60
- data/unittests/div_test.rb +0 -179
- data/unittests/errorchecker_test.rb +0 -29
- data/unittests/filefield_test.rb +0 -35
- data/unittests/form_test.rb +0 -279
- data/unittests/frame_test.rb +0 -141
- data/unittests/html/blankpage.html +0 -12
- data/unittests/html/buttons1.html +0 -40
- data/unittests/html/checkboxes1.html +0 -69
- data/unittests/html/complex_table.html +0 -36
- data/unittests/html/cssTest.html +0 -42
- data/unittests/html/div.html +0 -105
- data/unittests/html/fileupload.html +0 -45
- data/unittests/html/formTest1.html +0 -39
- data/unittests/html/forms2.html +0 -45
- data/unittests/html/forms3.html +0 -132
- data/unittests/html/forms4.html +0 -27
- data/unittests/html/frame_buttons.html +0 -4
- data/unittests/html/frame_links.html +0 -4
- data/unittests/html/frame_multi.html +0 -5
- data/unittests/html/iframeTest.html +0 -13
- data/unittests/html/iframeTest1.html +0 -7
- data/unittests/html/iframeTest2.html +0 -6
- data/unittests/html/images/button.jpg +0 -0
- data/unittests/html/images/circle.jpg +0 -0
- data/unittests/html/images/originaltriangle.jpg +0 -0
- data/unittests/html/images/square.jpg +0 -0
- data/unittests/html/images/triangle.jpg +0 -0
- data/unittests/html/images1.html +0 -52
- data/unittests/html/javascriptevents.html +0 -39
- data/unittests/html/link_pass.html +0 -11
- data/unittests/html/links1.html +0 -37
- data/unittests/html/links2.html +0 -11
- data/unittests/html/nestedFrames.html +0 -6
- data/unittests/html/pass.html +0 -10
- data/unittests/html/popups1.html +0 -60
- data/unittests/html/radioButtons1.html +0 -71
- data/unittests/html/select_tealeaf.html +0 -54
- data/unittests/html/selectboxes1.html +0 -55
- data/unittests/html/simple_table.html +0 -26
- data/unittests/html/simple_table_buttons.html +0 -104
- data/unittests/html/simple_table_columns.html +0 -76
- data/unittests/html/table1.html +0 -142
- data/unittests/html/textarea.html +0 -30
- data/unittests/html/textfields1.html +0 -87
- data/unittests/html/textsearch.html +0 -44
- data/unittests/ie_mock.rb +0 -93
- data/unittests/ie_test.rb +0 -50
- data/unittests/images_test.rb +0 -179
- data/unittests/iostring.rb +0 -30
- data/unittests/iostring_test.rb +0 -48
- data/unittests/js_events_test.rb +0 -77
- data/unittests/jscriptExtraAlert.rb +0 -6
- data/unittests/jscriptExtraConfirmCancel.rb +0 -7
- data/unittests/jscriptExtraConfirmOk.rb +0 -7
- data/unittests/jscriptPushButton.rb +0 -5
- data/unittests/jscript_test.rb +0 -57
- data/unittests/links_test.rb +0 -169
- data/unittests/minmax_test.rb +0 -31
- data/unittests/navigate_test.rb +0 -56
- data/unittests/non_core_tests.rb +0 -9
- data/unittests/pagecontainstext_test.rb +0 -49
- data/unittests/popups_test.rb +0 -44
- data/unittests/radios_test.rb +0 -164
- data/unittests/screen_capture_test.rb +0 -53
- data/unittests/selectbox_test.rb +0 -197
- data/unittests/send_keys_test.rb +0 -29
- data/unittests/setup.rb +0 -47
- data/unittests/table_test.rb +0 -306
- data/unittests/textAreafields_test.rb +0 -81
- data/unittests/textfields_test.rb +0 -239
- data/watir/AutoItX3.dll +0 -0
- data/watir/WindowHelper.rb +0 -47
- data/watir/camel_case.rb +0 -37
- data/watir/clickJSDialog.rb +0 -19
- data/watir/cookiemanager.rb +0 -53
- data/watir/exceptions.rb +0 -60
- data/watir/screen_capture.rb +0 -115
- data/watir/setFileDialog.rb +0 -16
- data/watir/testUnitAddons.rb +0 -47
- data/watir/watir_simple.rb +0 -475
- data/watir/winClicker.rb +0 -505
- data/watir.rb +0 -3744
- /data/{unittests → spec/watirspec}/html/images/1.gif +0 -0
- /data/{unittests/html/images/2.GIF → spec/watirspec/html/images/2.gif} +0 -0
- /data/{unittests/html/images/3.GIF → spec/watirspec/html/images/3.gif} +0 -0
- /data/{unittests/html/images/minus.GIF → spec/watirspec/html/images/minus.gif} +0 -0
- /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
|