capybara 2.5.0 → 2.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.md +22 -1
- data/License.txt +1 -1
- data/README.md +21 -28
- data/lib/capybara.rb +44 -19
- data/lib/capybara/cucumber.rb +1 -1
- data/lib/capybara/node/finders.rb +8 -2
- data/lib/capybara/queries/current_path_query.rb +3 -3
- data/lib/capybara/rack_test/form.rb +28 -9
- data/lib/capybara/rails.rb +0 -1
- data/lib/capybara/rspec.rb +0 -1
- data/lib/capybara/rspec/features.rb +2 -0
- data/lib/capybara/selector.rb +54 -22
- data/lib/capybara/selenium/node.rb +18 -2
- data/lib/capybara/session.rb +35 -47
- 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 +15 -6
- data/lib/capybara/spec/session/accept_confirm_spec.rb +11 -0
- data/lib/capybara/spec/session/find_button_spec.rb +22 -0
- data/lib/capybara/spec/session/find_field_spec.rb +9 -1
- data/lib/capybara/spec/session/has_button_spec.rb +8 -0
- data/lib/capybara/spec/session/has_current_path_spec.rb +10 -0
- data/lib/capybara/spec/session/has_field_spec.rb +8 -0
- data/lib/capybara/spec/session/has_select_spec.rb +14 -0
- data/lib/capybara/spec/session/node_spec.rb +22 -4
- data/lib/capybara/spec/session/visit_spec.rb +19 -0
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +1 -0
- data/lib/capybara/spec/views/form.erb +20 -0
- data/lib/capybara/spec/views/with_js.erb +6 -0
- data/lib/capybara/version.rb +1 -1
- data/spec/rspec/features_spec.rb +17 -5
- data/spec/rspec/scenarios_spec.rb +20 -0
- data/spec/selector_spec.rb +53 -0
- data/spec/selenium_spec.rb +19 -0
- data/spec/selenium_spec_chrome.rb +2 -0
- data/spec/server_spec.rb +1 -1
- metadata +22 -4
@@ -60,12 +60,14 @@ $(function() {
|
|
60
60
|
$('title').text('changed title')
|
61
61
|
}, 250)
|
62
62
|
});
|
63
|
-
$('#click-test').
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
e
|
68
|
-
|
63
|
+
$('#click-test').on({
|
64
|
+
dblclick: function() {
|
65
|
+
$(this).after('<a id="has-been-double-clicked" href="#">Has been double clicked</a>');
|
66
|
+
},
|
67
|
+
contextmenu: function(e) {
|
68
|
+
e.preventDefault();
|
69
|
+
$(this).after('<a id="has-been-right-clicked" href="#">Has been right clicked</a>');
|
70
|
+
}
|
69
71
|
});
|
70
72
|
$('#open-alert').click(function() {
|
71
73
|
alert('Alert opened');
|
@@ -100,6 +102,13 @@ $(function() {
|
|
100
102
|
$(this).attr('response', response);
|
101
103
|
}
|
102
104
|
});
|
105
|
+
$('#open-twice').click(function() {
|
106
|
+
if (confirm('Are you sure?')) {
|
107
|
+
if (!confirm('Are you really sure?')) {
|
108
|
+
$(this).attr('confirmed', 'false');
|
109
|
+
}
|
110
|
+
}
|
111
|
+
})
|
103
112
|
$('#delayed-page-change').click(function() {
|
104
113
|
setTimeout(function() {
|
105
114
|
window.location.pathname = '/with_html'
|
@@ -16,4 +16,15 @@ Capybara::SpecHelper.spec '#accept_confirm', :requires => [:modals] do
|
|
16
16
|
end
|
17
17
|
expect(message).to eq('Confirm opened')
|
18
18
|
end
|
19
|
+
|
20
|
+
it "should work with nested modals" do
|
21
|
+
expect {
|
22
|
+
@session.dismiss_confirm 'Are you really sure?' do
|
23
|
+
@session.accept_confirm 'Are you sure?' do
|
24
|
+
@session.click_link('Open check twice')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
}.not_to raise_error
|
28
|
+
expect(@session).to have_xpath("//a[@id='open-twice' and @confirmed='false']")
|
29
|
+
end
|
19
30
|
end
|
@@ -29,4 +29,26 @@ Capybara::SpecHelper.spec '#find_button' do
|
|
29
29
|
end.to raise_error(Capybara::ElementNotFound)
|
30
30
|
end
|
31
31
|
end
|
32
|
+
|
33
|
+
context "with :disabled option" do
|
34
|
+
it "should find disabled buttons when true" do
|
35
|
+
expect(@session.find_button('Disabled button', :disabled => true).value).to eq("Disabled button")
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should not find disabled buttons when false" do
|
39
|
+
expect do
|
40
|
+
@session.find_button('Disabled button', :disabled => false)
|
41
|
+
end.to raise_error(Capybara::ElementNotFound)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should default to not finding disabled buttons" do
|
45
|
+
expect do
|
46
|
+
@session.find_button('Disabled button')
|
47
|
+
end.to raise_error(Capybara::ElementNotFound)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should find disabled buttons when :all" do
|
51
|
+
expect(@session.find_button('Disabled button', :disabled => :all).value).to eq("Disabled button")
|
52
|
+
end
|
53
|
+
end
|
32
54
|
end
|
@@ -21,7 +21,7 @@ Capybara::SpecHelper.spec '#find_field' do
|
|
21
21
|
|
22
22
|
it "should warn if filter option is invalid" do
|
23
23
|
expect_any_instance_of(Kernel).to receive(:warn).
|
24
|
-
with('Invalid value nil passed to filter disabled')
|
24
|
+
with('Invalid value nil passed to filter disabled - defaulting to false')
|
25
25
|
@session.find_field('Dog', disabled: nil)
|
26
26
|
end
|
27
27
|
|
@@ -60,6 +60,14 @@ Capybara::SpecHelper.spec '#find_field' do
|
|
60
60
|
@session.find_field("Disabled Checkbox")
|
61
61
|
end.to raise_error(Capybara::ElementNotFound)
|
62
62
|
end
|
63
|
+
|
64
|
+
it "should find disabled fields when :all" do
|
65
|
+
expect(@session.find_field("Disabled Checkbox", :disabled => :all)[:name]).to eq("form[disabled_checkbox]")
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should find enabled fields when :all" do
|
69
|
+
expect(@session.find_field('Dog', :disabled => :all).value).to eq('dog')
|
70
|
+
end
|
63
71
|
end
|
64
72
|
|
65
73
|
|
@@ -24,6 +24,14 @@ Capybara::SpecHelper.spec '#has_button?' do
|
|
24
24
|
it "should be false for disabled buttons if :disabled => false" do
|
25
25
|
expect(@session).not_to have_button('Disabled button', :disabled => false)
|
26
26
|
end
|
27
|
+
|
28
|
+
it "should be true for disabled buttons if :disabled => :all" do
|
29
|
+
expect(@session).to have_button('Disabled button', :disabled => :all)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should be true for enabled buttons if :disabled => :all" do
|
33
|
+
expect(@session).to have_button('med', :disabled => :all)
|
34
|
+
end
|
27
35
|
end
|
28
36
|
|
29
37
|
Capybara::SpecHelper.spec '#has_no_button?' do
|
@@ -12,6 +12,16 @@ Capybara::SpecHelper.spec '#has_current_path?' do
|
|
12
12
|
expect(@session).not_to have_current_path(/monkey/)
|
13
13
|
end
|
14
14
|
|
15
|
+
it "should handle non-escaped query options" do
|
16
|
+
@session.click_link("Non-escaped query options")
|
17
|
+
expect(@session).to have_current_path("/with_html?options[]=things")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should handle escaped query options" do
|
21
|
+
@session.click_link("Escaped query options")
|
22
|
+
expect(@session).to have_current_path("/with_html?options%5B%5D=things")
|
23
|
+
end
|
24
|
+
|
15
25
|
it "should wait for current_path", :requires => [:js] do
|
16
26
|
@session.click_link("Change page")
|
17
27
|
expect(@session).to have_current_path("/with_html")
|
@@ -142,6 +142,14 @@ Capybara::SpecHelper.spec '#has_checked_field?' do
|
|
142
142
|
expect(@session).not_to have_checked_field('Disabled Checkbox', :disabled => false)
|
143
143
|
end
|
144
144
|
|
145
|
+
it "should be true for disabled checkboxes if :disabled => :all" do
|
146
|
+
expect(@session).to have_checked_field('Disabled Checkbox', :disabled => :all)
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should be true for enabled checkboxes if :disabled => :all" do
|
150
|
+
expect(@session).to have_checked_field('gender_female', :disabled => :all)
|
151
|
+
end
|
152
|
+
|
145
153
|
it "should be true after an unchecked checkbox is checked" do
|
146
154
|
@session.check('form_pets_cat')
|
147
155
|
expect(@session).to have_checked_field('form_pets_cat')
|
@@ -59,6 +59,11 @@ Capybara::SpecHelper.spec '#has_select?' do
|
|
59
59
|
'Boxerbriefs', 'Briefs', 'Commando', "Frenchman's Pantalons", 'Long Johns'
|
60
60
|
])
|
61
61
|
end
|
62
|
+
|
63
|
+
it "should be true even when the selected option invisible, regardless of the select's visibility" do
|
64
|
+
expect(@session).to have_select('Icecream', :visible => false, :selected => 'Chocolate')
|
65
|
+
expect(@session).to have_select('Sorbet', :selected => 'Vanilla')
|
66
|
+
end
|
62
67
|
end
|
63
68
|
|
64
69
|
context 'with exact options' do
|
@@ -74,6 +79,11 @@ Capybara::SpecHelper.spec '#has_select?' do
|
|
74
79
|
expect(@session).not_to have_select('Region', :options => ['Norway', 'Sweden'])
|
75
80
|
expect(@session).not_to have_select('Region', :options => ['Norway', 'Norway', 'Norway'])
|
76
81
|
end
|
82
|
+
|
83
|
+
it" should be true even when the options are invisible, if the select itself is invisible" do
|
84
|
+
expect(@session).to have_select("Icecream", :visible => false, :options => ['Chocolate', 'Vanilla', 'Strawberry'])
|
85
|
+
end
|
86
|
+
|
77
87
|
end
|
78
88
|
|
79
89
|
context 'with partial options' do
|
@@ -87,6 +97,10 @@ Capybara::SpecHelper.spec '#has_select?' do
|
|
87
97
|
expect(@session).not_to have_select('Does not exist', :with_options => ['John'])
|
88
98
|
expect(@session).not_to have_select('Region', :with_options => ['Norway', 'Sweden', 'Finland', 'Latvia'])
|
89
99
|
end
|
100
|
+
|
101
|
+
it" should be true even when the options are invisible, if the select itself is invisible" do
|
102
|
+
expect(@session).to have_select("Icecream", :visible => false, :with_options => ['Vanilla', 'Strawberry'])
|
103
|
+
end
|
90
104
|
end
|
91
105
|
end
|
92
106
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
Capybara::SpecHelper.spec "node" do
|
2
3
|
before do
|
3
4
|
@session.visit('/with_html')
|
@@ -317,7 +318,11 @@ Capybara::SpecHelper.spec "node" do
|
|
317
318
|
node = @session.find(:css, '#reload-me')
|
318
319
|
@session.click_link('Reload!')
|
319
320
|
sleep(0.3)
|
320
|
-
expect
|
321
|
+
expect do
|
322
|
+
expect(node).to have_text('has been reloaded')
|
323
|
+
end.to raise_error do |error|
|
324
|
+
expect(error).to be_an_invalid_element_error(@session)
|
325
|
+
end
|
321
326
|
end
|
322
327
|
after { Capybara.automatic_reload = true }
|
323
328
|
end
|
@@ -347,13 +352,22 @@ Capybara::SpecHelper.spec "node" do
|
|
347
352
|
expect(node.find(:css, 'a').text).to eq('has been reloaded')
|
348
353
|
end
|
349
354
|
|
350
|
-
it "should not reload nodes which haven't been found" do
|
355
|
+
it "should not reload nodes which haven't been found with reevaluateable queries" do
|
351
356
|
@session.visit('/with_js')
|
352
357
|
node = @session.all(:css, '#the-list li')[1]
|
353
358
|
@session.click_link('Fetch new list!')
|
354
359
|
sleep(0.3)
|
355
|
-
|
356
|
-
expect
|
360
|
+
|
361
|
+
expect do
|
362
|
+
expect(node).to have_text('Foo')
|
363
|
+
end.to raise_error { |error|
|
364
|
+
expect(error).to be_an_invalid_element_error(@session)
|
365
|
+
}
|
366
|
+
expect do
|
367
|
+
expect(node).to have_text('Bar')
|
368
|
+
end.to raise_error { |error|
|
369
|
+
expect(error).to be_an_invalid_element_error(@session)
|
370
|
+
}
|
357
371
|
end
|
358
372
|
|
359
373
|
it "should reload nodes with options" do
|
@@ -365,4 +379,8 @@ Capybara::SpecHelper.spec "node" do
|
|
365
379
|
end
|
366
380
|
end
|
367
381
|
end
|
382
|
+
|
383
|
+
def be_an_invalid_element_error(session)
|
384
|
+
satisfy { |error| session.driver.invalid_element_errors.any? { |e| error.is_a? e } }
|
385
|
+
end
|
368
386
|
end
|
@@ -79,6 +79,25 @@ Capybara::SpecHelper.spec '#visit' do
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
+
context "with Capybara.app_host set" do
|
83
|
+
it "should override server", requires: [:server] do
|
84
|
+
another_session = Capybara::Session.new(@session.mode, @session.app.dup)
|
85
|
+
Capybara.app_host = "http://#{@session.server.host}:#{@session.server.port}"
|
86
|
+
another_session.visit('/foo')
|
87
|
+
expect(another_session).to have_content("Another World")
|
88
|
+
expect(another_session.current_url).to start_with(Capybara.app_host)
|
89
|
+
expect(URI.parse(another_session.current_url).port).not_to eq another_session.server.port
|
90
|
+
expect(URI.parse(another_session.current_url).port).to eq @session.server.port
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should append relative path", requires: [:server] do
|
94
|
+
Capybara.app_host = "http://#{@session.server.host}:#{@session.server.port}/redirect/0"
|
95
|
+
@session.visit('/times')
|
96
|
+
expect(@session).to have_content('redirection complete')
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
82
101
|
it "should send no referer when visiting a page" do
|
83
102
|
@session.visit '/get_referer'
|
84
103
|
expect(@session).to have_content 'No referer'
|
@@ -72,6 +72,7 @@ Capybara::SpecHelper.spec '#window_opened_by', requires: [:windows] do
|
|
72
72
|
expect do
|
73
73
|
@session.window_opened_by do
|
74
74
|
button.click
|
75
|
+
sleep 0.1 # It's possible for window_opened_by to be fullfilled before the second window opens
|
75
76
|
end
|
76
77
|
end.to raise_error(Capybara::WindowError, two_windows_message)
|
77
78
|
@session.document.synchronize(2, errors: [Capybara::CapybaraError]) do
|
@@ -191,6 +191,26 @@ New line after and before textarea tag
|
|
191
191
|
</select>
|
192
192
|
</p>
|
193
193
|
|
194
|
+
<!-- invisible select and options -->
|
195
|
+
<p style="display: none">
|
196
|
+
<label for="form_icecream">Icecream</label>
|
197
|
+
<select name="form[icecream]" id="form_icecream">
|
198
|
+
<option selected="selected">Chocolate</option>
|
199
|
+
<option>Vanilla</option>
|
200
|
+
<option>Strawberry</option>
|
201
|
+
</select>
|
202
|
+
</p>
|
203
|
+
|
204
|
+
<!-- visible select with invisible selected option (which some browsers may treat as visible) -->
|
205
|
+
<p>
|
206
|
+
<label for="form_sorbet">Sorbet</label>
|
207
|
+
<select name="form[sorbet]" id="form_sorbet">
|
208
|
+
<option>Chocolate</option>
|
209
|
+
<option selected="selected" style="display: none">Vanilla</option>
|
210
|
+
<option>Strawberry</option>
|
211
|
+
</select>
|
212
|
+
</p>
|
213
|
+
|
194
214
|
<p>
|
195
215
|
<span>First address<span>
|
196
216
|
<label for='address1_street'>Street</label>
|
@@ -85,12 +85,18 @@
|
|
85
85
|
<a href="#" id="open-confirm">Open confirm</a>
|
86
86
|
</p>
|
87
87
|
|
88
|
+
<p>
|
89
|
+
<a href="#" id="open-twice">Open check twice</a>
|
90
|
+
</p>
|
91
|
+
|
88
92
|
<p>
|
89
93
|
<a href="#" id="open-prompt">Open prompt</a>
|
90
94
|
</p>
|
91
95
|
|
92
96
|
<p>
|
93
97
|
<a href="#" id="delayed-page-change">Change page</a>
|
98
|
+
<a href="/with_html?options[]=things">Non-escaped query options</a>
|
99
|
+
<a href="/with_html?options%5B%5D=things">Escaped query options</a>
|
94
100
|
</p>
|
95
101
|
|
96
102
|
<p>
|
data/lib/capybara/version.rb
CHANGED
data/spec/rspec/features_spec.rb
CHANGED
@@ -70,13 +70,25 @@ feature "given and given! aliases to let and let!" do
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
-
feature "if xscenario aliases to pending then" do
|
74
|
-
xscenario "this test should be 'temporarily disabled with xscenario'" do
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
73
|
feature "Capybara's feature DSL with driver", :driver => :culerity do
|
79
74
|
scenario "switches driver" do
|
80
75
|
expect(Capybara.current_driver).to eq(:culerity)
|
81
76
|
end
|
82
77
|
end
|
78
|
+
|
79
|
+
if RSpec::Core::Version::STRING.to_f >= 3.0
|
80
|
+
xfeature "if xfeature aliases to pending then" do
|
81
|
+
scenario "this should be 'temporarily disabled with xfeature'" do; end
|
82
|
+
scenario "this also should be 'temporarily disabled with xfeature'" do; end
|
83
|
+
end
|
84
|
+
|
85
|
+
ffeature "if ffeature aliases focused tag then" do
|
86
|
+
scenario "scenario inside this feature has metatag focus tag" do |example|
|
87
|
+
expect(example.metadata[:focus]).to eq true
|
88
|
+
end
|
89
|
+
|
90
|
+
scenario "other scenarios also has metatag focus tag " do |example|
|
91
|
+
expect(example.metadata[:focus]).to eq true
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'capybara/rspec'
|
3
|
+
|
4
|
+
RSpec.configuration.before(:each, { file_path: "./spec/rspec/scenarios_spec.rb" } ) do
|
5
|
+
@in_filtered_hook = true
|
6
|
+
end
|
7
|
+
|
8
|
+
if RSpec::Core::Version::STRING.to_f >= 3.0
|
9
|
+
feature "if fscenario aliases focused tag then" do
|
10
|
+
fscenario "scenario should have focused meta tag" do |example|
|
11
|
+
expect(example.metadata[:focus]).to eq true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
feature "if xscenario aliases to pending then" do
|
17
|
+
xscenario "this test should be 'temporarily disabled with xscenario'" do
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Capybara do
|
4
|
+
describe 'Selectors' do
|
5
|
+
let :string do
|
6
|
+
Capybara.string <<-STRING
|
7
|
+
<html>
|
8
|
+
<head>
|
9
|
+
<title>selectors</title>
|
10
|
+
</head>
|
11
|
+
<body>
|
12
|
+
<div class="a" id="page">
|
13
|
+
<div class="b" id="content">
|
14
|
+
<h1 class="a">Totally awesome</h1>
|
15
|
+
<p>Yes it is</p>
|
16
|
+
</div>
|
17
|
+
<p class="b">Some Content</p>
|
18
|
+
<p class="b"></p>
|
19
|
+
</div>
|
20
|
+
</body>
|
21
|
+
</html>
|
22
|
+
STRING
|
23
|
+
end
|
24
|
+
|
25
|
+
before do
|
26
|
+
Capybara.add_selector :custom_selector do
|
27
|
+
css { |css_class| "div.#{css_class}" }
|
28
|
+
filter(:not_empty, boolean: true, default: true, skip_if: :all) { |node, value| value ^ (node.text == '') }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "modfiy_selector" do
|
33
|
+
it "allows modifying a selector" do
|
34
|
+
el = string.find(:custom_selector, 'a')
|
35
|
+
expect(el.tag_name).to eq 'div'
|
36
|
+
Capybara.modify_selector :custom_selector do
|
37
|
+
css { |css_class| "h1.#{css_class}" }
|
38
|
+
end
|
39
|
+
el = string.find(:custom_selector, 'a')
|
40
|
+
expect(el.tag_name).to eq 'h1'
|
41
|
+
end
|
42
|
+
|
43
|
+
it "doesn't change existing filters" do
|
44
|
+
Capybara.modify_selector :custom_selector do
|
45
|
+
css { |css_class| "p.#{css_class}"}
|
46
|
+
end
|
47
|
+
expect(string).to have_selector(:custom_selector, 'b', count: 1)
|
48
|
+
expect(string).to have_selector(:custom_selector, 'b', not_empty: false, count: 1)
|
49
|
+
expect(string).to have_selector(:custom_selector, 'b', not_empty: :all, count: 2)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/spec/selenium_spec.rb
CHANGED
@@ -100,6 +100,25 @@ RSpec.describe Capybara::Session do
|
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
103
|
+
context "#fill_in with { clear: :none } fill_options" do
|
104
|
+
it 'should append to content in a field' do
|
105
|
+
@session.visit('/form')
|
106
|
+
@session.fill_in('form_first_name', :with => 'Harry',
|
107
|
+
fill_options: { clear: :none} )
|
108
|
+
expect(@session.find(:fillable_field, 'form_first_name').value).to eq('JohnHarry')
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context "#fill_in with { clear: Array } fill_options" do
|
113
|
+
it 'should pass the array through to the element', tw: true do
|
114
|
+
#this is mainly for use with [[:ctrl, 'a'], :backspace] - however since that is platform dependant I'm testing with something less useful
|
115
|
+
@session.visit('/form')
|
116
|
+
@session.fill_in('form_first_name', :with => 'Harry',
|
117
|
+
fill_options: { clear: [[:shift, 'abc'], :backspace] } )
|
118
|
+
expect(@session.find(:fillable_field, 'form_first_name').value).to eq('JohnABHarry')
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
103
122
|
describe "#path" do
|
104
123
|
it "returns xpath" do
|
105
124
|
# this is here because it is testing for an XPath that is specific to the algorithm used in the selenium driver
|