capybara 2.5.0 → 2.18.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 +5 -5
- data/.yard/templates_custom/default/class/html/selectors.erb +38 -0
- data/.yard/templates_custom/default/class/html/setup.rb +17 -0
- data/.yard/yard_extensions.rb +78 -0
- data/.yardopts +1 -0
- data/History.md +413 -10
- data/License.txt +1 -1
- data/README.md +237 -130
- data/lib/capybara/config.rb +132 -0
- data/lib/capybara/cucumber.rb +3 -1
- data/lib/capybara/driver/base.rb +27 -6
- data/lib/capybara/driver/node.rb +14 -5
- data/lib/capybara/dsl.rb +2 -3
- data/lib/capybara/helpers.rb +13 -65
- data/lib/capybara/minitest/spec.rb +177 -0
- data/lib/capybara/minitest.rb +278 -0
- data/lib/capybara/node/actions.rb +180 -24
- data/lib/capybara/node/base.rb +17 -5
- data/lib/capybara/node/document.rb +5 -0
- data/lib/capybara/node/document_matchers.rb +15 -14
- data/lib/capybara/node/element.rb +55 -7
- data/lib/capybara/node/finders.rb +179 -67
- data/lib/capybara/node/matchers.rb +301 -105
- data/lib/capybara/node/simple.rb +15 -4
- data/lib/capybara/queries/ancestor_query.rb +25 -0
- data/lib/capybara/queries/base_query.rb +69 -3
- data/lib/capybara/queries/current_path_query.rb +17 -8
- data/lib/capybara/queries/match_query.rb +19 -0
- data/lib/capybara/queries/selector_query.rb +251 -0
- data/lib/capybara/queries/sibling_query.rb +25 -0
- data/lib/capybara/queries/text_query.rb +67 -16
- data/lib/capybara/queries/title_query.rb +4 -2
- data/lib/capybara/query.rb +3 -131
- data/lib/capybara/rack_test/browser.rb +14 -5
- data/lib/capybara/rack_test/css_handlers.rb +1 -0
- data/lib/capybara/rack_test/driver.rb +15 -8
- data/lib/capybara/rack_test/form.rb +34 -12
- data/lib/capybara/rack_test/node.rb +29 -12
- data/lib/capybara/rails.rb +3 -3
- data/lib/capybara/result.rb +104 -9
- data/lib/capybara/rspec/compound.rb +95 -0
- data/lib/capybara/rspec/features.rb +17 -6
- data/lib/capybara/rspec/matcher_proxies.rb +45 -0
- data/lib/capybara/rspec/matchers.rb +199 -80
- data/lib/capybara/rspec.rb +4 -2
- data/lib/capybara/selector/css.rb +30 -0
- data/lib/capybara/selector/filter.rb +20 -0
- data/lib/capybara/selector/filter_set.rb +74 -0
- data/lib/capybara/selector/filters/base.rb +33 -0
- data/lib/capybara/selector/filters/expression_filter.rb +40 -0
- data/lib/capybara/selector/filters/node_filter.rb +27 -0
- data/lib/capybara/selector/selector.rb +276 -0
- data/lib/capybara/selector.rb +452 -157
- data/lib/capybara/selenium/driver.rb +282 -81
- data/lib/capybara/selenium/node.rb +144 -46
- data/lib/capybara/server.rb +59 -16
- data/lib/capybara/session/config.rb +114 -0
- data/lib/capybara/session/matchers.rb +29 -19
- data/lib/capybara/session.rb +378 -143
- data/lib/capybara/spec/fixtures/no_extension +1 -0
- data/lib/capybara/spec/public/jquery-ui.js +13 -791
- data/lib/capybara/spec/public/jquery.js +4 -9045
- data/lib/capybara/spec/public/test.js +45 -11
- data/lib/capybara/spec/session/accept_alert_spec.rb +30 -7
- data/lib/capybara/spec/session/accept_confirm_spec.rb +14 -2
- data/lib/capybara/spec/session/accept_prompt_spec.rb +35 -6
- data/lib/capybara/spec/session/all_spec.rb +45 -32
- data/lib/capybara/spec/session/ancestor_spec.rb +85 -0
- data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +110 -0
- data/lib/capybara/spec/session/assert_current_path.rb +15 -2
- data/lib/capybara/spec/session/assert_selector.rb +29 -28
- data/lib/capybara/spec/session/assert_text.rb +59 -20
- data/lib/capybara/spec/session/assert_title.rb +25 -11
- data/lib/capybara/spec/session/attach_file_spec.rb +42 -4
- data/lib/capybara/spec/session/body_spec.rb +1 -0
- data/lib/capybara/spec/session/check_spec.rb +90 -14
- data/lib/capybara/spec/session/choose_spec.rb +31 -5
- data/lib/capybara/spec/session/click_button_spec.rb +20 -9
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +15 -9
- data/lib/capybara/spec/session/click_link_spec.rb +39 -15
- data/lib/capybara/spec/session/current_scope_spec.rb +2 -1
- data/lib/capybara/spec/session/current_url_spec.rb +12 -3
- data/lib/capybara/spec/session/dismiss_confirm_spec.rb +6 -5
- data/lib/capybara/spec/session/dismiss_prompt_spec.rb +4 -3
- data/lib/capybara/spec/session/element/assert_match_selector.rb +36 -0
- data/lib/capybara/spec/session/element/match_css_spec.rb +23 -0
- data/lib/capybara/spec/session/element/match_xpath_spec.rb +23 -0
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +106 -0
- data/lib/capybara/spec/session/evaluate_async_script_spec.rb +22 -0
- data/lib/capybara/spec/session/evaluate_script_spec.rb +23 -1
- data/lib/capybara/spec/session/execute_script_spec.rb +22 -3
- data/lib/capybara/spec/session/fill_in_spec.rb +50 -32
- data/lib/capybara/spec/session/find_button_spec.rb +43 -2
- data/lib/capybara/spec/session/find_by_id_spec.rb +3 -2
- data/lib/capybara/spec/session/find_field_spec.rb +42 -6
- data/lib/capybara/spec/session/find_link_spec.rb +22 -3
- data/lib/capybara/spec/session/find_spec.rb +103 -57
- data/lib/capybara/spec/session/first_spec.rb +34 -18
- data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +103 -0
- data/lib/capybara/spec/session/{within_frame_spec.rb → frame/within_frame_spec.rb} +44 -2
- data/lib/capybara/spec/session/go_back_spec.rb +2 -1
- data/lib/capybara/spec/session/go_forward_spec.rb +2 -1
- data/lib/capybara/spec/session/has_all_selectors_spec.rb +69 -0
- data/lib/capybara/spec/session/has_button_spec.rb +17 -8
- data/lib/capybara/spec/session/has_css_spec.rb +85 -73
- data/lib/capybara/spec/session/has_current_path_spec.rb +91 -7
- data/lib/capybara/spec/session/has_field_spec.rb +93 -58
- data/lib/capybara/spec/session/has_link_spec.rb +9 -8
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +76 -0
- data/lib/capybara/spec/session/has_select_spec.rb +159 -59
- data/lib/capybara/spec/session/has_selector_spec.rb +64 -28
- data/lib/capybara/spec/session/has_table_spec.rb +1 -0
- data/lib/capybara/spec/session/has_text_spec.rb +27 -12
- data/lib/capybara/spec/session/has_title_spec.rb +22 -4
- data/lib/capybara/spec/session/has_xpath_spec.rb +32 -29
- data/lib/capybara/spec/session/headers.rb +2 -1
- data/lib/capybara/spec/session/html_spec.rb +4 -3
- data/lib/capybara/spec/session/node_spec.rb +198 -38
- data/lib/capybara/spec/session/refresh_spec.rb +28 -0
- data/lib/capybara/spec/session/reset_session_spec.rb +46 -5
- data/lib/capybara/spec/session/response_code.rb +2 -1
- data/lib/capybara/spec/session/save_and_open_page_spec.rb +1 -0
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +6 -5
- data/lib/capybara/spec/session/save_page_spec.rb +34 -2
- data/lib/capybara/spec/session/save_screenshot_spec.rb +31 -1
- data/lib/capybara/spec/session/screenshot_spec.rb +4 -2
- data/lib/capybara/spec/session/select_spec.rb +34 -32
- data/lib/capybara/spec/session/selectors_spec.rb +65 -0
- data/lib/capybara/spec/session/sibling_spec.rb +52 -0
- data/lib/capybara/spec/session/text_spec.rb +4 -4
- data/lib/capybara/spec/session/title_spec.rb +2 -1
- data/lib/capybara/spec/session/uncheck_spec.rb +42 -2
- data/lib/capybara/spec/session/unselect_spec.rb +17 -16
- data/lib/capybara/spec/session/visit_spec.rb +77 -2
- data/lib/capybara/spec/session/window/become_closed_spec.rb +12 -11
- data/lib/capybara/spec/session/window/current_window_spec.rb +1 -0
- data/lib/capybara/spec/session/window/open_new_window_spec.rb +1 -0
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +16 -11
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +7 -4
- data/lib/capybara/spec/session/window/window_spec.rb +36 -29
- data/lib/capybara/spec/session/window/windows_spec.rb +1 -0
- data/lib/capybara/spec/session/window/within_window_spec.rb +31 -7
- data/lib/capybara/spec/session/within_spec.rb +14 -6
- data/lib/capybara/spec/spec_helper.rb +37 -4
- data/lib/capybara/spec/test_app.rb +15 -3
- data/lib/capybara/spec/views/buttons.erb +1 -0
- data/lib/capybara/spec/views/fieldsets.erb +2 -1
- data/lib/capybara/spec/views/form.erb +169 -9
- data/lib/capybara/spec/views/frame_child.erb +10 -2
- data/lib/capybara/spec/views/frame_one.erb +2 -1
- data/lib/capybara/spec/views/frame_parent.erb +3 -2
- data/lib/capybara/spec/views/frame_two.erb +2 -1
- data/lib/capybara/spec/views/header_links.erb +1 -0
- data/lib/capybara/spec/views/host_links.erb +1 -0
- data/lib/capybara/spec/views/initial_alert.erb +10 -0
- data/lib/capybara/spec/views/path.erb +1 -0
- data/lib/capybara/spec/views/popup_one.erb +1 -0
- data/lib/capybara/spec/views/popup_two.erb +1 -0
- data/lib/capybara/spec/views/postback.erb +2 -1
- data/lib/capybara/spec/views/tables.erb +1 -0
- data/lib/capybara/spec/views/with_base_tag.erb +1 -0
- data/lib/capybara/spec/views/with_count.erb +2 -1
- data/lib/capybara/spec/views/with_fixed_header_footer.erb +17 -0
- data/lib/capybara/spec/views/with_hover.erb +7 -1
- data/lib/capybara/spec/views/with_html.erb +40 -2
- data/lib/capybara/spec/views/with_html_entities.erb +1 -0
- data/lib/capybara/spec/views/with_js.erb +32 -1
- data/lib/capybara/spec/views/with_scope.erb +1 -0
- data/lib/capybara/spec/views/with_simple_html.erb +2 -1
- data/lib/capybara/spec/views/with_slow_unload.erb +17 -0
- data/lib/capybara/spec/views/with_title.erb +2 -1
- data/lib/capybara/spec/views/with_unload_alert.erb +14 -0
- data/lib/capybara/spec/views/with_windows.erb +7 -0
- data/lib/capybara/spec/views/within_frames.erb +3 -2
- data/lib/capybara/version.rb +2 -1
- data/lib/capybara/window.rb +20 -3
- data/lib/capybara.rb +189 -93
- data/spec/basic_node_spec.rb +7 -6
- data/spec/capybara_spec.rb +90 -4
- data/spec/dsl_spec.rb +3 -1
- data/spec/filter_set_spec.rb +28 -0
- data/spec/fixtures/capybara.csv +1 -0
- data/spec/fixtures/selenium_driver_rspec_failure.rb +5 -1
- data/spec/fixtures/selenium_driver_rspec_success.rb +5 -1
- data/spec/minitest_spec.rb +130 -0
- data/spec/minitest_spec_spec.rb +135 -0
- data/spec/per_session_config_spec.rb +67 -0
- data/spec/rack_test_spec.rb +50 -7
- data/spec/result_spec.rb +76 -0
- data/spec/rspec/features_spec.rb +21 -8
- data/spec/rspec/scenarios_spec.rb +21 -0
- data/spec/rspec/{matchers_spec.rb → shared_spec_matchers.rb} +160 -54
- data/spec/rspec/views_spec.rb +5 -0
- data/spec/rspec_matchers_spec.rb +46 -0
- data/spec/rspec_spec.rb +79 -1
- data/spec/selector_spec.rb +199 -0
- data/spec/selenium_spec_chrome.rb +54 -9
- data/spec/selenium_spec_firefox.rb +68 -0
- data/spec/selenium_spec_marionette.rb +127 -0
- data/spec/server_spec.rb +102 -14
- data/spec/session_spec.rb +54 -0
- data/spec/shared_selenium_session.rb +215 -0
- data/spec/spec_helper.rb +7 -0
- metadata +140 -15
- data/spec/selenium_spec.rb +0 -128
data/spec/rspec_spec.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'spec_helper'
|
|
2
3
|
|
|
3
4
|
RSpec.describe 'capybara/rspec', :type => :feature do
|
|
@@ -6,6 +7,10 @@ RSpec.describe 'capybara/rspec', :type => :feature do
|
|
|
6
7
|
expect(page.body).to include('Another World')
|
|
7
8
|
end
|
|
8
9
|
|
|
10
|
+
it "should include RSpec matcher proxies" do
|
|
11
|
+
expect(self.class.ancestors).to include Capybara::RSpecMatcherProxies
|
|
12
|
+
end
|
|
13
|
+
|
|
9
14
|
context "resetting session" do
|
|
10
15
|
it "sets a cookie in one example..." do
|
|
11
16
|
visit('/set_cookie')
|
|
@@ -28,13 +33,86 @@ RSpec.describe 'capybara/rspec', :type => :feature do
|
|
|
28
33
|
end
|
|
29
34
|
end
|
|
30
35
|
|
|
31
|
-
it "switches to the javascript driver when giving it as metadata", :
|
|
36
|
+
it "switches to the javascript driver when giving it as metadata", js: true do
|
|
32
37
|
expect(Capybara.current_driver).to eq(Capybara.javascript_driver)
|
|
33
38
|
end
|
|
34
39
|
|
|
35
40
|
it "switches to the given driver when giving it as metadata", :driver => :culerity do
|
|
36
41
|
expect(Capybara.current_driver).to eq(:culerity)
|
|
37
42
|
end
|
|
43
|
+
|
|
44
|
+
context "#all" do
|
|
45
|
+
it "allows access to the Capybara finder" do
|
|
46
|
+
visit('/with_html')
|
|
47
|
+
expect(all(:css, 'h2.head').size).to eq(5)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "allows access to the RSpec matcher" do
|
|
51
|
+
skip "RSpec < 3 doesn't have an `all` matcher" if rspec2?
|
|
52
|
+
|
|
53
|
+
visit('/with_html')
|
|
54
|
+
expect(["test1", "test2"]).to all(be_a(String))
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
context "#within" do
|
|
59
|
+
it "allows access to the Capybara scoper" do
|
|
60
|
+
visit('/with_html')
|
|
61
|
+
expect do
|
|
62
|
+
within(:css, "#does_not_exist") { click_link "Go to simple" }
|
|
63
|
+
end.to raise_error(Capybara::ElementNotFound)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "allows access to the RSpec matcher" do
|
|
67
|
+
skip "RSpec version doesn't have a 'within' matcher" unless ::RSpec::Matchers.instance_methods.include?(:within)
|
|
68
|
+
visit('/with_html')
|
|
69
|
+
# This reads terribly, but must call #within
|
|
70
|
+
expect(find(:css, 'span.number').text.to_i).to within(1).of(41)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
RSpec.describe 'capybara/rspec', :type => :other do
|
|
76
|
+
context "when RSpec::Matchers is included after Capybara::DSL" do
|
|
77
|
+
before do
|
|
78
|
+
class DSL_MatchersTest
|
|
79
|
+
include Capybara::DSL
|
|
80
|
+
include RSpec::Matchers
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
@test_class_instance = DSL_MatchersTest.new
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
context "#all" do
|
|
87
|
+
it "allows access to the Capybara finder" do
|
|
88
|
+
@test_class_instance.visit('/with_html')
|
|
89
|
+
expect(@test_class_instance.all(:css, 'h2.head').size).to eq(5)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "allows access to the RSpec matcher" do
|
|
93
|
+
skip "RSpec < 3 doesn't have an `all` matcher" if rspec2?
|
|
94
|
+
|
|
95
|
+
@test_class_instance.visit('/with_html')
|
|
96
|
+
expect(["test1", "test2"]).to @test_class_instance.all(be_a(String))
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
context "#within" do
|
|
101
|
+
it "allows access to the Capybara scoper" do
|
|
102
|
+
@test_class_instance.visit('/with_html')
|
|
103
|
+
expect do
|
|
104
|
+
@test_class_instance.within(:css, "#does_not_exist") { @test_class_instance.click_link "Go to simple" }
|
|
105
|
+
end.to raise_error(Capybara::ElementNotFound)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "allows access to the RSpec matcher" do
|
|
109
|
+
skip "RSpec version doesn't have a 'within' matcher" unless ::RSpec::Matchers.instance_methods.include?(:within)
|
|
110
|
+
@test_class_instance.visit('/with_html')
|
|
111
|
+
# This reads terribly, but must call #within
|
|
112
|
+
expect(@test_class_instance.find(:css, 'span.number').text.to_i).to @test_class_instance.within(1).of(41)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
38
116
|
end
|
|
39
117
|
|
|
40
118
|
RSpec.describe 'capybara/rspec', :type => :other do
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'spec_helper'
|
|
3
|
+
|
|
4
|
+
RSpec.describe Capybara do
|
|
5
|
+
describe 'Selectors' do
|
|
6
|
+
let :string do
|
|
7
|
+
Capybara.string <<-STRING
|
|
8
|
+
<html>
|
|
9
|
+
<head>
|
|
10
|
+
<title>selectors</title>
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<div class="a" id="page">
|
|
14
|
+
<div class="b" id="content">
|
|
15
|
+
<h1 class="a">Totally awesome</h1>
|
|
16
|
+
<p>Yes it is</p>
|
|
17
|
+
</div>
|
|
18
|
+
<p class="b">Some Content</p>
|
|
19
|
+
<p class="b"></p>
|
|
20
|
+
</div>
|
|
21
|
+
<div id="#special">
|
|
22
|
+
</div>
|
|
23
|
+
<input id="2checkbox" class="2checkbox" type="checkbox"/>
|
|
24
|
+
<input type="radio"/>
|
|
25
|
+
<label for="my_text_input">My Text Input</label>
|
|
26
|
+
<input type="text" name="form[my_text_input]" placeholder="my text" id="my_text_input"/>
|
|
27
|
+
<input type="file" id="file" class=".special file"/>
|
|
28
|
+
<input type="hidden" id="hidden_field" value="this is hidden"/>
|
|
29
|
+
<a href="#">link</a>
|
|
30
|
+
<fieldset></fieldset>
|
|
31
|
+
<select id="select">
|
|
32
|
+
<option value="a">A</option>
|
|
33
|
+
<option value="b" disabled>B</option>
|
|
34
|
+
<option value="c" selected>C</option>
|
|
35
|
+
</select>
|
|
36
|
+
<table>
|
|
37
|
+
<tr><td></td></tr>
|
|
38
|
+
</table
|
|
39
|
+
</body>
|
|
40
|
+
</html>
|
|
41
|
+
STRING
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
before do
|
|
45
|
+
Capybara.add_selector :custom_selector do
|
|
46
|
+
css { |css_class| "div.#{css_class}" }
|
|
47
|
+
filter(:not_empty, boolean: true, default: true, skip_if: :all) { |node, value| value ^ (node.text == '') }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
Capybara.add_selector :custom_css_selector do
|
|
51
|
+
css { |selector| selector }
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe "adding a selector" do
|
|
56
|
+
it "can set default visiblity" do
|
|
57
|
+
Capybara.add_selector :hidden_field do
|
|
58
|
+
visible :hidden
|
|
59
|
+
css { |sel| 'input[type="hidden"]' }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
expect(string).to have_no_css('input[type="hidden"]')
|
|
63
|
+
expect(string).to have_selector(:hidden_field)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
describe "modify_selector" do
|
|
68
|
+
it "allows modifying a selector" do
|
|
69
|
+
el = string.find(:custom_selector, 'a')
|
|
70
|
+
expect(el.tag_name).to eq 'div'
|
|
71
|
+
Capybara.modify_selector :custom_selector do
|
|
72
|
+
css { |css_class| "h1.#{css_class}" }
|
|
73
|
+
end
|
|
74
|
+
el = string.find(:custom_selector, 'a')
|
|
75
|
+
expect(el.tag_name).to eq 'h1'
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "doesn't change existing filters" do
|
|
79
|
+
Capybara.modify_selector :custom_selector do
|
|
80
|
+
css { |css_class| "p.#{css_class}"}
|
|
81
|
+
end
|
|
82
|
+
expect(string).to have_selector(:custom_selector, 'b', count: 1)
|
|
83
|
+
expect(string).to have_selector(:custom_selector, 'b', not_empty: false, count: 1)
|
|
84
|
+
expect(string).to have_selector(:custom_selector, 'b', not_empty: :all, count: 2)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
describe "builtin selectors" do
|
|
89
|
+
context "when locator is nil" do
|
|
90
|
+
it "devolves to just finding element types" do
|
|
91
|
+
selectors = {
|
|
92
|
+
field: ".//*[self::input | self::textarea | self::select][not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')]",
|
|
93
|
+
fieldset: ".//fieldset",
|
|
94
|
+
link: ".//a[./@href]",
|
|
95
|
+
link_or_button: ".//a[./@href] | .//input[./@type = 'submit' or ./@type = 'reset' or ./@type = 'image' or ./@type = 'button'] | .//button" ,
|
|
96
|
+
fillable_field: ".//*[self::input | self::textarea][not(./@type = 'submit' or ./@type = 'image' or ./@type = 'radio' or ./@type = 'checkbox' or ./@type = 'hidden' or ./@type = 'file')]",
|
|
97
|
+
radio_button: ".//input[./@type = 'radio']",
|
|
98
|
+
checkbox: ".//input[./@type = 'checkbox']",
|
|
99
|
+
select: ".//select",
|
|
100
|
+
option: ".//option",
|
|
101
|
+
file_field: ".//input[./@type = 'file']",
|
|
102
|
+
table: ".//table"
|
|
103
|
+
}
|
|
104
|
+
selectors.each do |selector, xpath|
|
|
105
|
+
results = string.all(selector,nil).to_a.map(&:native)
|
|
106
|
+
expect(results.size).to be > 0
|
|
107
|
+
expect(results).to eq string.all(:xpath, xpath).to_a.map(&:native)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
context "with :id option" do
|
|
113
|
+
it "works with compound css selectors" do
|
|
114
|
+
expect(string.all(:custom_css_selector, "div, h1", id: 'page').size).to eq 1
|
|
115
|
+
expect(string.all(:custom_css_selector, "h1, div", id: 'page').size).to eq 1
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it "works with 'special' characters" do
|
|
119
|
+
skip "We support old Nokogiris but they have their limits" if Gem::Version.new(Nokogiri::VERSION) < Gem::Version.new('1.6.8')
|
|
120
|
+
expect(string.find(:custom_css_selector, "div", id: "#special")[:id]).to eq '#special'
|
|
121
|
+
expect(string.find(:custom_css_selector, "input", id: "2checkbox")[:id]).to eq '2checkbox'
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
context "with :class option" do
|
|
126
|
+
it "works with compound css selectors" do
|
|
127
|
+
expect(string.all(:custom_css_selector, "div, h1", class: 'a').size).to eq 2
|
|
128
|
+
expect(string.all(:custom_css_selector, "h1, div", class: 'a').size).to eq 2
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it "works with 'special' characters" do
|
|
132
|
+
skip "We support old Nokogiris but they have their limits" if Gem::Version.new(Nokogiri::VERSION) < Gem::Version.new('1.6.8')
|
|
133
|
+
expect(string.find(:custom_css_selector, "input", class: ".special")[:id]).to eq 'file'
|
|
134
|
+
expect(string.find(:custom_css_selector, "input", class: "2checkbox")[:id]).to eq '2checkbox'
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# :css, :xpath, :id, :field, :fieldset, :link, :button, :link_or_button, :fillable_field, :radio_button, :checkbox, :select,
|
|
139
|
+
# :option, :file_field, :label, :table, :frame
|
|
140
|
+
|
|
141
|
+
describe ":css selector" do
|
|
142
|
+
it "finds by CSS locator" do
|
|
143
|
+
expect(string.find(:css, "input#my_text_input")[:name]).to eq 'form[my_text_input]'
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
describe ":xpath selector" do
|
|
148
|
+
it "finds by XPath locator" do
|
|
149
|
+
expect(string.find(:xpath, './/input[@id="my_text_input"]')[:name]).to eq 'form[my_text_input]'
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
describe ":id selector" do
|
|
154
|
+
it "finds by locator" do
|
|
155
|
+
expect(string.find(:id, "my_text_input")[:name]).to eq 'form[my_text_input]'
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
describe ":field selector" do
|
|
160
|
+
it "finds by locator" do
|
|
161
|
+
expect(string.find(:field, 'My Text Input')[:id]).to eq 'my_text_input'
|
|
162
|
+
expect(string.find(:field, 'my_text_input')[:id]).to eq 'my_text_input'
|
|
163
|
+
expect(string.find(:field, 'form[my_text_input]')[:id]).to eq 'my_text_input'
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it "finds by id" do
|
|
167
|
+
expect(string.find(:field, id: 'my_text_input')[:name]).to eq 'form[my_text_input]'
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it "finds by name" do
|
|
171
|
+
expect(string.find(:field, name: 'form[my_text_input]')[:id]).to eq 'my_text_input'
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it "finds by placeholder" do
|
|
175
|
+
expect(string.find(:field, placeholder: 'my text')[:id]).to eq 'my_text_input'
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
it "finds by type" do
|
|
179
|
+
expect(string.find(:field, type: 'file')[:id]).to eq 'file'
|
|
180
|
+
expect(string.find(:field, type: 'select')[:id]).to eq 'select'
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
describe ":option selector" do
|
|
185
|
+
it "finds disabled options" do
|
|
186
|
+
expect(string.find(:option, disabled: true).value).to eq 'b'
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
it "finds selected options" do
|
|
190
|
+
expect(string.find(:option, selected: true).value).to eq 'c'
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
it "finds not selected and not disabled options" do
|
|
194
|
+
expect(string.find(:option, disabled: false, selected: false).value).to eq 'a'
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
end
|
|
@@ -1,17 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'spec_helper'
|
|
2
3
|
require 'selenium-webdriver'
|
|
4
|
+
require 'shared_selenium_session'
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
CHROME_DRIVER = if ENV['HEADLESS'] then :selenium_chrome_headless else :selenium_chrome end
|
|
7
|
+
|
|
8
|
+
# if ENV['HEADLESS'] && ENV['TRAVIS']
|
|
9
|
+
# Selenium::WebDriver::Chrome.path='/usr/bin/google-chrome-beta'
|
|
10
|
+
# end
|
|
11
|
+
|
|
12
|
+
Capybara.register_driver :selenium_chrome_clear_storage do |app|
|
|
13
|
+
chrome_options = {
|
|
14
|
+
browser: :chrome,
|
|
15
|
+
options: ::Selenium::WebDriver::Chrome::Options.new()
|
|
16
|
+
}
|
|
17
|
+
chrome_options[:options].args << 'headless' if ENV['HEADLESS']
|
|
18
|
+
Capybara::Selenium::Driver.new(app, chrome_options.merge(clear_local_storage: true, clear_session_storage: true))
|
|
7
19
|
end
|
|
8
20
|
|
|
9
21
|
module TestSessions
|
|
10
|
-
Chrome = Capybara::Session.new(
|
|
22
|
+
Chrome = Capybara::Session.new(CHROME_DRIVER, TestApp)
|
|
11
23
|
end
|
|
12
24
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
25
|
+
skipped_tests = [:response_headers, :status_code, :trigger]
|
|
26
|
+
# skip window tests when headless for now - closing a window not supported by chromedriver/chrome
|
|
27
|
+
skipped_tests << :windows if ENV['TRAVIS'] && (ENV['SKIP_WINDOW'] || ENV['HEADLESS'])
|
|
28
|
+
|
|
29
|
+
Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_DRIVER.to_s, capybara_skip: skipped_tests
|
|
30
|
+
|
|
31
|
+
RSpec.describe "Capybara::Session with chrome" do
|
|
32
|
+
include Capybara::SpecHelper
|
|
33
|
+
include_examples "Capybara::Session", TestSessions::Chrome, CHROME_DRIVER
|
|
34
|
+
|
|
35
|
+
context "storage" do
|
|
36
|
+
describe "#reset!" do
|
|
37
|
+
it "does not clear either storage by default" do
|
|
38
|
+
@session = TestSessions::Chrome
|
|
39
|
+
@session.visit('/with_js')
|
|
40
|
+
@session.find(:css, '#set-storage').click
|
|
41
|
+
@session.reset!
|
|
42
|
+
@session.visit('/with_js')
|
|
43
|
+
# expect(@session.driver.browser.local_storage.keys).not_to be_empty
|
|
44
|
+
# expect(@session.driver.browser.session_storage.keys).not_to be_empty
|
|
45
|
+
expect(@session.evaluate_script('Object.keys(localStorage)')).not_to be_empty
|
|
46
|
+
expect(@session.evaluate_script('Object.keys(sessionStorage)')).not_to be_empty
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "clears storage when set" do
|
|
50
|
+
@session = Capybara::Session.new(:selenium_chrome_clear_storage, TestApp)
|
|
51
|
+
@session.visit('/with_js')
|
|
52
|
+
@session.find(:css, '#set-storage').click
|
|
53
|
+
@session.reset!
|
|
54
|
+
@session.visit('/with_js')
|
|
55
|
+
# expect(@session.driver.browser.local_storage.keys).to be_empty
|
|
56
|
+
# expect(@session.driver.browser.session_storage.keys).to be_empty
|
|
57
|
+
expect(@session.evaluate_script('Object.keys(localStorage)')).to be_empty
|
|
58
|
+
expect(@session.evaluate_script('Object.keys(sessionStorage)')).to be_empty
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'spec_helper'
|
|
3
|
+
require "selenium-webdriver"
|
|
4
|
+
require 'shared_selenium_session'
|
|
5
|
+
require 'rspec/shared_spec_matchers'
|
|
6
|
+
|
|
7
|
+
Capybara.register_driver :selenium_firefox do |app|
|
|
8
|
+
Capybara::Selenium::Driver.new(
|
|
9
|
+
app,
|
|
10
|
+
browser: :firefox,
|
|
11
|
+
desired_capabilities: Selenium::WebDriver::Remote::Capabilities.firefox(marionette: false)
|
|
12
|
+
)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
Capybara.register_driver :selenium_firefox_cant_clear_storage do |app|
|
|
16
|
+
Capybara::Selenium::Driver.new(
|
|
17
|
+
app,
|
|
18
|
+
browser: :firefox,
|
|
19
|
+
desired_capabilities: Selenium::WebDriver::Remote::Capabilities.firefox(marionette: false),
|
|
20
|
+
clear_local_storage: true,
|
|
21
|
+
clear_session_storage: true
|
|
22
|
+
)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
module TestSessions
|
|
26
|
+
Selenium = Capybara::Session.new(:selenium_firefox, TestApp)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
skipped_tests = [
|
|
30
|
+
:response_headers,
|
|
31
|
+
:status_code,
|
|
32
|
+
:trigger
|
|
33
|
+
]
|
|
34
|
+
skipped_tests << :windows if ENV['TRAVIS'] && ENV['SKIP_WINDOW']
|
|
35
|
+
|
|
36
|
+
Capybara::SpecHelper.run_specs TestSessions::Selenium, "selenium", capybara_skip: skipped_tests
|
|
37
|
+
|
|
38
|
+
RSpec.describe "Capybara::Session with legacy firefox" do
|
|
39
|
+
include Capybara::SpecHelper
|
|
40
|
+
include_examples "Capybara::Session", TestSessions::Selenium, :selenium_firefox
|
|
41
|
+
include_examples Capybara::RSpecMatchers, TestSessions::Selenium, :selenium_firefox
|
|
42
|
+
|
|
43
|
+
context "storage" do
|
|
44
|
+
it "warns storage clearing isn't available" do
|
|
45
|
+
@session = Capybara::Session.new(:selenium_firefox_cant_clear_storage, TestApp)
|
|
46
|
+
expect_any_instance_of(Kernel).to receive(:warn).with('sessionStorage clear requested but is not available for this driver')
|
|
47
|
+
expect_any_instance_of(Kernel).to receive(:warn).with('localStorage clear requested but is not available for this driver')
|
|
48
|
+
@session.visit('/')
|
|
49
|
+
@session.reset!
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
RSpec.describe Capybara::Selenium::Driver do
|
|
55
|
+
before do
|
|
56
|
+
@driver = Capybara::Selenium::Driver.new(TestApp, browser: :firefox, desired_capabilities: Selenium::WebDriver::Remote::Capabilities.firefox(marionette: false))
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
describe '#quit' do
|
|
60
|
+
it "should reset browser when quit" do
|
|
61
|
+
expect(@driver.browser).to be
|
|
62
|
+
@driver.quit
|
|
63
|
+
#access instance variable directly so we don't create a new browser instance
|
|
64
|
+
expect(@driver.instance_variable_get(:@browser)).to be_nil
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'spec_helper'
|
|
3
|
+
require "selenium-webdriver"
|
|
4
|
+
require 'shared_selenium_session'
|
|
5
|
+
require 'rspec/shared_spec_matchers'
|
|
6
|
+
|
|
7
|
+
browser_options = ::Selenium::WebDriver::Firefox::Options.new()
|
|
8
|
+
browser_options.args << '--headless' if ENV['HEADLESS']
|
|
9
|
+
browser_options.add_preference 'dom.file.createInChild', true
|
|
10
|
+
# browser_options.add_option("log", {"level": "trace"})
|
|
11
|
+
|
|
12
|
+
Capybara.register_driver :selenium_marionette do |app|
|
|
13
|
+
# ::Selenium::WebDriver.logger.level = "debug"
|
|
14
|
+
Capybara::Selenium::Driver.new(
|
|
15
|
+
app,
|
|
16
|
+
browser: :firefox,
|
|
17
|
+
desired_capabilities: {marionette: true, 'moz:webdriverClick': true},
|
|
18
|
+
options: browser_options
|
|
19
|
+
# Get a trace level log from geckodriver
|
|
20
|
+
# :driver_opts => { args: ['-vv'] }
|
|
21
|
+
)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
Capybara.register_driver :selenium_marionette_clear_storage do |app|
|
|
25
|
+
Capybara::Selenium::Driver.new(
|
|
26
|
+
app,
|
|
27
|
+
browser: :firefox,
|
|
28
|
+
desired_capabilities: {marionette: true},
|
|
29
|
+
clear_local_storage: true,
|
|
30
|
+
clear_session_storage: true,
|
|
31
|
+
options: browser_options
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
module TestSessions
|
|
38
|
+
SeleniumMarionette = Capybara::Session.new(:selenium_marionette, TestApp)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
skipped_tests = [
|
|
42
|
+
:response_headers,
|
|
43
|
+
:status_code,
|
|
44
|
+
:trigger
|
|
45
|
+
]
|
|
46
|
+
skipped_tests << :windows if ENV['TRAVIS'] && ENV['SKIP_WINDOW']
|
|
47
|
+
|
|
48
|
+
Capybara::SpecHelper.run_specs TestSessions::SeleniumMarionette, "selenium", capybara_skip: skipped_tests
|
|
49
|
+
|
|
50
|
+
RSpec.describe "Capybara::Session with firefox" do
|
|
51
|
+
include Capybara::SpecHelper
|
|
52
|
+
include_examples "Capybara::Session", TestSessions::SeleniumMarionette, :selenium_marionette
|
|
53
|
+
include_examples Capybara::RSpecMatchers, TestSessions::SeleniumMarionette, :selenium_marionette
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
RSpec.describe Capybara::Selenium::Driver do
|
|
57
|
+
before do
|
|
58
|
+
@driver = Capybara::Selenium::Driver.new(TestApp, browser: :firefox, options: browser_options)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
describe '#quit' do
|
|
62
|
+
it "should reset browser when quit" do
|
|
63
|
+
expect(@driver.browser).to be
|
|
64
|
+
@driver.quit
|
|
65
|
+
#access instance variable directly so we don't create a new browser instance
|
|
66
|
+
expect(@driver.instance_variable_get(:@browser)).to be_nil
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
context "with errors" do
|
|
70
|
+
before do
|
|
71
|
+
@original_browser = @driver.browser
|
|
72
|
+
end
|
|
73
|
+
after do
|
|
74
|
+
# Ensure browser is actually quit so we don't leave hanging processe
|
|
75
|
+
RSpec::Mocks.space.proxy_for(@original_browser).reset
|
|
76
|
+
@original_browser.quit
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "warns UnknownError returned during quit because the browser is probably already gone" do
|
|
80
|
+
expect_any_instance_of(Capybara::Selenium::Driver).to receive(:warn).with(/random message/)
|
|
81
|
+
allow(@driver.browser).to(
|
|
82
|
+
receive(:quit)
|
|
83
|
+
.and_raise(Selenium::WebDriver::Error::UnknownError, "random message")
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
expect { @driver.quit }.not_to raise_error
|
|
87
|
+
expect(@driver.instance_variable_get(:@browser)).to be_nil
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "ignores silenced UnknownError returned during quit because the browser is almost definitely already gone" do
|
|
91
|
+
expect_any_instance_of(Capybara::Selenium::Driver).not_to receive(:warn)
|
|
92
|
+
allow(@driver.browser).to(
|
|
93
|
+
receive(:quit)
|
|
94
|
+
.and_raise(Selenium::WebDriver::Error::UnknownError, "Error communicating with the remote browser")
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
expect { @driver.quit }.not_to raise_error
|
|
98
|
+
expect(@driver.instance_variable_get(:@browser)).to be_nil
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
context "storage" do
|
|
104
|
+
describe "#reset!" do
|
|
105
|
+
it "does not clear either storage by default" do
|
|
106
|
+
@session = TestSessions::SeleniumMarionette
|
|
107
|
+
@session.visit('/with_js')
|
|
108
|
+
@session.find(:css, '#set-storage').click
|
|
109
|
+
@session.reset!
|
|
110
|
+
@session.visit('/with_js')
|
|
111
|
+
expect(@session.driver.browser.local_storage.keys).not_to be_empty
|
|
112
|
+
expect(@session.driver.browser.session_storage.keys).not_to be_empty
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it "clears storage when set" do
|
|
116
|
+
@session = Capybara::Session.new(:selenium_marionette_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.driver.browser.local_storage.keys).to be_empty
|
|
122
|
+
expect(@session.driver.browser.session_storage.keys).to be_empty
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|