capybara 2.5.0 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
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