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
@@ -23,32 +23,35 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
23
23
|
it 'freshly reset session should not be touched' do
|
24
24
|
session.instance_variable_set(:@touched, true)
|
25
25
|
session.reset!
|
26
|
-
expect(session.instance_variable_get(:@touched)).to
|
26
|
+
expect(session.instance_variable_get(:@touched)).to be false
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
30
|
describe 'exit codes' do
|
31
|
+
let(:env) { { 'SELENIUM_BROWSER' => session.driver.options[:browser].to_s } }
|
32
|
+
let!(:orig_dir) { Dir.getwd }
|
33
|
+
|
31
34
|
before do
|
32
|
-
@current_dir = Dir.getwd
|
33
35
|
Dir.chdir(File.join(File.dirname(__FILE__), '..'))
|
34
|
-
@env = { 'SELENIUM_BROWSER' => session.driver.options[:browser].to_s }
|
35
36
|
end
|
36
37
|
|
37
38
|
after do
|
38
|
-
Dir.chdir(
|
39
|
+
Dir.chdir(orig_dir)
|
39
40
|
end
|
40
41
|
|
41
42
|
it 'should have return code 1 when running selenium_driver_rspec_failure.rb' do
|
42
43
|
skip 'only setup for local non-headless' if headless_or_remote?
|
44
|
+
skip 'Not setup for edge' if edge?(session)
|
43
45
|
|
44
|
-
system(
|
46
|
+
system(env, 'rspec spec/fixtures/selenium_driver_rspec_failure.rb', out: File::NULL, err: File::NULL)
|
45
47
|
expect($CHILD_STATUS.exitstatus).to eq(1)
|
46
48
|
end
|
47
49
|
|
48
50
|
it 'should have return code 0 when running selenium_driver_rspec_success.rb' do
|
49
51
|
skip 'only setup for local non-headless' if headless_or_remote?
|
52
|
+
skip 'Not setup for edge' if edge?(session)
|
50
53
|
|
51
|
-
system(
|
54
|
+
system(env, 'rspec spec/fixtures/selenium_driver_rspec_success.rb', out: File::NULL, err: File::NULL)
|
52
55
|
expect($CHILD_STATUS.exitstatus).to eq(0)
|
53
56
|
end
|
54
57
|
end
|
@@ -69,7 +72,7 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
69
72
|
end
|
70
73
|
end
|
71
74
|
|
72
|
-
|
75
|
+
describe '#fill_in_with empty string and no options' do
|
73
76
|
it 'should trigger change when clearing a field' do
|
74
77
|
session.visit('/with_js')
|
75
78
|
session.fill_in('with_change_event', with: '')
|
@@ -79,7 +82,7 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
79
82
|
end
|
80
83
|
end
|
81
84
|
|
82
|
-
|
85
|
+
describe '#fill_in with { :clear => :backspace } fill_option', requires: [:js] do
|
83
86
|
before do
|
84
87
|
# Firefox has an issue with change events if the main window doesn't think it's focused
|
85
88
|
session.execute_script('window.focus()')
|
@@ -115,6 +118,7 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
115
118
|
|
116
119
|
it 'should only trigger onchange once' do
|
117
120
|
session.visit('/with_js')
|
121
|
+
sleep 2 if safari?(session) # Safari needs a delay (to load event handlers maybe ???)
|
118
122
|
session.fill_in('with_change_event',
|
119
123
|
with: 'some value',
|
120
124
|
fill_options: { clear: :backspace })
|
@@ -139,22 +143,34 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
139
143
|
with: '',
|
140
144
|
fill_options: { clear: :backspace })
|
141
145
|
# click outside the field to trigger the change event
|
142
|
-
session.find(:css, 'body').click
|
146
|
+
# session.find(:css, 'body').click
|
147
|
+
session.find(:css, 'h1', text: 'FooBar').click
|
143
148
|
expect(session).to have_xpath('//p[@class="input_event_triggered"]', count: 13)
|
144
149
|
end
|
145
150
|
end
|
146
151
|
|
147
|
-
|
152
|
+
describe '#fill_in with { clear: :none } fill_options' do
|
148
153
|
it 'should append to content in a field' do
|
154
|
+
pending 'Safari overwrites by default - need to figure out a workaround' if safari?(session)
|
155
|
+
|
149
156
|
session.visit('/form')
|
150
157
|
session.fill_in('form_first_name',
|
151
158
|
with: 'Harry',
|
152
159
|
fill_options: { clear: :none })
|
153
160
|
expect(session.find(:fillable_field, 'form_first_name').value).to eq('JohnHarry')
|
154
161
|
end
|
162
|
+
|
163
|
+
it 'works with rapid fill' do
|
164
|
+
pending 'Safari overwrites by default - need to figure out a workaround' if safari?(session)
|
165
|
+
|
166
|
+
long_string = (0...60).map { |i| ((i % 26) + 65).chr }.join
|
167
|
+
session.visit('/form')
|
168
|
+
session.fill_in('form_first_name', with: long_string, fill_options: { clear: :none })
|
169
|
+
expect(session.find(:fillable_field, 'form_first_name').value).to eq("John#{long_string}")
|
170
|
+
end
|
155
171
|
end
|
156
172
|
|
157
|
-
|
173
|
+
describe '#fill_in with Date' do
|
158
174
|
before do
|
159
175
|
session.visit('/form')
|
160
176
|
session.find(:css, '#form_date').execute_script <<-JS
|
@@ -165,7 +181,8 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
165
181
|
});
|
166
182
|
JS
|
167
183
|
# work around weird FF issue where it would create an extra focus issue in some cases
|
168
|
-
session.find(:css, '
|
184
|
+
session.find(:css, 'h1', text: 'Form').click
|
185
|
+
# session.find(:css, 'body').click
|
169
186
|
end
|
170
187
|
|
171
188
|
it 'should generate standard events on changing value' do
|
@@ -183,7 +200,7 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
183
200
|
end
|
184
201
|
end
|
185
202
|
|
186
|
-
|
203
|
+
describe '#fill_in with { clear: Array } fill_options' do
|
187
204
|
it 'should pass the array through to the element' do
|
188
205
|
# this is mainly for use with [[:control, 'a'], :backspace] - however since that is platform dependant I'm testing with something less useful
|
189
206
|
session.visit('/form')
|
@@ -194,6 +211,26 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
194
211
|
end
|
195
212
|
end
|
196
213
|
|
214
|
+
describe '#fill_in with Emoji' do
|
215
|
+
it 'sends emojis' do
|
216
|
+
session.visit('/form')
|
217
|
+
session.fill_in('form_first_name', with: 'a😀cd😴 🛌🏽🇵🇹 e🤾🏽♀️f')
|
218
|
+
expect(session.find(:fillable_field, 'form_first_name').value).to eq('a😀cd😴 🛌🏽🇵🇹 e🤾🏽♀️f')
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
describe '#send_keys' do
|
223
|
+
it 'defaults to sending keys to the active_element' do
|
224
|
+
session.visit('/form')
|
225
|
+
|
226
|
+
expect(session.active_element).to match_selector(:css, 'body')
|
227
|
+
|
228
|
+
session.send_keys(:tab)
|
229
|
+
|
230
|
+
expect(session.active_element).to match_selector(:css, '[tabindex="1"]')
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
197
234
|
describe '#path' do
|
198
235
|
it 'returns xpath' do
|
199
236
|
# this is here because it is testing for an XPath that is specific to the algorithm used in the selenium driver
|
@@ -243,6 +280,13 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
243
280
|
expect(element).to eq session.find(:id, 'form_title')
|
244
281
|
end
|
245
282
|
|
283
|
+
it 'returns a shadow root' do
|
284
|
+
session.visit('/with_shadow')
|
285
|
+
shadow = session.find(:css, '#shadow_host')
|
286
|
+
element = session.evaluate_script('arguments[0].shadowRoot', shadow)
|
287
|
+
expect(element).to be_instance_of(Capybara::Node::Element)
|
288
|
+
end
|
289
|
+
|
246
290
|
it 'can return arrays of nested elements' do
|
247
291
|
session.visit('/form')
|
248
292
|
elements = session.evaluate_script('document.querySelectorAll("#form_city option")')
|
@@ -263,6 +307,7 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
263
307
|
|
264
308
|
describe '#evaluate_async_script' do
|
265
309
|
it 'will timeout if the script takes too long' do
|
310
|
+
skip 'safaridriver returns the wrong error type' if safari?(session)
|
266
311
|
session.visit('/with_js')
|
267
312
|
expect do
|
268
313
|
session.using_wait_time(1) do
|
@@ -287,65 +332,35 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
287
332
|
describe 'Element#click' do
|
288
333
|
it 'should handle fixed headers/footers' do
|
289
334
|
session.visit('/with_fixed_header_footer')
|
290
|
-
|
291
|
-
|
335
|
+
session.using_wait_time(2) do
|
336
|
+
session.find(:link, 'Go to root').click
|
337
|
+
end
|
292
338
|
expect(session).to have_current_path('/')
|
293
339
|
end
|
294
340
|
end
|
295
341
|
|
296
|
-
describe 'Element#drag_to' do
|
297
|
-
before do
|
298
|
-
skip "Firefox < 62 doesn't support a DataTransfer constuctor" if firefox_lt?(62.0, session)
|
299
|
-
skip "IE doesn't support a DataTransfer constuctor" if ie?(session)
|
300
|
-
end
|
301
|
-
|
302
|
-
it 'should HTML5 drag and drop an object' do
|
303
|
-
session.visit('/with_js')
|
304
|
-
element = session.find('//div[@id="drag_html5"]')
|
305
|
-
target = session.find('//div[@id="drop_html5"]')
|
306
|
-
element.drag_to(target)
|
307
|
-
expect(session).to have_xpath('//div[contains(., "HTML5 Dropped drag_html5")]')
|
308
|
-
end
|
309
|
-
|
310
|
-
it 'should not HTML5 drag and drop on a non HTML5 drop element' do
|
311
|
-
session.visit('/with_js')
|
312
|
-
element = session.find('//div[@id="drag_html5"]')
|
313
|
-
target = session.find('//div[@id="drop_html5"]')
|
314
|
-
target.execute_script("$(this).removeClass('drop');")
|
315
|
-
element.drag_to(target)
|
316
|
-
sleep 1
|
317
|
-
expect(session).not_to have_xpath('//div[contains(., "HTML5 Dropped drag_html5")]')
|
318
|
-
end
|
319
|
-
|
320
|
-
it 'should HTML5 drag and drop when scrolling needed' do
|
321
|
-
session.visit('/with_js')
|
322
|
-
element = session.find('//div[@id="drag_html5_scroll"]')
|
323
|
-
target = session.find('//div[@id="drop_html5_scroll"]')
|
324
|
-
element.drag_to(target)
|
325
|
-
expect(session).to have_xpath('//div[contains(., "HTML5 Dropped drag_html5_scroll")]')
|
326
|
-
end
|
327
|
-
|
328
|
-
it 'should drag HTML5 default draggable elements' do
|
329
|
-
session.visit('/with_js')
|
330
|
-
link = session.find_link('drag_link_html5')
|
331
|
-
target = session.find(:id, 'drop_html5')
|
332
|
-
link.drag_to target
|
333
|
-
expect(session).to have_xpath('//div[contains(., "HTML5 Dropped")]')
|
334
|
-
end
|
335
|
-
end
|
336
|
-
|
337
342
|
describe 'Capybara#Node#attach_file' do
|
338
343
|
it 'can attach a directory' do
|
339
344
|
pending "Geckodriver doesn't support uploading a directory" if firefox?(session)
|
340
345
|
pending "Selenium remote doesn't support transferring a directory" if remote?(session)
|
341
|
-
pending "Headless Chrome doesn't support directory upload - https://bugs.chromium.org/p/chromedriver/issues/detail?id=2521&q=directory%20upload&colspec=ID%20Status%20Pri%20Owner%20Summary" if chrome?(session) && ENV
|
346
|
+
pending "Headless Chrome doesn't support directory upload - https://bugs.chromium.org/p/chromedriver/issues/detail?id=2521&q=directory%20upload&colspec=ID%20Status%20Pri%20Owner%20Summary" if chrome?(session) && chrome_lt?(110, session) && ENV.fetch('HEADLESS', nil)
|
342
347
|
pending "IE doesn't support uploading a directory" if ie?(session)
|
348
|
+
pending 'Chrome/chromedriver 73 breaks this' if chrome?(session) && chrome_gte?(73, session) && chrome_lt?(75, session)
|
343
349
|
|
344
350
|
session.visit('/form')
|
345
|
-
|
346
|
-
session.attach_file('Directory Upload',
|
351
|
+
test_file_dir = File.expand_path('./fixtures', File.dirname(__FILE__))
|
352
|
+
session.attach_file('Directory Upload', test_file_dir)
|
347
353
|
session.click_button('Upload Multiple')
|
348
|
-
expect(session
|
354
|
+
expect(session).to have_text('5 | ') # number of files
|
355
|
+
end
|
356
|
+
|
357
|
+
it 'can attach a relative file' do
|
358
|
+
pending 'Geckdoriver on windows requires alternate file separator which path expansion replaces' if Gem.win_platform? && firefox?(session)
|
359
|
+
|
360
|
+
session.visit('/form')
|
361
|
+
session.attach_file('Single Document', 'spec/fixtures/capybara.csv')
|
362
|
+
session.click_button('Upload Single')
|
363
|
+
expect(session).to have_text('Content-type: text/csv')
|
349
364
|
end
|
350
365
|
end
|
351
366
|
|
@@ -357,17 +372,21 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
357
372
|
end
|
358
373
|
end
|
359
374
|
|
375
|
+
# rubocop:disable RSpec/InstanceVariable
|
360
376
|
describe 'Capybara#disable_animation' do
|
361
377
|
context 'when set to `true`' do
|
362
378
|
before(:context) do # rubocop:disable RSpec/BeforeAfterAll
|
379
|
+
skip "Safari doesn't support multiple sessions" if safari?(session)
|
363
380
|
# NOTE: Although Capybara.SpecHelper.reset! sets Capybara.disable_animation to false,
|
364
381
|
# it doesn't affect any of these tests because the settings are applied per-session
|
365
382
|
Capybara.disable_animation = true
|
366
383
|
@animation_session = Capybara::Session.new(session.mode, TestApp.new)
|
367
384
|
end
|
368
385
|
|
369
|
-
|
370
|
-
@animation_session
|
386
|
+
it 'should add CSS to the <head> element' do
|
387
|
+
@animation_session.visit('with_animation')
|
388
|
+
|
389
|
+
expect(@animation_session).to have_selector(:css, 'head > style', text: 'transition: none', visible: :hidden)
|
371
390
|
end
|
372
391
|
|
373
392
|
it 'should disable CSS transitions' do
|
@@ -376,33 +395,87 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
376
395
|
expect(@animation_session).to have_no_link('transition me away', wait: 0.5)
|
377
396
|
end
|
378
397
|
|
379
|
-
it 'should disable CSS animations' do
|
398
|
+
it 'should disable CSS animations (set to 0s)' do
|
380
399
|
@animation_session.visit('with_animation')
|
400
|
+
sleep 1
|
381
401
|
@animation_session.click_link('animate me away')
|
382
402
|
expect(@animation_session).to have_no_link('animate me away', wait: 0.5)
|
383
403
|
end
|
404
|
+
|
405
|
+
it 'should disable CSS animations on pseudo elements (set to 0s)' do
|
406
|
+
@animation_session.visit('with_animation')
|
407
|
+
sleep 1
|
408
|
+
@animation_session.find_link('animate me away').right_click
|
409
|
+
expect(@animation_session).to have_content('Animation Ended', wait: 0.1)
|
410
|
+
end
|
411
|
+
|
412
|
+
it 'should scroll the page instantly', requires: [:js] do
|
413
|
+
@animation_session.visit('with_animation')
|
414
|
+
scroll_y = @animation_session.evaluate_script(<<~JS)
|
415
|
+
(function(){
|
416
|
+
window.scrollTo(0,500);
|
417
|
+
return window.scrollY;
|
418
|
+
})()
|
419
|
+
JS
|
420
|
+
expect(scroll_y).to eq 500
|
421
|
+
end
|
422
|
+
|
423
|
+
it 'should scroll the page instantly without jquery animation', requires: [:js] do
|
424
|
+
@animation_session.visit('with_jquery_animation')
|
425
|
+
@animation_session.click_link('scroll top 500')
|
426
|
+
scroll_y = @animation_session.evaluate_script('window.scrollY')
|
427
|
+
expect(scroll_y).to eq 500
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
context 'when set to `false`' do
|
432
|
+
before(:context) do # rubocop:disable RSpec/BeforeAfterAll
|
433
|
+
skip "Safari doesn't support multiple sessions" if safari?(session)
|
434
|
+
# NOTE: Although Capybara.SpecHelper.reset! sets Capybara.disable_animation to false,
|
435
|
+
# it doesn't affect any of these tests because the settings are applied per-session
|
436
|
+
Capybara.disable_animation = false
|
437
|
+
@animation_session = Capybara::Session.new(session.mode, TestApp.new)
|
438
|
+
end
|
439
|
+
|
440
|
+
it 'should scroll the page with a smooth animation', requires: [:js] do
|
441
|
+
@animation_session.visit('with_animation')
|
442
|
+
scroll_y = @animation_session.evaluate_script(<<~JS)
|
443
|
+
(function(){
|
444
|
+
window.scrollTo(0,500);
|
445
|
+
return window.scrollY;
|
446
|
+
})()
|
447
|
+
JS
|
448
|
+
# measured over 0.5 seconds: 0, 75, 282, 478, 500
|
449
|
+
expect(scroll_y).to be < 500
|
450
|
+
end
|
451
|
+
|
452
|
+
it 'should scroll the page with jquery animation', requires: [:js] do
|
453
|
+
@animation_session.visit('with_jquery_animation')
|
454
|
+
@animation_session.click_link('scroll top 500')
|
455
|
+
scroll_y = @animation_session.evaluate_script('window.scrollY')
|
456
|
+
expect(scroll_y).to be < 500
|
457
|
+
end
|
384
458
|
end
|
385
459
|
|
386
460
|
context 'if we pass in css that matches elements' do
|
387
461
|
before(:context) do # rubocop:disable RSpec/BeforeAfterAll
|
462
|
+
skip "safaridriver doesn't support multiple sessions" if safari?(session)
|
388
463
|
# NOTE: Although Capybara.SpecHelper.reset! sets Capybara.disable_animation to false,
|
389
464
|
# it doesn't affect any of these tests because the settings are applied per-session
|
390
465
|
Capybara.disable_animation = '#with_animation a'
|
391
466
|
@animation_session_with_matching_css = Capybara::Session.new(session.mode, TestApp.new)
|
392
467
|
end
|
393
468
|
|
394
|
-
after(:context) do # rubocop:disable RSpec/BeforeAfterAll
|
395
|
-
@animation_session_with_matching_css = nil
|
396
|
-
end
|
397
|
-
|
398
469
|
it 'should disable CSS transitions' do
|
399
470
|
@animation_session_with_matching_css.visit('with_animation')
|
471
|
+
sleep 1
|
400
472
|
@animation_session_with_matching_css.click_link('transition me away')
|
401
473
|
expect(@animation_session_with_matching_css).to have_no_link('transition me away', wait: 0.5)
|
402
474
|
end
|
403
475
|
|
404
476
|
it 'should disable CSS animations' do
|
405
477
|
@animation_session_with_matching_css.visit('with_animation')
|
478
|
+
sleep 1
|
406
479
|
@animation_session_with_matching_css.click_link('animate me away')
|
407
480
|
expect(@animation_session_with_matching_css).to have_no_link('animate me away', wait: 0.5)
|
408
481
|
end
|
@@ -410,18 +483,16 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
410
483
|
|
411
484
|
context 'if we pass in css that does not match elements' do
|
412
485
|
before(:context) do # rubocop:disable RSpec/BeforeAfterAll
|
486
|
+
skip "Safari doesn't support multiple sessions" if safari?(session)
|
413
487
|
# NOTE: Although Capybara.SpecHelper.reset! sets Capybara.disable_animation to false,
|
414
488
|
# it doesn't affect any of these tests because the settings are applied per-session
|
415
489
|
Capybara.disable_animation = '.this-class-matches-nothing'
|
416
490
|
@animation_session_without_matching_css = Capybara::Session.new(session.mode, TestApp.new)
|
417
491
|
end
|
418
492
|
|
419
|
-
after(:context) do # rubocop:disable RSpec/BeforeAfterAll
|
420
|
-
@animation_session_without_matching_css = nil
|
421
|
-
end
|
422
|
-
|
423
493
|
it 'should not disable CSS transitions' do
|
424
494
|
@animation_session_without_matching_css.visit('with_animation')
|
495
|
+
sleep 1
|
425
496
|
@animation_session_without_matching_css.click_link('transition me away')
|
426
497
|
sleep 0.5 # Wait long enough for click to have been processed
|
427
498
|
expect(@animation_session_without_matching_css).to have_link('transition me away', wait: false)
|
@@ -430,6 +501,7 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
430
501
|
|
431
502
|
it 'should not disable CSS animations' do
|
432
503
|
@animation_session_without_matching_css.visit('with_animation')
|
504
|
+
sleep 1
|
433
505
|
@animation_session_without_matching_css.click_link('animate me away')
|
434
506
|
sleep 0.5 # Wait long enough for click to have been processed
|
435
507
|
expect(@animation_session_without_matching_css).to have_link('animate me away', wait: false)
|
@@ -437,20 +509,53 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
437
509
|
end
|
438
510
|
end
|
439
511
|
end
|
512
|
+
# rubocop:enable RSpec/InstanceVariable
|
440
513
|
|
441
514
|
describe ':element selector' do
|
442
515
|
it 'can find html5 svg elements' do
|
443
516
|
session.visit('with_html5_svg')
|
444
517
|
expect(session).to have_selector(:element, :svg)
|
445
|
-
expect(session).to have_selector(:element, :rect, visible:
|
518
|
+
expect(session).to have_selector(:element, :rect, visible: :visible)
|
446
519
|
expect(session).to have_selector(:element, :circle)
|
447
520
|
expect(session).to have_selector(:element, :linearGradient, visible: :all)
|
448
521
|
end
|
449
522
|
|
450
523
|
it 'can query attributes with strange characters' do
|
451
524
|
session.visit('/form')
|
452
|
-
expect(session).to have_selector(:element,
|
453
|
-
expect(session).to have_selector(:element,
|
525
|
+
expect(session).to have_selector(:element, '{custom}': true)
|
526
|
+
expect(session).to have_selector(:element, '{custom}': 'abcdef')
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
describe 'with react' do
|
531
|
+
context 'controlled components' do
|
532
|
+
it 'can set and clear a text field' do
|
533
|
+
skip "This test doesn't support older browsers" if ie?(session)
|
534
|
+
|
535
|
+
session.visit 'react'
|
536
|
+
|
537
|
+
session.fill_in('Name:', with: 'abc')
|
538
|
+
session.accept_prompt 'A name was submitted: abc' do
|
539
|
+
session.click_button('Submit')
|
540
|
+
end
|
541
|
+
|
542
|
+
session.fill_in('Name:', with: '')
|
543
|
+
session.accept_prompt(/A name was submitted: $/) do
|
544
|
+
session.click_button('Submit')
|
545
|
+
end
|
546
|
+
end
|
547
|
+
|
548
|
+
it 'works with rapid fill' do
|
549
|
+
skip "This test doesn't support older browsers" if ie?(session)
|
550
|
+
|
551
|
+
session.visit 'react'
|
552
|
+
long_string = (0...60).map { |i| ((i % 26) + 65).chr }.join
|
553
|
+
|
554
|
+
session.fill_in('Name:', with: long_string)
|
555
|
+
session.accept_prompt "A name was submitted: #{long_string}" do
|
556
|
+
session.click_button('Submit')
|
557
|
+
end
|
558
|
+
end
|
454
559
|
end
|
455
560
|
end
|
456
561
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,15 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'rspec/expectations'
|
4
|
-
require '
|
5
|
-
require 'webdrivers' if ENV['CI']
|
4
|
+
require 'webdrivers' if ENV.fetch('WEBDRIVERS', nil)
|
6
5
|
require 'selenium_statistics'
|
6
|
+
if ENV['TRAVIS']
|
7
|
+
require 'coveralls'
|
8
|
+
Coveralls.wear! do
|
9
|
+
add_filter '/lib/capybara/driver/'
|
10
|
+
add_filter '/lib/capybara/registrations/'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
require 'capybara/spec/spec_helper'
|
7
14
|
|
8
15
|
module Capybara
|
9
16
|
module SpecHelper
|
10
17
|
def firefox?(session)
|
11
18
|
browser_name(session) == :firefox &&
|
12
|
-
|
19
|
+
((defined?(::Selenium::WebDriver::VERSION) && (Gem::Version.new(::Selenium::WebDriver::VERSION) >= Gem::Version.new('4'))) ||
|
20
|
+
session.driver.browser.capabilities.is_a?(::Selenium::WebDriver::Remote::W3C::Capabilities))
|
13
21
|
end
|
14
22
|
|
15
23
|
def firefox_lt?(version, session)
|
@@ -20,26 +28,80 @@ module Capybara
|
|
20
28
|
firefox?(session) && (session.driver.browser.capabilities[:browser_version].to_f >= version)
|
21
29
|
end
|
22
30
|
|
31
|
+
def geckodriver_version(session)
|
32
|
+
Gem::Version.new(session.driver.browser.capabilities['moz:geckodriverVersion'])
|
33
|
+
end
|
34
|
+
|
35
|
+
def geckodriver_gte?(version, session)
|
36
|
+
firefox?(session) && geckodriver_version(session) >= Gem::Version.new(version)
|
37
|
+
end
|
38
|
+
|
39
|
+
def geckodriver_lt?(version, session)
|
40
|
+
firefox?(session) && geckodriver_version(session) < Gem::Version.new(version)
|
41
|
+
end
|
42
|
+
|
23
43
|
def chrome?(session)
|
24
44
|
browser_name(session) == :chrome
|
25
45
|
end
|
26
46
|
|
47
|
+
def chrome_version(session)
|
48
|
+
(session.driver.browser.capabilities[:browser_version] ||
|
49
|
+
session.driver.browser.capabilities[:version]).to_f
|
50
|
+
end
|
51
|
+
|
27
52
|
def chrome_lt?(version, session)
|
28
|
-
chrome?(session) && (session
|
53
|
+
chrome?(session) && (chrome_version(session) < version)
|
29
54
|
end
|
30
55
|
|
31
56
|
def chrome_gte?(version, session)
|
32
|
-
chrome?(session) && (session
|
57
|
+
chrome?(session) && (chrome_version(session) >= version)
|
58
|
+
end
|
59
|
+
|
60
|
+
def chromedriver_version(session)
|
61
|
+
Gem::Version.new(session.driver.browser.capabilities['chrome']['chromedriverVersion'].split[0])
|
62
|
+
end
|
63
|
+
|
64
|
+
def chromedriver_gte?(version, session)
|
65
|
+
chrome?(session) && chromedriver_version(session) >= Gem::Version.new(version)
|
66
|
+
end
|
67
|
+
|
68
|
+
def chromedriver_lt?(version, session)
|
69
|
+
chrome?(session) && chromedriver_version(session) < Gem::Version.new(version)
|
70
|
+
end
|
71
|
+
|
72
|
+
def selenium?(session)
|
73
|
+
session.driver.is_a? Capybara::Selenium::Driver
|
74
|
+
end
|
75
|
+
|
76
|
+
def selenium_lt?(version, session)
|
77
|
+
selenium?(session) &&
|
78
|
+
Gem::Version.new(::Selenium::WebDriver::VERSION) < Gem::Version.new(version)
|
33
79
|
end
|
34
80
|
|
35
81
|
def edge?(session)
|
82
|
+
browser_name(session).to_s.start_with?('edge')
|
83
|
+
end
|
84
|
+
|
85
|
+
def legacy_edge?(session)
|
36
86
|
browser_name(session) == :edge
|
37
87
|
end
|
38
88
|
|
89
|
+
def edge_lt?(version, session)
|
90
|
+
edge?(session) && (chrome_version(session) < version)
|
91
|
+
end
|
92
|
+
|
93
|
+
def edge_gte?(version, session)
|
94
|
+
edge?(session) && (chrome_version(session) >= version)
|
95
|
+
end
|
96
|
+
|
39
97
|
def ie?(session)
|
40
98
|
%i[internet_explorer ie].include?(browser_name(session))
|
41
99
|
end
|
42
100
|
|
101
|
+
def safari?(session)
|
102
|
+
%i[safari Safari Safari_Technology_Preview].include?(browser_name(session))
|
103
|
+
end
|
104
|
+
|
43
105
|
def browser_name(session)
|
44
106
|
session.driver.browser.browser if session.respond_to?(:driver)
|
45
107
|
end
|
@@ -47,11 +109,24 @@ module Capybara
|
|
47
109
|
def remote?(session)
|
48
110
|
session.driver.browser.is_a? ::Selenium::WebDriver::Remote::Driver
|
49
111
|
end
|
112
|
+
|
113
|
+
def self.log_selenium_driver_version(mod)
|
114
|
+
mod = mod::Service if ::Selenium::WebDriver::Service.respond_to? :driver_path
|
115
|
+
path = mod.driver_path
|
116
|
+
path = path.call if path.respond_to? :call
|
117
|
+
$stdout.puts `#{path.gsub(' ', '\ ')} --version` if path
|
118
|
+
end
|
50
119
|
end
|
51
120
|
end
|
52
121
|
|
53
122
|
RSpec.configure do |config|
|
54
123
|
Capybara::SpecHelper.configure(config)
|
124
|
+
config.expect_with :rspec do |expectations|
|
125
|
+
expectations.syntax = :expect
|
126
|
+
end
|
127
|
+
config.mock_with :rspec do |mocks|
|
128
|
+
mocks.verify_partial_doubles = true
|
129
|
+
end
|
55
130
|
config.filter_run_including focus_: true unless ENV['CI']
|
56
131
|
config.run_all_when_everything_filtered = true
|
57
132
|
config.after(:suite) { SeleniumStatistics.print_results }
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'capybara/node/whitespace_normalizer'
|
5
|
+
|
6
|
+
RSpec.describe Capybara::Node::WhitespaceNormalizer do
|
7
|
+
subject(:normalizer) do
|
8
|
+
klass = Class.new do
|
9
|
+
include Capybara::Node::WhitespaceNormalizer
|
10
|
+
end
|
11
|
+
|
12
|
+
klass.new
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:text_needing_correction) do
|
16
|
+
<<~TEXT
|
17
|
+
Some #{described_class::NON_BREAKING_SPACE}text
|
18
|
+
#{described_class::RIGHT_TO_LEFT_MARK}
|
19
|
+
#{described_class::ZERO_WIDTH_SPACE * 30}
|
20
|
+
#{described_class::LEFT_TO_RIGHT_MARK}
|
21
|
+
Here
|
22
|
+
TEXT
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#normalize_spacing' do
|
26
|
+
it 'does nothing to text not containing special characters' do
|
27
|
+
expect(normalizer.normalize_spacing('text')).to eq('text')
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'compresses excess breaking spacing' do
|
31
|
+
expect(
|
32
|
+
normalizer.normalize_spacing(text_needing_correction)
|
33
|
+
).to eq('Some text Here')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#normalize_visible_spacing' do
|
38
|
+
it 'does nothing to text not containing special characters' do
|
39
|
+
expect(normalizer.normalize_visible_spacing('text')).to eq('text')
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'compresses excess breaking visible spacing' do
|
43
|
+
expect(
|
44
|
+
normalizer.normalize_visible_spacing(text_needing_correction)
|
45
|
+
).to eq <<~TEXT.chomp
|
46
|
+
Some text
|
47
|
+
#{described_class::RIGHT_TO_LEFT_MARK}
|
48
|
+
#{described_class::ZERO_WIDTH_SPACE * 30}
|
49
|
+
#{described_class::LEFT_TO_RIGHT_MARK}
|
50
|
+
Here
|
51
|
+
TEXT
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/spec/xpath_builder_spec.rb
CHANGED
@@ -2,9 +2,10 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
+
# rubocop:disable RSpec/InstanceVariable
|
5
6
|
RSpec.describe Capybara::Selector::XPathBuilder do
|
6
7
|
let :builder do
|
7
|
-
|
8
|
+
described_class.new(@xpath)
|
8
9
|
end
|
9
10
|
|
10
11
|
context 'add_attribute_conditions' do
|
@@ -89,3 +90,4 @@ RSpec.describe Capybara::Selector::XPathBuilder do
|
|
89
90
|
end
|
90
91
|
end
|
91
92
|
end
|
93
|
+
# rubocop:enable RSpec/InstanceVariable
|