capybara 2.5.0 → 2.6.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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +22 -1
  3. data/License.txt +1 -1
  4. data/README.md +21 -28
  5. data/lib/capybara.rb +44 -19
  6. data/lib/capybara/cucumber.rb +1 -1
  7. data/lib/capybara/node/finders.rb +8 -2
  8. data/lib/capybara/queries/current_path_query.rb +3 -3
  9. data/lib/capybara/rack_test/form.rb +28 -9
  10. data/lib/capybara/rails.rb +0 -1
  11. data/lib/capybara/rspec.rb +0 -1
  12. data/lib/capybara/rspec/features.rb +2 -0
  13. data/lib/capybara/selector.rb +54 -22
  14. data/lib/capybara/selenium/node.rb +18 -2
  15. data/lib/capybara/session.rb +35 -47
  16. data/lib/capybara/spec/public/jquery-ui.js +13 -791
  17. data/lib/capybara/spec/public/jquery.js +4 -9045
  18. data/lib/capybara/spec/public/test.js +15 -6
  19. data/lib/capybara/spec/session/accept_confirm_spec.rb +11 -0
  20. data/lib/capybara/spec/session/find_button_spec.rb +22 -0
  21. data/lib/capybara/spec/session/find_field_spec.rb +9 -1
  22. data/lib/capybara/spec/session/has_button_spec.rb +8 -0
  23. data/lib/capybara/spec/session/has_current_path_spec.rb +10 -0
  24. data/lib/capybara/spec/session/has_field_spec.rb +8 -0
  25. data/lib/capybara/spec/session/has_select_spec.rb +14 -0
  26. data/lib/capybara/spec/session/node_spec.rb +22 -4
  27. data/lib/capybara/spec/session/visit_spec.rb +19 -0
  28. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +1 -0
  29. data/lib/capybara/spec/views/form.erb +20 -0
  30. data/lib/capybara/spec/views/with_js.erb +6 -0
  31. data/lib/capybara/version.rb +1 -1
  32. data/spec/rspec/features_spec.rb +17 -5
  33. data/spec/rspec/scenarios_spec.rb +20 -0
  34. data/spec/selector_spec.rb +53 -0
  35. data/spec/selenium_spec.rb +19 -0
  36. data/spec/selenium_spec_chrome.rb +2 -0
  37. data/spec/server_spec.rb +1 -1
  38. metadata +22 -4
@@ -60,12 +60,14 @@ $(function() {
60
60
  $('title').text('changed title')
61
61
  }, 250)
62
62
  });
63
- $('#click-test').dblclick(function() {
64
- $(this).after('<a id="has-been-double-clicked" href="#">Has been double clicked</a>');
65
- });
66
- $('#click-test').bind('contextmenu', function(e) {
67
- e.preventDefault();
68
- $(this).after('<a id="has-been-right-clicked" href="#">Has been right clicked</a>');
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 { node.text.to == 'has been reloaded' }.to raise_error
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
- expect { node.text.to == 'Foo' }.to raise_error
356
- expect { node.text.to == 'Bar' }.to raise_error
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>
@@ -1,3 +1,3 @@
1
1
  module Capybara
2
- VERSION = '2.5.0'
2
+ VERSION = '2.6.0'
3
3
  end
@@ -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
@@ -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