capybara 2.7.1 → 2.8.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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +22 -0
  3. data/README.md +27 -3
  4. data/lib/capybara.rb +19 -4
  5. data/lib/capybara/driver/base.rb +6 -2
  6. data/lib/capybara/driver/node.rb +13 -5
  7. data/lib/capybara/helpers.rb +2 -2
  8. data/lib/capybara/node/actions.rb +116 -17
  9. data/lib/capybara/node/base.rb +7 -1
  10. data/lib/capybara/node/element.rb +23 -3
  11. data/lib/capybara/node/finders.rb +45 -29
  12. data/lib/capybara/node/matchers.rb +13 -15
  13. data/lib/capybara/queries/selector_query.rb +22 -5
  14. data/lib/capybara/queries/text_query.rb +42 -6
  15. data/lib/capybara/rack_test/node.rb +13 -1
  16. data/lib/capybara/result.rb +80 -8
  17. data/lib/capybara/rspec/features.rb +13 -6
  18. data/lib/capybara/selector.rb +98 -71
  19. data/lib/capybara/selector/filter_set.rb +46 -0
  20. data/lib/capybara/selenium/driver.rb +22 -23
  21. data/lib/capybara/selenium/node.rb +14 -6
  22. data/lib/capybara/server.rb +20 -10
  23. data/lib/capybara/session.rb +44 -8
  24. data/lib/capybara/spec/session/all_spec.rb +4 -4
  25. data/lib/capybara/spec/session/assert_text.rb +23 -0
  26. data/lib/capybara/spec/session/check_spec.rb +66 -8
  27. data/lib/capybara/spec/session/choose_spec.rb +20 -0
  28. data/lib/capybara/spec/session/click_button_spec.rb +0 -3
  29. data/lib/capybara/spec/session/click_link_spec.rb +7 -0
  30. data/lib/capybara/spec/session/execute_script_spec.rb +6 -1
  31. data/lib/capybara/spec/session/find_button_spec.rb +19 -1
  32. data/lib/capybara/spec/session/find_field_spec.rb +21 -1
  33. data/lib/capybara/spec/session/find_link_spec.rb +19 -1
  34. data/lib/capybara/spec/session/find_spec.rb +32 -4
  35. data/lib/capybara/spec/session/first_spec.rb +4 -4
  36. data/lib/capybara/spec/session/has_field_spec.rb +4 -0
  37. data/lib/capybara/spec/session/has_text_spec.rb +2 -2
  38. data/lib/capybara/spec/session/node_spec.rb +24 -3
  39. data/lib/capybara/spec/session/reset_session_spec.rb +7 -0
  40. data/lib/capybara/spec/session/selectors_spec.rb +14 -0
  41. data/lib/capybara/spec/session/uncheck_spec.rb +39 -0
  42. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +4 -2
  43. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +2 -1
  44. data/lib/capybara/spec/session/window/window_spec.rb +36 -22
  45. data/lib/capybara/spec/session/within_frame_spec.rb +19 -0
  46. data/lib/capybara/spec/spec_helper.rb +3 -0
  47. data/lib/capybara/spec/views/form.erb +34 -6
  48. data/lib/capybara/spec/views/with_html.erb +5 -1
  49. data/lib/capybara/spec/views/with_unload_alert.erb +3 -1
  50. data/lib/capybara/spec/views/with_windows.erb +2 -0
  51. data/lib/capybara/version.rb +1 -1
  52. data/spec/capybara_spec.rb +34 -0
  53. data/spec/rack_test_spec.rb +24 -0
  54. data/spec/result_spec.rb +25 -0
  55. data/spec/rspec/features_spec.rb +3 -3
  56. data/spec/selenium_spec.rb +6 -3
  57. data/spec/server_spec.rb +2 -2
  58. metadata +18 -4
@@ -9,32 +9,38 @@ Capybara::SpecHelper.spec '#within_frame', :requires => [:frames] do
9
9
  expect(@session.find("//*[@id='divInFrameOne']").text).to eql 'This is the text of divInFrameOne'
10
10
  end
11
11
  end
12
+
12
13
  it "should find the div in FrameTwo" do
13
14
  @session.within_frame("frameTwo") do
14
15
  expect(@session.find("//*[@id='divInFrameTwo']").text).to eql 'This is the text of divInFrameTwo'
15
16
  end
16
17
  end
18
+
17
19
  it "should find the text div in the main window after finding text in frameOne" do
18
20
  @session.within_frame("frameOne") do
19
21
  expect(@session.find("//*[@id='divInFrameOne']").text).to eql 'This is the text of divInFrameOne'
20
22
  end
21
23
  expect(@session.find("//*[@id='divInMainWindow']").text).to eql 'This is the text for divInMainWindow'
22
24
  end
25
+
23
26
  it "should find the text div in the main window after finding text in frameTwo" do
24
27
  @session.within_frame("frameTwo") do
25
28
  expect(@session.find("//*[@id='divInFrameTwo']").text).to eql 'This is the text of divInFrameTwo'
26
29
  end
27
30
  expect(@session.find("//*[@id='divInMainWindow']").text).to eql 'This is the text for divInMainWindow'
28
31
  end
32
+
29
33
  it "should return the result of executing the block" do
30
34
  expect(@session.within_frame("frameOne") { "return value" }).to eql "return value"
31
35
  end
36
+
32
37
  it "should find the div given Element" do
33
38
  element = @session.find(:id, 'frameOne')
34
39
  @session.within_frame element do
35
40
  expect(@session.find("//*[@id='divInFrameOne']").text).to eql 'This is the text of divInFrameOne'
36
41
  end
37
42
  end
43
+
38
44
  it "should find multiple nested frames" do
39
45
  @session.within_frame 'parentFrame' do
40
46
  @session.within_frame 'childFrame' do
@@ -43,6 +49,7 @@ Capybara::SpecHelper.spec '#within_frame', :requires => [:frames] do
43
49
  end
44
50
  end
45
51
  end
52
+
46
53
  it "should reset scope when changing frames" do
47
54
  @session.within(:css, '#divInMainWindow') do
48
55
  @session.within_frame 'parentFrame' do
@@ -60,4 +67,16 @@ Capybara::SpecHelper.spec '#within_frame', :requires => [:frames] do
60
67
  expect(@session).not_to have_selector(:css, '#childFrame')
61
68
  end
62
69
  end
70
+
71
+ it "should support the driver #switch_to_frame api" do
72
+ # This test is purely to notify driver authors to update their API.
73
+ # The #switch_to_frame API will be required in the next version (> 2.8) of Capybara for frames support.
74
+ # It should not be used as an example of code for users.
75
+ frame = @session.find(:frame, "frameOne")
76
+ expect {
77
+ @session.driver.switch_to_frame(frame)
78
+ sleep 0.5
79
+ @session.driver.switch_to_frame(:parent)
80
+ }.not_to raise_error
81
+ end
63
82
  end
@@ -22,6 +22,8 @@ module Capybara
22
22
  config.filter_run_excluding :requires => method(:filter).to_proc
23
23
  config.before { Capybara::SpecHelper.reset! }
24
24
  config.after { Capybara::SpecHelper.reset! }
25
+ # Test in 3.5+ where metadata doesn't autotrigger shared context inclusion - will be only behavior in RSpec 4
26
+ config.shared_context_metadata_behavior = :apply_to_host_groups if RSpec::Core::Version::STRING.to_f >= 3.5
25
27
  end
26
28
 
27
29
  def reset!
@@ -36,6 +38,7 @@ module Capybara
36
38
  Capybara.visible_text_only = false
37
39
  Capybara.match = :smart
38
40
  Capybara.wait_on_first_by_default = false
41
+ Capybara.enable_aria_label = false
39
42
  end
40
43
 
41
44
  def filter(requires, metadata)
@@ -37,7 +37,7 @@
37
37
  <p>
38
38
  <label for="form_first_name">
39
39
  First Name
40
- <input type="text" name="form[first_name]" value="John" id="form_first_name"/>
40
+ <input type="text" name="form[first_name]" value="John" id="form_first_name" placeholder="FirstName"/>
41
41
  </label>
42
42
  </p>
43
43
 
@@ -154,6 +154,15 @@ New line after and before textarea tag
154
154
  <label for="gender_both">Both</label>
155
155
  </p>
156
156
 
157
+ <p>
158
+ <input type="radio" name="form[party]" value="democrat" id="party_democrat" style="display:none"/>
159
+ <label for="party_democrat">Democrat</label>
160
+ <input type="radio" name="form[party]" value="republican" id="party_republican" style="display:none"/>
161
+ <label for="party_republican">Republican</label>
162
+ <input type="radio" name="form[party]" value="independent" id="party_independent" checked="checked" style="display:none"/>
163
+ <label for="party_independent">Independent</label>
164
+ </p>
165
+
157
166
  <p>
158
167
  <input type="checkbox" id="no_attr_value_checked" value="1" checked/>
159
168
  </p>
@@ -167,6 +176,24 @@ New line after and before textarea tag
167
176
  <label for="form_pets_hamster">Hamster</label>
168
177
  </p>
169
178
 
179
+ <p>
180
+ <input type="checkbox" value="jaguar" name="form[cars][]" id="form_cars_jaguar" checked="checked" style="display: none"/>
181
+ <label for="form_cars_jaguar">Jaguar</label>
182
+ <input type="checkbox" value="tesla" name="form[cars][]" id="form_cars_tesla" style="display: none"/>
183
+ <label for="form_cars_tesla">Tesla</label>
184
+ <input type="checkbox" value="ferrari" name="form[cars][]" id="form_cars_ferrari" checked="checked" style="display: none"/>
185
+ <label for="form_cars_ferrari">Ferrari</label>
186
+ <input type="checkbox" value="ariel" name="form[cars][]" id="form_cars_ariel" style="display: none"/>
187
+ <label>
188
+ McLaren
189
+ <input type="checkbox" value="mclaren" name="form[cars][]" id="form_cars_mclaren" style="display: none"/>
190
+ </label>
191
+ <label>
192
+ Koenigsegg
193
+ <input type="checkbox" value="koenigsegg" name="form[cars][]" id="form_cars_koenigsegg" checked="checked" style="display: none"/>
194
+ </label>
195
+ </p>
196
+
170
197
  <p>
171
198
  <input type="checkbox" name="form[valueless_checkbox]" id="valueless_checkbox" checked="checked"/>
172
199
  <label for="valueless_checkbox">Valueless Checkbox</label>
@@ -226,7 +253,7 @@ New line after and before textarea tag
226
253
 
227
254
  <label for='address1_country'>Country</label>
228
255
  <select name="form[addresses][][country]" id="address1_country">
229
- <option>France</option>
256
+ <option selected>France</option>
230
257
  <option>Ukraine</option>
231
258
  </select>
232
259
  </p>
@@ -242,7 +269,7 @@ New line after and before textarea tag
242
269
  <label for='address2_country'>Country</label>
243
270
  <select name="form[addresses][][country]" id="address2_country">
244
271
  <option>France</option>
245
- <option>Ukraine</option>
272
+ <option selected>Ukraine</option>
246
273
  </select>
247
274
  </p>
248
275
 
@@ -370,7 +397,7 @@ New line after and before textarea tag
370
397
  </p>
371
398
 
372
399
  <p>
373
- <input type="submit" name="form[mediocre]" id="mediocre" value="med"/>
400
+ <input type="submit" name="form[mediocre]" id="mediocre" value="med" aria-label="Mediocre Button"/>
374
401
  <p>
375
402
  </form>
376
403
 
@@ -455,9 +482,10 @@ New line after and before textarea tag
455
482
  <label for="html5_search">Html5 Search</label>
456
483
  <input type="search" name="form[html5_search]" value="what are you looking for" id="html5_search"/>
457
484
  </p>
485
+ <p id="emergency">Emergency Number</p>
458
486
  <p>
459
487
  <label for="html5_tel">Html5 Tel</label>
460
- <input type="tel" name="form[html5_tel]" value="911" id="html5_tel"/>
488
+ <input type="tel" aria-labelledby="emergency" name="form[html5_tel]" value="911" id="html5_tel"/>
461
489
  </p>
462
490
  <p>
463
491
  <label for="html5_color">Html5 Color</label>
@@ -480,7 +508,7 @@ New line after and before textarea tag
480
508
 
481
509
  <form action="/other_form" method="post">
482
510
  <p>
483
- <input type="text" name="form[which_form]" value="formaction form"/>
511
+ <input type="text" name="form[which_form]" value="formaction form" aria-label="Unlabelled Input"/>
484
512
  </p>
485
513
  <input type="submit" name="form[button]" formaction="/form" value="Formaction button"/>
486
514
  <input type="submit" name="form[button]" formaction="/form/get" formmethod="get" value="Formmethod button"/>
@@ -19,7 +19,7 @@
19
19
  et dolore magna aliqua. Ut enim ad minim veniam,
20
20
  quis nostrud exercitation <a href="/foo" id="foo">ullamco</a> laboris nisi
21
21
  ut aliquip ex ea commodo consequat.
22
- <a href="/with_simple_html"><img width="20" height="20" alt="awesome image" /></a>
22
+ <a href="/with_simple_html" aria-label="Go to simple"><img width="20" height="20" alt="awesome image" /></a>
23
23
  </p>
24
24
 
25
25
  <p class="para" id="second">
@@ -79,6 +79,10 @@ banana</textarea>
79
79
  Some of this text is <em style="display:none">hidden!</em>
80
80
  </div>
81
81
 
82
+ <div id="some-hidden-text">
83
+ Some of this text is not hidden <em style="display:none">and some is hidden</em>
84
+ </div>
85
+
82
86
  <div style="display: none;">
83
87
  <a id="first_invisble" class="hidden">first hidden link</a>
84
88
  </div>
@@ -8,5 +8,7 @@
8
8
  </head>
9
9
  <body>
10
10
  <div>This triggers an alert on unload</div>
11
+
12
+ <a href="/">Go away</a>
11
13
  </body>
12
- </html>
14
+ </html>
@@ -29,6 +29,8 @@
29
29
  window.open('/popup_two', 'secondPopup');
30
30
  return false;
31
31
  });
32
+
33
+ $('body').addClass('loaded');
32
34
  });
33
35
  </script>
34
36
  </head>
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Capybara
3
- VERSION = '2.7.1'
3
+ VERSION = '2.8.0'
4
4
  end
@@ -77,6 +77,40 @@ RSpec.describe Capybara do
77
77
  expect(Capybara.server).to eq(server)
78
78
  end
79
79
  end
80
+
81
+ describe 'app_host' do
82
+ after do
83
+ Capybara.app_host = nil
84
+ end
85
+
86
+ it "should warn if not a valid URL" do
87
+ expect { Capybara.app_host = "www.example.com" }.to raise_error(ArgumentError, /Capybara\.app_host should be set to a url/)
88
+ end
89
+
90
+ it "should not warn if a valid URL" do
91
+ expect { Capybara.app_host = "http://www.example.com" }.not_to raise_error
92
+ end
93
+
94
+ it "should not warn if nil" do
95
+ expect { Capybara.app_host = nil }.not_to raise_error
96
+ end
97
+ end
98
+
99
+ describe 'default_host' do
100
+ around do |test|
101
+ old_default = Capybara.default_host
102
+ test.run
103
+ Capybara.default_host = old_default
104
+ end
105
+
106
+ it "should warn if not a valid URL" do
107
+ expect { Capybara.default_host = "www.example.com" }.to raise_error(ArgumentError, /Capybara\.default_host should be set to a url/)
108
+ end
109
+
110
+ it "should not warn if a valid URL" do
111
+ expect { Capybara.default_host = "http://www.example.com" }.not_to raise_error
112
+ end
113
+ end
80
114
  end
81
115
 
82
116
  RSpec.describe Capybara::Session do
@@ -80,6 +80,30 @@ RSpec.describe Capybara::Session do
80
80
  end
81
81
  end
82
82
  end
83
+
84
+ describe "#click" do
85
+ context "on a label" do
86
+ it "should toggle the associated checkbox" do
87
+ @session.visit("/form")
88
+ expect(@session).to have_unchecked_field('form_pets_cat')
89
+ @session.find(:label, 'Cat').click
90
+ expect(@session).to have_checked_field('form_pets_cat')
91
+ @session.find(:label, 'Cat').click
92
+ expect(@session).to have_unchecked_field('form_pets_cat')
93
+ @session.find(:label, 'McLaren').click
94
+ expect(@session).to have_checked_field('form_cars_mclaren', visible: :hidden)
95
+ end
96
+
97
+ it "should toggle the associated radio" do
98
+ @session.visit("/form")
99
+ expect(@session).to have_unchecked_field('gender_male')
100
+ @session.find(:label, 'Male').click
101
+ expect(@session).to have_checked_field('gender_male')
102
+ @session.find(:label, 'Female').click
103
+ expect(@session).to have_unchecked_field('gender_male')
104
+ end
105
+ end
106
+ end
83
107
  end
84
108
  end
85
109
 
@@ -63,4 +63,29 @@ RSpec.describe Capybara::Result do
63
63
  el.text == 'Gamma'
64
64
  end).to eq(2)
65
65
  end
66
+
67
+ it 'supports all modes of []' do
68
+ expect(result[1].text).to eq 'Beta'
69
+ expect(result[0,2].map &:text).to eq ['Alpha', 'Beta']
70
+ expect(result[1..3].map &:text).to eq ['Beta', 'Gamma', 'Delta']
71
+ expect(result[-1].text).to eq 'Delta'
72
+ end
73
+
74
+ #Not a great test but it indirectly tests what is needed
75
+ it "should evaluate filters lazily" do
76
+ #Not processed until accessed
77
+ expect(result.instance_variable_get('@result_cache').size).to be 0
78
+
79
+ #Only one retrieved when needed
80
+ result.first
81
+ expect(result.instance_variable_get('@result_cache').size).to be 1
82
+
83
+ #works for indexed access
84
+ result[2]
85
+ expect(result.instance_variable_get('@result_cache').size).to be 3
86
+
87
+ #All cached when converted to array
88
+ result.to_a
89
+ expect(result.instance_variable_get('@result_cache').size).to eq 4
90
+ end
66
91
  end
@@ -6,11 +6,11 @@ RSpec.configuration.before(:each, { file_path: "./spec/rspec/features_spec.rb" }
6
6
  @in_filtered_hook = true
7
7
  end
8
8
 
9
- feature "Capybara's feature DSL" do
9
+ feature "Capybara's feature DSL" do
10
10
  background do
11
11
  @in_background = true
12
12
  end
13
-
13
+
14
14
  def current_example(context)
15
15
  RSpec.respond_to?(:current_example) ? RSpec.current_example : context.example
16
16
  end
@@ -20,7 +20,7 @@ feature "Capybara's feature DSL" do
20
20
  expect(page).to have_content('Hello world!')
21
21
  end
22
22
 
23
- scenario "preserves description" do
23
+ scenario "preserves description" do
24
24
  expect(current_example(self).metadata[:full_description])
25
25
  .to eq("Capybara's feature DSL preserves description")
26
26
  end
@@ -2,10 +2,13 @@
2
2
  require 'spec_helper'
3
3
  require "selenium-webdriver"
4
4
 
5
+ Selenium::WebDriver::Firefox.driver_path = '/home/travis/geckodriver' if ENV['TRAVIS'] && ENV['GECKODRIVER']
6
+
5
7
  Capybara.register_driver :selenium_focus do |app|
6
- profile = Selenium::WebDriver::Firefox::Profile.new
7
- profile["focusmanager.testmode"] = true
8
- Capybara::Selenium::Driver.new(app, browser: :firefox, profile: profile)
8
+ # profile = Selenium::WebDriver::Firefox::Profile.new
9
+ # profile["focusmanager.testmode"] = true
10
+ # Capybara::Selenium::Driver.new(app, browser: :firefox, profile: profile)
11
+ Capybara::Selenium::Driver.new(app, browser: :firefox)
9
12
  end
10
13
 
11
14
  module TestSessions
@@ -116,7 +116,7 @@ RSpec.describe Capybara::Server do
116
116
  expect {
117
117
  server1.wait_for_pending_requests
118
118
  }.to change{done}.from(false).to(true)
119
- expect(server2.instance_variable_get('@middleware').pending_requests?).to eq(false)
119
+ expect(server2.send(:pending_requests?)).to eq(false)
120
120
  end
121
121
 
122
122
  end
@@ -165,7 +165,7 @@ RSpec.describe Capybara::Server do
165
165
  expect {
166
166
  server1.wait_for_pending_requests
167
167
  }.to change{done}.from(false).to(true)
168
- expect(server2.instance_variable_get('@middleware').pending_requests?).to eq(true)
168
+ expect(server2.send(:pending_requests?)).to eq(true)
169
169
  end
170
170
 
171
171
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capybara
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.7.1
4
+ version: 2.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Walpole
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain:
12
12
  - gem-public_cert.pem
13
- date: 2016-05-01 00:00:00.000000000 Z
13
+ date: 2016-08-16 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: nokogiri
@@ -222,6 +222,20 @@ dependencies:
222
222
  - - ">="
223
223
  - !ruby/object:Gem::Version
224
224
  version: '0'
225
+ - !ruby/object:Gem::Dependency
226
+ name: erubis
227
+ requirement: !ruby/object:Gem::Requirement
228
+ requirements:
229
+ - - ">="
230
+ - !ruby/object:Gem::Version
231
+ version: '0'
232
+ type: :development
233
+ prerelease: false
234
+ version_requirements: !ruby/object:Gem::Requirement
235
+ requirements:
236
+ - - ">="
237
+ - !ruby/object:Gem::Version
238
+ version: '0'
225
239
  description: Capybara is an integration testing tool for rack based web applications.
226
240
  It simulates how a user would interact with a website
227
241
  email:
@@ -267,6 +281,7 @@ files:
267
281
  - lib/capybara/rspec/matchers.rb
268
282
  - lib/capybara/selector.rb
269
283
  - lib/capybara/selector/filter.rb
284
+ - lib/capybara/selector/filter_set.rb
270
285
  - lib/capybara/selenium/driver.rb
271
286
  - lib/capybara/selenium/node.rb
272
287
  - lib/capybara/server.rb
@@ -419,10 +434,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
419
434
  version: '0'
420
435
  requirements: []
421
436
  rubyforge_project:
422
- rubygems_version: 2.6.3
437
+ rubygems_version: 2.6.4
423
438
  signing_key:
424
439
  specification_version: 4
425
440
  summary: Capybara aims to simplify the process of integration testing Rack applications,
426
441
  such as Rails, Sinatra or Merb
427
442
  test_files: []
428
- has_rdoc: