capybara 3.13.2 → 3.40.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 +4 -4
- data/.yardopts +1 -0
- data/History.md +587 -16
- data/README.md +240 -90
- data/lib/capybara/config.rb +24 -11
- data/lib/capybara/cucumber.rb +1 -1
- data/lib/capybara/driver/base.rb +8 -0
- data/lib/capybara/driver/node.rb +20 -4
- data/lib/capybara/dsl.rb +5 -3
- data/lib/capybara/helpers.rb +25 -4
- data/lib/capybara/minitest/spec.rb +174 -90
- data/lib/capybara/minitest.rb +256 -142
- data/lib/capybara/node/actions.rb +123 -77
- data/lib/capybara/node/base.rb +20 -12
- data/lib/capybara/node/document.rb +2 -2
- data/lib/capybara/node/document_matchers.rb +3 -3
- data/lib/capybara/node/element.rb +223 -117
- data/lib/capybara/node/finders.rb +81 -71
- data/lib/capybara/node/matchers.rb +271 -134
- data/lib/capybara/node/simple.rb +18 -5
- data/lib/capybara/node/whitespace_normalizer.rb +81 -0
- data/lib/capybara/queries/active_element_query.rb +18 -0
- data/lib/capybara/queries/ancestor_query.rb +8 -9
- data/lib/capybara/queries/base_query.rb +3 -2
- data/lib/capybara/queries/current_path_query.rb +15 -5
- data/lib/capybara/queries/selector_query.rb +364 -54
- data/lib/capybara/queries/sibling_query.rb +8 -6
- data/lib/capybara/queries/style_query.rb +2 -2
- data/lib/capybara/queries/text_query.rb +13 -1
- data/lib/capybara/queries/title_query.rb +1 -1
- data/lib/capybara/rack_test/browser.rb +76 -11
- data/lib/capybara/rack_test/driver.rb +10 -5
- data/lib/capybara/rack_test/errors.rb +6 -0
- data/lib/capybara/rack_test/form.rb +31 -9
- data/lib/capybara/rack_test/node.rb +74 -23
- data/lib/capybara/registration_container.rb +41 -0
- data/lib/capybara/registrations/drivers.rb +42 -0
- data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
- data/lib/capybara/registrations/servers.rb +66 -0
- data/lib/capybara/result.rb +44 -20
- data/lib/capybara/rspec/matcher_proxies.rb +13 -11
- data/lib/capybara/rspec/matchers/base.rb +31 -16
- data/lib/capybara/rspec/matchers/compound.rb +1 -1
- data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
- data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
- data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
- data/lib/capybara/rspec/matchers/have_selector.rb +21 -21
- data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
- data/lib/capybara/rspec/matchers/have_text.rb +4 -4
- data/lib/capybara/rspec/matchers/have_title.rb +2 -2
- data/lib/capybara/rspec/matchers/match_selector.rb +3 -3
- data/lib/capybara/rspec/matchers/match_style.rb +7 -2
- data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
- data/lib/capybara/rspec/matchers.rb +111 -68
- data/lib/capybara/rspec.rb +2 -0
- data/lib/capybara/selector/builders/css_builder.rb +11 -7
- data/lib/capybara/selector/builders/xpath_builder.rb +5 -3
- data/lib/capybara/selector/css.rb +11 -9
- data/lib/capybara/selector/definition/button.rb +68 -0
- data/lib/capybara/selector/definition/checkbox.rb +26 -0
- data/lib/capybara/selector/definition/css.rb +10 -0
- data/lib/capybara/selector/definition/datalist_input.rb +35 -0
- data/lib/capybara/selector/definition/datalist_option.rb +25 -0
- data/lib/capybara/selector/definition/element.rb +28 -0
- data/lib/capybara/selector/definition/field.rb +40 -0
- data/lib/capybara/selector/definition/fieldset.rb +14 -0
- data/lib/capybara/selector/definition/file_field.rb +13 -0
- data/lib/capybara/selector/definition/fillable_field.rb +33 -0
- data/lib/capybara/selector/definition/frame.rb +17 -0
- data/lib/capybara/selector/definition/id.rb +6 -0
- data/lib/capybara/selector/definition/label.rb +62 -0
- data/lib/capybara/selector/definition/link.rb +55 -0
- data/lib/capybara/selector/definition/link_or_button.rb +16 -0
- data/lib/capybara/selector/definition/option.rb +27 -0
- data/lib/capybara/selector/definition/radio_button.rb +27 -0
- data/lib/capybara/selector/definition/select.rb +81 -0
- data/lib/capybara/selector/definition/table.rb +109 -0
- data/lib/capybara/selector/definition/table_row.rb +21 -0
- data/lib/capybara/selector/definition/xpath.rb +5 -0
- data/lib/capybara/selector/definition.rb +280 -0
- data/lib/capybara/selector/filter_set.rb +19 -18
- data/lib/capybara/selector/filters/base.rb +11 -2
- data/lib/capybara/selector/filters/locator_filter.rb +13 -3
- data/lib/capybara/selector/regexp_disassembler.rb +11 -7
- data/lib/capybara/selector/selector.rb +50 -440
- data/lib/capybara/selector/xpath_extensions.rb +17 -0
- data/lib/capybara/selector.rb +473 -482
- data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
- data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
- data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
- data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
- data/lib/capybara/selenium/driver.rb +174 -62
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +74 -18
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +128 -0
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +37 -3
- data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +14 -1
- data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
- data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
- data/lib/capybara/selenium/extensions/find.rb +68 -45
- data/lib/capybara/selenium/extensions/html5_drag.rb +192 -22
- data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
- data/lib/capybara/selenium/extensions/scroll.rb +8 -10
- data/lib/capybara/selenium/node.rb +268 -72
- data/lib/capybara/selenium/nodes/chrome_node.rb +105 -9
- data/lib/capybara/selenium/nodes/edge_node.rb +110 -0
- data/lib/capybara/selenium/nodes/firefox_node.rb +51 -61
- data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
- data/lib/capybara/selenium/nodes/safari_node.rb +118 -0
- data/lib/capybara/selenium/patches/atoms.rb +18 -0
- data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
- data/lib/capybara/selenium/patches/logs.rb +45 -0
- data/lib/capybara/selenium/patches/pause_duration_fix.rb +1 -1
- data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
- data/lib/capybara/server/animation_disabler.rb +43 -21
- data/lib/capybara/server/checker.rb +6 -2
- data/lib/capybara/server/middleware.rb +25 -13
- data/lib/capybara/server.rb +20 -4
- data/lib/capybara/session/config.rb +15 -11
- data/lib/capybara/session/matchers.rb +11 -11
- data/lib/capybara/session.rb +162 -131
- data/lib/capybara/spec/public/offset.js +6 -0
- data/lib/capybara/spec/public/test.js +105 -6
- data/lib/capybara/spec/session/accept_alert_spec.rb +1 -1
- data/lib/capybara/spec/session/active_element_spec.rb +31 -0
- data/lib/capybara/spec/session/all_spec.rb +89 -15
- data/lib/capybara/spec/session/ancestor_spec.rb +5 -0
- data/lib/capybara/spec/session/assert_current_path_spec.rb +5 -2
- data/lib/capybara/spec/session/assert_text_spec.rb +26 -22
- data/lib/capybara/spec/session/attach_file_spec.rb +64 -31
- data/lib/capybara/spec/session/check_spec.rb +26 -4
- data/lib/capybara/spec/session/choose_spec.rb +14 -2
- data/lib/capybara/spec/session/click_button_spec.rb +109 -61
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +9 -0
- data/lib/capybara/spec/session/click_link_spec.rb +23 -1
- data/lib/capybara/spec/session/current_scope_spec.rb +1 -1
- data/lib/capybara/spec/session/current_url_spec.rb +11 -1
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +40 -39
- data/lib/capybara/spec/session/evaluate_script_spec.rb +12 -0
- data/lib/capybara/spec/session/fill_in_spec.rb +46 -5
- data/lib/capybara/spec/session/find_link_spec.rb +10 -0
- data/lib/capybara/spec/session/find_spec.rb +80 -7
- data/lib/capybara/spec/session/first_spec.rb +2 -2
- data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +14 -1
- data/lib/capybara/spec/session/frame/within_frame_spec.rb +14 -1
- data/lib/capybara/spec/session/has_all_selectors_spec.rb +5 -5
- data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
- data/lib/capybara/spec/session/has_any_selectors_spec.rb +6 -2
- data/lib/capybara/spec/session/has_button_spec.rb +81 -0
- data/lib/capybara/spec/session/has_css_spec.rb +45 -8
- data/lib/capybara/spec/session/has_current_path_spec.rb +22 -7
- data/lib/capybara/spec/session/has_element_spec.rb +47 -0
- data/lib/capybara/spec/session/has_field_spec.rb +59 -1
- data/lib/capybara/spec/session/has_link_spec.rb +40 -0
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +7 -7
- data/lib/capybara/spec/session/has_select_spec.rb +42 -8
- data/lib/capybara/spec/session/has_selector_spec.rb +19 -4
- data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
- data/lib/capybara/spec/session/has_table_spec.rb +177 -0
- data/lib/capybara/spec/session/has_text_spec.rb +31 -3
- data/lib/capybara/spec/session/html_spec.rb +1 -1
- data/lib/capybara/spec/session/matches_style_spec.rb +6 -4
- data/lib/capybara/spec/session/node_spec.rb +697 -23
- data/lib/capybara/spec/session/node_wrapper_spec.rb +1 -1
- data/lib/capybara/spec/session/refresh_spec.rb +2 -1
- data/lib/capybara/spec/session/reset_session_spec.rb +21 -7
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
- data/lib/capybara/spec/session/save_page_spec.rb +4 -4
- data/lib/capybara/spec/session/save_screenshot_spec.rb +4 -4
- data/lib/capybara/spec/session/scroll_spec.rb +9 -7
- data/lib/capybara/spec/session/select_spec.rb +5 -10
- data/lib/capybara/spec/session/selectors_spec.rb +24 -3
- data/lib/capybara/spec/session/uncheck_spec.rb +3 -3
- data/lib/capybara/spec/session/unselect_spec.rb +1 -1
- data/lib/capybara/spec/session/visit_spec.rb +20 -0
- data/lib/capybara/spec/session/window/become_closed_spec.rb +20 -17
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +1 -1
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +1 -1
- data/lib/capybara/spec/session/window/window_spec.rb +54 -57
- data/lib/capybara/spec/session/window/windows_spec.rb +2 -2
- data/lib/capybara/spec/session/within_spec.rb +36 -0
- data/lib/capybara/spec/spec_helper.rb +30 -19
- data/lib/capybara/spec/test_app.rb +122 -34
- data/lib/capybara/spec/views/animated.erb +49 -0
- data/lib/capybara/spec/views/form.erb +86 -8
- data/lib/capybara/spec/views/frame_child.erb +3 -2
- data/lib/capybara/spec/views/frame_one.erb +2 -1
- data/lib/capybara/spec/views/frame_parent.erb +1 -1
- data/lib/capybara/spec/views/frame_two.erb +1 -1
- data/lib/capybara/spec/views/initial_alert.erb +2 -1
- data/lib/capybara/spec/views/layout.erb +10 -0
- data/lib/capybara/spec/views/obscured.erb +10 -10
- data/lib/capybara/spec/views/offset.erb +33 -0
- data/lib/capybara/spec/views/path.erb +2 -2
- data/lib/capybara/spec/views/popup_one.erb +1 -1
- data/lib/capybara/spec/views/popup_two.erb +1 -1
- data/lib/capybara/spec/views/react.erb +45 -0
- data/lib/capybara/spec/views/scroll.erb +2 -1
- data/lib/capybara/spec/views/spatial.erb +31 -0
- data/lib/capybara/spec/views/tables.erb +67 -0
- data/lib/capybara/spec/views/with_animation.erb +39 -4
- data/lib/capybara/spec/views/with_base_tag.erb +2 -2
- data/lib/capybara/spec/views/with_dragula.erb +24 -0
- data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
- data/lib/capybara/spec/views/with_hover.erb +3 -2
- data/lib/capybara/spec/views/with_hover1.erb +10 -0
- data/lib/capybara/spec/views/with_html.erb +34 -6
- data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
- data/lib/capybara/spec/views/with_js.erb +7 -4
- data/lib/capybara/spec/views/with_jstree.erb +26 -0
- data/lib/capybara/spec/views/with_namespace.erb +1 -0
- data/lib/capybara/spec/views/with_scope.erb +2 -2
- data/lib/capybara/spec/views/with_scope_other.erb +6 -0
- data/lib/capybara/spec/views/with_shadow.erb +31 -0
- data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
- data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
- data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
- data/lib/capybara/spec/views/with_windows.erb +1 -1
- data/lib/capybara/spec/views/within_frames.erb +1 -1
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara/window.rb +14 -18
- data/lib/capybara.rb +91 -126
- data/spec/basic_node_spec.rb +30 -16
- data/spec/capybara_spec.rb +40 -28
- data/spec/counter_spec.rb +35 -0
- data/spec/css_builder_spec.rb +3 -1
- data/spec/css_splitter_spec.rb +1 -1
- data/spec/dsl_spec.rb +33 -22
- data/spec/filter_set_spec.rb +5 -5
- data/spec/fixtures/selenium_driver_rspec_failure.rb +3 -3
- data/spec/fixtures/selenium_driver_rspec_success.rb +3 -3
- data/spec/minitest_spec.rb +24 -2
- data/spec/minitest_spec_spec.rb +60 -45
- data/spec/per_session_config_spec.rb +1 -1
- data/spec/rack_test_spec.rb +131 -98
- data/spec/regexp_dissassembler_spec.rb +53 -39
- data/spec/result_spec.rb +68 -66
- data/spec/rspec/features_spec.rb +9 -4
- data/spec/rspec/scenarios_spec.rb +6 -2
- data/spec/rspec/shared_spec_matchers.rb +137 -98
- data/spec/rspec_matchers_spec.rb +25 -0
- data/spec/rspec_spec.rb +23 -21
- data/spec/sauce_spec_chrome.rb +43 -0
- data/spec/selector_spec.rb +77 -21
- data/spec/selenium_spec_chrome.rb +141 -39
- data/spec/selenium_spec_chrome_remote.rb +32 -17
- data/spec/selenium_spec_edge.rb +36 -8
- data/spec/selenium_spec_firefox.rb +110 -68
- data/spec/selenium_spec_firefox_remote.rb +22 -15
- data/spec/selenium_spec_ie.rb +29 -22
- data/spec/selenium_spec_safari.rb +162 -0
- data/spec/server_spec.rb +153 -81
- data/spec/session_spec.rb +11 -4
- data/spec/shared_selenium_node.rb +79 -0
- data/spec/shared_selenium_session.rb +179 -74
- data/spec/spec_helper.rb +80 -5
- data/spec/whitespace_normalizer_spec.rb +54 -0
- data/spec/xpath_builder_spec.rb +3 -1
- metadata +218 -30
- data/lib/capybara/spec/session/source_spec.rb +0 -0
- data/lib/capybara/spec/views/with_title.erb +0 -5
@@ -0,0 +1,162 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'selenium-webdriver'
|
5
|
+
require 'shared_selenium_session'
|
6
|
+
require 'shared_selenium_node'
|
7
|
+
require 'rspec/shared_spec_matchers'
|
8
|
+
|
9
|
+
SAFARI_DRIVER = :selenium_safari
|
10
|
+
|
11
|
+
# if ::Selenium::WebDriver::Service.respond_to? :driver_path=
|
12
|
+
# ::Selenium::WebDriver::Safari::Service
|
13
|
+
# else
|
14
|
+
# ::Selenium::WebDriver::Safari
|
15
|
+
# end.driver_path = '/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver'
|
16
|
+
|
17
|
+
browser_options = Selenium::WebDriver::Safari::Options.new
|
18
|
+
# browser_options.headless! if ENV['HEADLESS']
|
19
|
+
|
20
|
+
Capybara.register_driver :selenium_safari do |app|
|
21
|
+
version = Capybara::Selenium::Driver.load_selenium
|
22
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
23
|
+
driver_options = { browser: :safari, timeout: 30 }.tap do |opts|
|
24
|
+
opts[options_key] = browser_options
|
25
|
+
end
|
26
|
+
|
27
|
+
Capybara::Selenium::Driver.new(app, **driver_options).tap do |driver|
|
28
|
+
# driver.browser.download_path = Capybara.save_path
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Capybara.register_driver :selenium_safari_not_clear_storage do |app|
|
33
|
+
version = Capybara::Selenium::Driver.load_selenium
|
34
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
35
|
+
driver_options = {
|
36
|
+
browser: :safari,
|
37
|
+
clear_local_storage: false,
|
38
|
+
clear_session_storage: false,
|
39
|
+
timeout: 30
|
40
|
+
}.tap do |opts|
|
41
|
+
opts[options_key] = browser_options
|
42
|
+
end
|
43
|
+
|
44
|
+
Capybara::Selenium::Driver.new(app, **driver_options)
|
45
|
+
end
|
46
|
+
|
47
|
+
module TestSessions
|
48
|
+
Safari = Capybara::Session.new(SAFARI_DRIVER, TestApp)
|
49
|
+
end
|
50
|
+
|
51
|
+
skipped_tests = %i[response_headers status_code trigger windows drag]
|
52
|
+
|
53
|
+
Capybara::SpecHelper.log_selenium_driver_version(Selenium::WebDriver::Safari) if ENV['CI']
|
54
|
+
|
55
|
+
Capybara::SpecHelper.run_specs TestSessions::Safari, SAFARI_DRIVER.to_s, capybara_skip: skipped_tests do |example|
|
56
|
+
case example.metadata[:full_description]
|
57
|
+
when /click_link can download a file/
|
58
|
+
skip "safaridriver doesn't provide a way to set the download directory"
|
59
|
+
when /Capybara::Session selenium_safari Capybara::Window#maximize/
|
60
|
+
pending "Safari headless doesn't support maximize" if ENV['HEADLESS']
|
61
|
+
when /Capybara::Session selenium_safari #visit without a server/,
|
62
|
+
/Capybara::Session selenium_safari #visit with Capybara.app_host set should override server/,
|
63
|
+
/Capybara::Session selenium_safari #reset_session! When reuse_server == false raises any standard errors caught inside the server during a second session/
|
64
|
+
skip "Safari webdriver doesn't support multiple sessions"
|
65
|
+
when /Capybara::Session selenium_safari #click_link with alternative text given to a contained image/,
|
66
|
+
'Capybara::Session selenium_safari #click_link_or_button with enable_aria_label should click on link'
|
67
|
+
pending 'safaridriver thinks these links are non-interactable for some unknown reason'
|
68
|
+
when /Capybara::Session selenium_safari #attach_file with a block can upload by clicking the file input/
|
69
|
+
skip "safaridriver doesn't allow clicking on file inputs"
|
70
|
+
when /Capybara::Session selenium_safari #within_frame works if the frame is closed/,
|
71
|
+
/Capybara::Session selenium_safari #switch_to_frame works if the frame is closed/
|
72
|
+
skip 'Safari has a race condition when clicking an element that causes the frame to close. It will sometimes raise a NoSuchFrameError'
|
73
|
+
when /Capybara::Session selenium_safari #reset_session! removes ALL cookies/
|
74
|
+
skip 'Safari webdriver can only remove cookies for the current domain'
|
75
|
+
when /Capybara::Session selenium_safari #refresh it reposts/
|
76
|
+
skip "Safari opens an alert that can't be closed"
|
77
|
+
when 'Capybara::Session selenium_safari node #double_click should allow to adjust the offset',
|
78
|
+
'Capybara::Session selenium_safari node #double_click should double click an element'
|
79
|
+
pending "safardriver doesn't generate a double click event"
|
80
|
+
when 'Capybara::Session selenium_safari node #double_click should allow modifiers'
|
81
|
+
pending "safaridriver doesn't generate double click with key modifiers"
|
82
|
+
when /when w3c_click_offset is true should offset/
|
83
|
+
pending 'w3c_click_offset is not currently supported with safaridriver'
|
84
|
+
when 'Capybara::Session selenium_safari #go_back should fetch a response from the driver from the previous page',
|
85
|
+
'Capybara::Session selenium_safari #go_forward should fetch a response from the driver from the previous page'
|
86
|
+
skip 'safaridriver loses the ability to find elements in the document after `go_back`'
|
87
|
+
when 'Capybara::Session selenium node #shadow_root should get the shadow root',
|
88
|
+
'Capybara::Session selenium node #shadow_root should find elements inside the shadow dom using CSS',
|
89
|
+
'Capybara::Session selenium node #shadow_root should find nested shadow roots'
|
90
|
+
pending "Safari doesn't yet have W3C shadow root support"
|
91
|
+
when /Capybara::Session selenium_chrome node #shadow_root should get visible text/
|
92
|
+
pending "Selenium doesn't currently support getting visible text for shadow root elements"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
RSpec.describe 'Capybara::Session with safari' do
|
97
|
+
include Capybara::SpecHelper
|
98
|
+
['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|
|
99
|
+
include_examples examples, TestSessions::Safari, SAFARI_DRIVER
|
100
|
+
end
|
101
|
+
|
102
|
+
context 'storage' do
|
103
|
+
describe '#reset!' do
|
104
|
+
it 'clears storage by default' do
|
105
|
+
session = TestSessions::Safari
|
106
|
+
session.visit('/with_js')
|
107
|
+
session.find(:css, '#set-storage').click
|
108
|
+
session.reset!
|
109
|
+
session.visit('/with_js')
|
110
|
+
expect(session.evaluate_script('Object.keys(localStorage)')).to be_empty
|
111
|
+
expect(session.evaluate_script('Object.keys(sessionStorage)')).to be_empty
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'does not clear storage when false' do
|
115
|
+
skip "Safari webdriver doesn't support multiple sessions"
|
116
|
+
session = Capybara::Session.new(:selenium_safari_not_clear_storage, TestApp)
|
117
|
+
session.visit('/with_js')
|
118
|
+
session.find(:css, '#set-storage').click
|
119
|
+
session.reset!
|
120
|
+
session.visit('/with_js')
|
121
|
+
expect(session.evaluate_script('Object.keys(localStorage)')).not_to be_empty
|
122
|
+
expect(session.evaluate_script('Object.keys(sessionStorage)')).not_to be_empty
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context 'timeout' do
|
128
|
+
it 'sets the http client read timeout' do
|
129
|
+
expect(TestSessions::Safari.driver.browser.send(:bridge).http.read_timeout).to eq 30
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe 'filling in Safari-specific date and time fields with keystrokes' do
|
134
|
+
let(:datetime) { Time.new(1983, 6, 19, 6, 30) }
|
135
|
+
let(:session) { TestSessions::Safari }
|
136
|
+
|
137
|
+
before do
|
138
|
+
session.visit('/form')
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'should fill in a date input with a String' do
|
142
|
+
session.fill_in('form_date', with: '06/19/1983')
|
143
|
+
session.click_button('awesome')
|
144
|
+
expect(Date.parse(extract_results(session)['date'])).to eq datetime.to_date
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'should fill in a time input with a String' do
|
148
|
+
# Safari doesn't support time inputs - so this is just a text input
|
149
|
+
session.fill_in('form_time', with: '06:30A')
|
150
|
+
session.click_button('awesome')
|
151
|
+
results = extract_results(session)['time']
|
152
|
+
expect(Time.parse(results).strftime('%r')).to eq datetime.strftime('%r')
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'should fill in a datetime input with a String' do
|
156
|
+
pending "Safari doesn't support datetime inputs"
|
157
|
+
session.fill_in('form_datetime', with: "06/19/1983\t06:30A")
|
158
|
+
session.click_button('awesome')
|
159
|
+
expect(Time.parse(extract_results(session)['datetime'])).to eq datetime
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
data/spec/server_spec.rb
CHANGED
@@ -4,34 +4,34 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
RSpec.describe Capybara::Server do
|
6
6
|
it 'should spool up a rack server' do
|
7
|
-
|
8
|
-
|
7
|
+
app = proc { |_env| [200, {}, ['Hello Server!']] }
|
8
|
+
server = described_class.new(app).boot
|
9
9
|
|
10
|
-
|
10
|
+
res = Net::HTTP.start(server.host, server.port) { |http| http.get('/') }
|
11
11
|
|
12
|
-
expect(
|
12
|
+
expect(res.body).to include('Hello Server')
|
13
13
|
end
|
14
14
|
|
15
15
|
it 'should do nothing when no server given' do
|
16
16
|
expect do
|
17
|
-
|
17
|
+
described_class.new(nil).boot
|
18
18
|
end.not_to raise_error
|
19
19
|
end
|
20
20
|
|
21
21
|
it 'should bind to the specified host' do
|
22
22
|
# TODO: travis with jruby in container mode has an issue with this test
|
23
|
-
skip 'This platform has an issue with this test' if (ENV
|
23
|
+
skip 'This platform has an issue with this test' if (ENV.fetch('TRAVIS', nil) && (RUBY_ENGINE == 'jruby')) || Gem.win_platform?
|
24
24
|
|
25
25
|
begin
|
26
26
|
app = proc { |_env| [200, {}, ['Hello Server!']] }
|
27
27
|
|
28
28
|
Capybara.server_host = '127.0.0.1'
|
29
|
-
server =
|
29
|
+
server = described_class.new(app).boot
|
30
30
|
res = Net::HTTP.get(URI("http://127.0.0.1:#{server.port}"))
|
31
31
|
expect(res).to eq('Hello Server!')
|
32
32
|
|
33
33
|
Capybara.server_host = '0.0.0.0'
|
34
|
-
server =
|
34
|
+
server = described_class.new(app).boot
|
35
35
|
res = Net::HTTP.get(URI("http://127.0.0.1:#{server.port}"))
|
36
36
|
expect(res).to eq('Hello Server!')
|
37
37
|
ensure
|
@@ -42,84 +42,140 @@ RSpec.describe Capybara::Server do
|
|
42
42
|
it 'should use specified port' do
|
43
43
|
Capybara.server_port = 22789
|
44
44
|
|
45
|
-
|
46
|
-
|
45
|
+
app = proc { |_env| [200, {}, ['Hello Server!']] }
|
46
|
+
server = described_class.new(app).boot
|
47
47
|
|
48
|
-
|
49
|
-
expect(
|
48
|
+
res = Net::HTTP.start(server.host, 22789) { |http| http.get('/') }
|
49
|
+
expect(res.body).to include('Hello Server')
|
50
50
|
|
51
51
|
Capybara.server_port = nil
|
52
52
|
end
|
53
53
|
|
54
54
|
it 'should use given port' do
|
55
|
-
|
56
|
-
|
55
|
+
app = proc { |_env| [200, {}, ['Hello Server!']] }
|
56
|
+
server = described_class.new(app, port: 22790).boot
|
57
57
|
|
58
|
-
|
59
|
-
expect(
|
58
|
+
res = Net::HTTP.start(server.host, 22790) { |http| http.get('/') }
|
59
|
+
expect(res.body).to include('Hello Server')
|
60
60
|
|
61
61
|
Capybara.server_port = nil
|
62
62
|
end
|
63
63
|
|
64
64
|
it 'should find an available port' do
|
65
|
-
|
66
|
-
|
65
|
+
responses = ['Hello Server!', 'Hello Second Server!']
|
66
|
+
apps = responses.map do |response|
|
67
|
+
proc { |_env| [200, {}, [response]] }
|
68
|
+
end
|
69
|
+
servers = apps.map { |app| described_class.new(app).boot }
|
67
70
|
|
68
|
-
|
69
|
-
|
71
|
+
servers.each_with_index do |server, idx|
|
72
|
+
result = Net::HTTP.start(server.host, server.port) { |http| http.get('/') }
|
73
|
+
expect(result.body).to include(responses[idx])
|
74
|
+
end
|
75
|
+
end
|
70
76
|
|
71
|
-
|
72
|
-
|
77
|
+
it 'should handle that getting available ports fails randomly' do
|
78
|
+
# Use a port to force a EADDRINUSE error to be generated
|
79
|
+
server = TCPServer.new('0.0.0.0', 0)
|
80
|
+
server_port = server.addr[1]
|
81
|
+
d_server = instance_double(TCPServer, addr: [nil, server_port, nil, nil], close: nil)
|
82
|
+
call_count = 0
|
83
|
+
allow(TCPServer).to receive(:new).and_wrap_original do |m, *args|
|
84
|
+
call_count.zero? ? d_server : m.call(*args)
|
85
|
+
ensure
|
86
|
+
call_count += 1
|
87
|
+
end
|
73
88
|
|
74
|
-
|
75
|
-
expect(
|
89
|
+
port = described_class.new(Object.new, host: '0.0.0.0').port
|
90
|
+
expect(port).not_to eq(server_port)
|
91
|
+
ensure
|
92
|
+
server&.close
|
76
93
|
end
|
77
94
|
|
78
|
-
it 'should
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
server = Capybara::Server.new(app).boot
|
95
|
+
it 'should return its #base_url' do
|
96
|
+
app = proc { |_env| [200, {}, ['Hello Server!']] }
|
97
|
+
server = described_class.new(app).boot
|
98
|
+
uri = Addressable::URI.parse(server.base_url)
|
99
|
+
expect(uri.to_hash).to include(scheme: 'http', host: server.host, port: server.port)
|
100
|
+
end
|
85
101
|
|
86
|
-
|
87
|
-
|
88
|
-
|
102
|
+
it 'should call #clamp on the puma configuration to ensure that environment is a string' do
|
103
|
+
Capybara.server = :puma
|
104
|
+
app_proc = proc { |_env| [200, {}, ['Hello Puma!']] }
|
105
|
+
require 'puma'
|
106
|
+
allow(Puma::Server).to receive(:new).and_wrap_original do |method, app, events, options|
|
107
|
+
# If #clamp is not called on the puma config then this will be a Proc
|
108
|
+
expect(options.fetch(:environment)).to be_a(String)
|
109
|
+
method.call(app, events, options)
|
110
|
+
end
|
111
|
+
server = described_class.new(app_proc).boot
|
112
|
+
expect(Puma::Server).to have_received(:new).with(
|
113
|
+
anything,
|
114
|
+
anything,
|
115
|
+
satisfy { |opts| opts.final_options[:Port] == server.port }
|
116
|
+
)
|
117
|
+
ensure
|
118
|
+
Capybara.server = :default
|
119
|
+
end
|
89
120
|
|
90
|
-
|
91
|
-
|
92
|
-
|
121
|
+
it 'should not emit any warnings when booting puma' do
|
122
|
+
Capybara.server = :puma
|
123
|
+
app_proc = proc { |_env| [200, {}, ['Hello Puma!']] }
|
124
|
+
require 'puma'
|
93
125
|
|
94
|
-
|
95
|
-
|
96
|
-
|
126
|
+
expect do
|
127
|
+
described_class.new(app_proc).boot
|
128
|
+
end.not_to output.to_stderr
|
129
|
+
ensure
|
130
|
+
Capybara.server = :default
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'should support SSL' do
|
134
|
+
key = File.join(Dir.pwd, 'spec', 'fixtures', 'key.pem')
|
135
|
+
cert = File.join(Dir.pwd, 'spec', 'fixtures', 'certificate.pem')
|
136
|
+
Capybara.server = :puma, { Host: "ssl://#{Capybara.server_host}?key=#{key}&cert=#{cert}" }
|
137
|
+
app = proc { |_env| [200, {}, ['Hello SSL Server!']] }
|
138
|
+
server = described_class.new(app).boot
|
139
|
+
|
140
|
+
expect do
|
141
|
+
Net::HTTP.start(server.host, server.port, max_retries: 0) { |http| http.get('/__identify__') }
|
142
|
+
end.to(raise_error do |e|
|
143
|
+
expect(e.is_a?(EOFError) || e.is_a?(Net::ReadTimeout)).to be true
|
144
|
+
end)
|
145
|
+
|
146
|
+
res = Net::HTTP.start(server.host, server.port, use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE) do |https|
|
147
|
+
https.get('/')
|
97
148
|
end
|
149
|
+
|
150
|
+
expect(res.body).to include('Hello SSL Server!')
|
151
|
+
uri = Addressable::URI.parse(server.base_url)
|
152
|
+
expect(uri.to_hash).to include(scheme: 'https', host: server.host, port: server.port)
|
153
|
+
ensure
|
154
|
+
Capybara.server = :default
|
98
155
|
end
|
99
156
|
|
100
157
|
context 'When Capybara.reuse_server is true' do
|
158
|
+
let!(:old_reuse_server) { Capybara.reuse_server }
|
159
|
+
|
101
160
|
before do
|
102
|
-
@old_reuse_server = Capybara.reuse_server
|
103
161
|
Capybara.reuse_server = true
|
104
162
|
end
|
105
163
|
|
106
164
|
after do
|
107
|
-
Capybara.reuse_server =
|
165
|
+
Capybara.reuse_server = old_reuse_server
|
108
166
|
end
|
109
167
|
|
110
168
|
it 'should use the existing server if it already running' do
|
111
|
-
|
112
|
-
|
113
|
-
@server1 = Capybara::Server.new(@app).boot
|
114
|
-
@server2 = Capybara::Server.new(@app).boot
|
169
|
+
app = proc { |_env| [200, {}, ['Hello Server!']] }
|
115
170
|
|
116
|
-
|
117
|
-
expect(res.body).to include('Hello Server')
|
171
|
+
servers = Array.new(2) { described_class.new(app).boot }
|
118
172
|
|
119
|
-
|
120
|
-
|
173
|
+
servers.each do |server|
|
174
|
+
res = Net::HTTP.start(server.host, server.port) { |http| http.get('/') }
|
175
|
+
expect(res.body).to include('Hello Server')
|
176
|
+
end
|
121
177
|
|
122
|
-
expect(
|
178
|
+
expect(servers[0].port).to eq(servers[1].port)
|
123
179
|
end
|
124
180
|
|
125
181
|
it 'detects and waits for all reused server sessions pending requests' do
|
@@ -132,15 +188,15 @@ RSpec.describe Capybara::Server do
|
|
132
188
|
[200, {}, ['Hello Server!']]
|
133
189
|
end
|
134
190
|
|
135
|
-
server1 =
|
136
|
-
server2 =
|
191
|
+
server1 = described_class.new(app).boot
|
192
|
+
server2 = described_class.new(app).boot
|
137
193
|
|
138
194
|
expect do
|
139
195
|
start_request(server1, 1.0)
|
140
196
|
start_request(server2, 3.0)
|
141
197
|
server1.wait_for_pending_requests
|
142
198
|
end.to change { done }.from(0).to(2)
|
143
|
-
expect(server2.send(:pending_requests?)).to
|
199
|
+
expect(server2.send(:pending_requests?)).to be(false)
|
144
200
|
end
|
145
201
|
end
|
146
202
|
|
@@ -151,22 +207,20 @@ RSpec.describe Capybara::Server do
|
|
151
207
|
end
|
152
208
|
|
153
209
|
after do
|
154
|
-
Capybara.reuse_server = @old_reuse_server
|
210
|
+
Capybara.reuse_server = @old_reuse_server # rubocop:disable RSpec/InstanceVariable
|
155
211
|
end
|
156
212
|
|
157
213
|
it 'should not reuse an already running server' do
|
158
|
-
|
159
|
-
|
160
|
-
@server1 = Capybara::Server.new(@app).boot
|
161
|
-
@server2 = Capybara::Server.new(@app).boot
|
214
|
+
app = proc { |_env| [200, {}, ['Hello Server!']] }
|
162
215
|
|
163
|
-
|
164
|
-
expect(res.body).to include('Hello Server')
|
216
|
+
servers = Array.new(2) { described_class.new(app).boot }
|
165
217
|
|
166
|
-
|
167
|
-
|
218
|
+
servers.each do |server|
|
219
|
+
res = Net::HTTP.start(server.host, server.port) { |http| http.get('/') }
|
220
|
+
expect(res.body).to include('Hello Server')
|
221
|
+
end
|
168
222
|
|
169
|
-
expect(
|
223
|
+
expect(servers[0].port).not_to eq(servers[1].port)
|
170
224
|
end
|
171
225
|
|
172
226
|
it 'detects and waits for only one sessions pending requests' do
|
@@ -179,15 +233,15 @@ RSpec.describe Capybara::Server do
|
|
179
233
|
[200, {}, ['Hello Server!']]
|
180
234
|
end
|
181
235
|
|
182
|
-
server1 =
|
183
|
-
server2 =
|
236
|
+
server1 = described_class.new(app).boot
|
237
|
+
server2 = described_class.new(app).boot
|
184
238
|
|
185
239
|
expect do
|
186
240
|
start_request(server1, 1.0)
|
187
241
|
start_request(server2, 3.0)
|
188
242
|
server1.wait_for_pending_requests
|
189
243
|
end.to change { done }.from(0).to(1)
|
190
|
-
expect(server2.send(:pending_requests?)).to
|
244
|
+
expect(server2.send(:pending_requests?)).to be(true)
|
191
245
|
expect do
|
192
246
|
server2.wait_for_pending_requests
|
193
247
|
end.to change { done }.from(1).to(2)
|
@@ -195,26 +249,44 @@ RSpec.describe Capybara::Server do
|
|
195
249
|
end
|
196
250
|
|
197
251
|
it 'should raise server errors when the server errors before the timeout' do
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
Capybara.server = :kaboom
|
252
|
+
Capybara.register_server :kaboom do
|
253
|
+
sleep 0.1
|
254
|
+
raise 'kaboom'
|
255
|
+
end
|
256
|
+
Capybara.server = :kaboom
|
204
257
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
258
|
+
expect do
|
259
|
+
described_class.new(proc { |e| }).boot
|
260
|
+
end.to raise_error(RuntimeError, 'kaboom')
|
261
|
+
ensure
|
262
|
+
Capybara.server = :default
|
263
|
+
end
|
264
|
+
|
265
|
+
it 'should raise an error when there are pending requests' do
|
266
|
+
app = proc do |env|
|
267
|
+
request = Rack::Request.new(env)
|
268
|
+
sleep request.params['wait_time'].to_f
|
269
|
+
[200, {}, ['Hello Server!']]
|
210
270
|
end
|
271
|
+
|
272
|
+
server = described_class.new(app).boot
|
273
|
+
|
274
|
+
expect do
|
275
|
+
start_request(server, 59.0)
|
276
|
+
server.wait_for_pending_requests
|
277
|
+
end.not_to raise_error
|
278
|
+
|
279
|
+
expect do
|
280
|
+
start_request(server, 61.0)
|
281
|
+
server.wait_for_pending_requests
|
282
|
+
end.to raise_error('Requests did not finish in 60 seconds: ["/?wait_time=61.0"]')
|
211
283
|
end
|
212
284
|
|
213
285
|
it 'is not #responsive? when Net::HTTP raises a SystemCallError' do
|
214
286
|
app = -> { [200, {}, ['Hello, world']] }
|
215
|
-
server =
|
287
|
+
server = described_class.new(app)
|
216
288
|
allow(Net::HTTP).to receive(:start).and_raise(SystemCallError.allocate)
|
217
|
-
expect(server.responsive?).to
|
289
|
+
expect(server.responsive?).to be false
|
218
290
|
end
|
219
291
|
|
220
292
|
[EOFError, Net::ReadTimeout].each do |err|
|
@@ -227,7 +299,7 @@ RSpec.describe Capybara::Server do
|
|
227
299
|
response = Net::HTTPSuccess.allocate
|
228
300
|
allow(response).to receive(:body).and_return app.object_id.to_s
|
229
301
|
allow(Net::HTTP).to receive(:start).with(anything, anything, hash_including(use_ssl: true)).and_return(response).once
|
230
|
-
|
302
|
+
described_class.new(app).boot
|
231
303
|
expect(Net::HTTP).to have_received(:start).exactly(3).times
|
232
304
|
end
|
233
305
|
end
|
data/spec/session_spec.rb
CHANGED
@@ -3,16 +3,16 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
RSpec.describe Capybara::Session do
|
6
|
-
|
6
|
+
describe '#new' do
|
7
7
|
it 'should raise an error if passed non-existent driver' do
|
8
8
|
expect do
|
9
|
-
|
9
|
+
described_class.new(:quox, TestApp).driver
|
10
10
|
end.to raise_error(Capybara::DriverNotFoundError)
|
11
11
|
end
|
12
12
|
|
13
13
|
it 'verifies a passed app is a rack app' do
|
14
14
|
expect do
|
15
|
-
|
15
|
+
described_class.new(:unknown, random: 'hash')
|
16
16
|
end.to raise_error TypeError, 'The second parameter to Session::new should be a rack app if passed.'
|
17
17
|
end
|
18
18
|
end
|
@@ -75,10 +75,17 @@ RSpec.describe Capybara::Session do
|
|
75
75
|
|
76
76
|
context 'quit' do
|
77
77
|
it 'will reset the driver' do
|
78
|
-
session =
|
78
|
+
session = described_class.new(:rack_test, TestApp)
|
79
79
|
driver = session.driver
|
80
80
|
session.quit
|
81
81
|
expect(session.driver).not_to eql driver
|
82
82
|
end
|
83
|
+
|
84
|
+
it 'resets the document' do
|
85
|
+
session = described_class.new(:rack_test, TestApp)
|
86
|
+
document = session.document
|
87
|
+
session.quit
|
88
|
+
expect(session.document.base).not_to eql document.base
|
89
|
+
end
|
83
90
|
end
|
84
91
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'selenium-webdriver'
|
5
|
+
|
6
|
+
RSpec.shared_examples 'Capybara::Node' do |session, _mode|
|
7
|
+
let(:session) { session }
|
8
|
+
|
9
|
+
describe '#content_editable?' do
|
10
|
+
it 'returns true when the element is content editable' do
|
11
|
+
session.visit('/with_js')
|
12
|
+
expect(session.find(:css, '#existing_content_editable').base.content_editable?).to be true
|
13
|
+
expect(session.find(:css, '#existing_content_editable_child').base.content_editable?).to be true
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'returns false when the element is not content editable' do
|
17
|
+
session.visit('/with_js')
|
18
|
+
expect(session.find(:css, '#drag').base.content_editable?).to be false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#send_keys' do
|
23
|
+
it 'should process space' do
|
24
|
+
session.visit('/form')
|
25
|
+
session.find(:css, '#address1_city').send_keys('ocean', [:shift, :space, 'side'])
|
26
|
+
expect(session.find(:css, '#address1_city').value).to eq 'ocean SIDE'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#[]' do
|
31
|
+
it 'should work for spellcheck' do
|
32
|
+
session.visit('/with_html')
|
33
|
+
expect(session.find('//input[@spellcheck="TRUE"]')[:spellcheck]).to eq('true')
|
34
|
+
expect(session.find('//input[@spellcheck="FALSE"]')[:spellcheck]).to eq('false')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#set' do
|
39
|
+
it 'respects maxlength when using rapid set' do
|
40
|
+
session.visit('/form')
|
41
|
+
inp = session.find(:css, '#long_length')
|
42
|
+
value = (0...50).map { |i| ((i % 26) + 65).chr }.join
|
43
|
+
inp.set(value, rapid: true)
|
44
|
+
expect(inp.value).to eq value[0...35]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#visible?' do
|
49
|
+
let(:bridge) do
|
50
|
+
session.driver.browser.send(:bridge)
|
51
|
+
end
|
52
|
+
|
53
|
+
around do |example|
|
54
|
+
native_displayed = session.driver.options[:native_displayed]
|
55
|
+
example.run
|
56
|
+
session.driver.options[:native_displayed] = native_displayed
|
57
|
+
end
|
58
|
+
|
59
|
+
before do
|
60
|
+
allow(bridge).to receive(:execute_atom).and_call_original
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'will use native displayed if told to' do
|
64
|
+
session.driver.options[:native_displayed] = true
|
65
|
+
session.visit('/form')
|
66
|
+
session.find(:css, '#address1_city', visible: true)
|
67
|
+
|
68
|
+
expect(bridge).not_to have_received(:execute_atom)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "won't use native displayed if told not to" do
|
72
|
+
session.driver.options[:native_displayed] = false
|
73
|
+
session.visit('/form')
|
74
|
+
session.find(:css, '#address1_city', visible: true)
|
75
|
+
|
76
|
+
expect(bridge).to have_received(:execute_atom).with(:isDisplayed, any_args)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|