capybara 2.7.1 → 2.8.0

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