capybara 3.19.0 → 3.20.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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +27 -2
  3. data/README.md +1 -1
  4. data/lib/capybara/driver/node.rb +4 -0
  5. data/lib/capybara/node/actions.rb +3 -2
  6. data/lib/capybara/node/element.rb +11 -0
  7. data/lib/capybara/node/finders.rb +4 -1
  8. data/lib/capybara/queries/selector_query.rb +19 -5
  9. data/lib/capybara/selector/definition/label.rb +27 -10
  10. data/lib/capybara/selector/definition/link.rb +3 -2
  11. data/lib/capybara/selector.rb +2 -2
  12. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
  13. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
  14. data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
  15. data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
  16. data/lib/capybara/selenium/driver.rb +15 -2
  17. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +1 -1
  18. data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +1 -1
  19. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +1 -1
  20. data/lib/capybara/selenium/node.rb +25 -1
  21. data/lib/capybara/selenium/nodes/safari_node.rb +19 -6
  22. data/lib/capybara/selenium/patches/atoms.rb +18 -0
  23. data/lib/capybara/spec/session/all_spec.rb +23 -0
  24. data/lib/capybara/spec/session/click_link_spec.rb +11 -0
  25. data/lib/capybara/spec/session/node_spec.rb +78 -5
  26. data/lib/capybara/spec/session/selectors_spec.rb +8 -0
  27. data/lib/capybara/spec/views/animated.erb +49 -0
  28. data/lib/capybara/spec/views/frame_one.erb +1 -0
  29. data/lib/capybara/spec/views/obscured.erb +9 -9
  30. data/lib/capybara/version.rb +1 -1
  31. data/spec/sauce_spec_chrome.rb +1 -0
  32. data/spec/selenium_spec_chrome.rb +17 -2
  33. data/spec/selenium_spec_chrome_remote.rb +4 -2
  34. data/spec/selenium_spec_edge.rb +4 -2
  35. data/spec/selenium_spec_firefox.rb +4 -11
  36. data/spec/selenium_spec_firefox_remote.rb +4 -2
  37. data/spec/selenium_spec_ie.rb +5 -6
  38. data/spec/selenium_spec_safari.rb +7 -12
  39. data/spec/server_spec.rb +4 -2
  40. data/spec/shared_selenium_node.rb +29 -0
  41. metadata +23 -2
@@ -118,6 +118,17 @@ Capybara::SpecHelper.spec '#click_link' do
118
118
  expect { @session.click_link('Normal Anchor', href: nil) }.to raise_error(Capybara::ElementNotFound, /with no href attribute/)
119
119
  end
120
120
  end
121
+
122
+ context 'href: false' do
123
+ it 'should not raise an error on links with no href attribute' do
124
+ expect { @session.click_link('No Href', href: false) }.not_to raise_error
125
+ end
126
+
127
+ it 'should not raise an error if href attribute exists' do
128
+ expect { @session.click_link('Blank Href', href: false) }.not_to raise_error
129
+ expect { @session.click_link('Normal Anchor', href: false) }.not_to raise_error
130
+ end
131
+ end
121
132
  end
122
133
 
123
134
  it 'should follow relative links' do
@@ -251,6 +251,79 @@ Capybara::SpecHelper.spec 'node' do
251
251
  end
252
252
  end
253
253
 
254
+ describe '#obscured?', requires: [:css] do
255
+ it 'should see non visible elements as obscured' do
256
+ Capybara.ignore_hidden_elements = false
257
+ expect(@session.find('//div[@id="hidden"]')).to be_obscured
258
+ expect(@session.find('//div[@id="hidden_via_ancestor"]')).to be_obscured
259
+ expect(@session.find('//div[@id="hidden_attr"]')).to be_obscured
260
+ expect(@session.find('//a[@id="hidden_attr_via_ancestor"]')).to be_obscured
261
+ expect(@session.find('//input[@id="hidden_input"]')).to be_obscured
262
+ end
263
+
264
+ it 'should see non-overlapped elements as not obscured' do
265
+ @session.visit('/obscured')
266
+ expect(@session.find(:css, '#cover')).not_to be_obscured
267
+ end
268
+
269
+ it 'should see elements only overlapped by descendants as not obscured' do
270
+ expect(@session.first(:css, 'p:not(.para)')).not_to be_obscured
271
+ end
272
+
273
+ it 'should see elements outside the viewport as obscured' do
274
+ @session.visit('/obscured')
275
+ off = @session.find(:css, '#offscreen')
276
+ off_wrapper = @session.find(:css, '#offscreen_wrapper')
277
+ expect(off).to be_obscured
278
+ expect(off_wrapper).to be_obscured
279
+ @session.scroll_to(off_wrapper)
280
+ expect(off_wrapper).not_to be_obscured
281
+ expect(off).to be_obscured
282
+ off_wrapper.scroll_to(off)
283
+ expect(off).not_to be_obscured
284
+ expect(off_wrapper).not_to be_obscured
285
+ end
286
+
287
+ it 'should see overlapped elements as obscured' do
288
+ @session.visit('/obscured')
289
+ expect(@session.find(:css, '#obscured')).to be_obscured
290
+ end
291
+
292
+ it 'should be boolean' do
293
+ Capybara.ignore_hidden_elements = false
294
+ expect(@session.first('//a').obscured?).to be false
295
+ expect(@session.find('//div[@id="hidden"]').obscured?).to be true
296
+ end
297
+
298
+ it 'should work in frames' do
299
+ @session.visit('/obscured')
300
+ frame = @session.find(:css, '#frameOne')
301
+ @session.within_frame(frame) do
302
+ div = @session.find(:css, '#divInFrameOne')
303
+ expect(div).to be_obscured
304
+ @session.scroll_to div
305
+ expect(div).not_to be_obscured
306
+ end
307
+ end
308
+
309
+ it 'should work in nested iframes' do
310
+ @session.visit('/obscured')
311
+ frame = @session.find(:css, '#nestedFrames')
312
+ @session.within_frame(frame) do
313
+ @session.within_frame(:css, '#childFrame') do
314
+ gcframe = @session.find(:css, '#grandchildFrame2')
315
+ @session.within_frame(gcframe) do
316
+ expect(@session.find(:css, '#divInFrameTwo')).to be_obscured
317
+ end
318
+ @session.scroll_to(gcframe)
319
+ @session.within_frame(gcframe) do
320
+ expect(@session.find(:css, '#divInFrameTwo')).not_to be_obscured
321
+ end
322
+ end
323
+ end
324
+ end
325
+ end
326
+
254
327
  describe '#checked?' do
255
328
  it 'should extract node checked state' do
256
329
  @session.visit('/form')
@@ -441,7 +514,7 @@ Capybara::SpecHelper.spec 'node' do
441
514
  end
442
515
 
443
516
  it 'should retry clicking', requires: [:js] do
444
- @session.visit('/obscured')
517
+ @session.visit('/animated')
445
518
  obscured = @session.find(:css, '#obscured')
446
519
  @session.execute_script <<~JS
447
520
  setTimeout(function(){ $('#cover').hide(); }, 700)
@@ -450,7 +523,7 @@ Capybara::SpecHelper.spec 'node' do
450
523
  end
451
524
 
452
525
  it 'should allow to retry longer', requires: [:js] do
453
- @session.visit('/obscured')
526
+ @session.visit('/animated')
454
527
  obscured = @session.find(:css, '#obscured')
455
528
  @session.execute_script <<~JS
456
529
  setTimeout(function(){ $('#cover').hide(); }, 3000)
@@ -459,7 +532,7 @@ Capybara::SpecHelper.spec 'node' do
459
532
  end
460
533
 
461
534
  it 'should not retry clicking when wait is disabled', requires: [:js] do
462
- @session.visit('/obscured')
535
+ @session.visit('/animated')
463
536
  obscured = @session.find(:css, '#obscured')
464
537
  @session.execute_script <<~JS
465
538
  setTimeout(function(){ $('#cover').hide(); }, 2000)
@@ -493,7 +566,7 @@ Capybara::SpecHelper.spec 'node' do
493
566
  end
494
567
 
495
568
  it 'should retry clicking', requires: [:js] do
496
- @session.visit('/obscured')
569
+ @session.visit('/animated')
497
570
  obscured = @session.find(:css, '#obscured')
498
571
  @session.execute_script <<~JS
499
572
  setTimeout(function(){ $('#cover').hide(); }, 700)
@@ -527,7 +600,7 @@ Capybara::SpecHelper.spec 'node' do
527
600
  end
528
601
 
529
602
  it 'should retry clicking', requires: [:js] do
530
- @session.visit('/obscured')
603
+ @session.visit('/animated')
531
604
  obscured = @session.find(:css, '#obscured')
532
605
  @session.execute_script <<~JS
533
606
  setTimeout(function(){ $('#cover').hide(); }, 700)
@@ -14,10 +14,18 @@ Capybara::SpecHelper.spec Capybara::Selector do
14
14
  expect(@session.find(:label, for: 'form_other_title')['for']).to eq 'form_other_title'
15
15
  end
16
16
 
17
+ it 'finds a label for for attribute regex' do
18
+ expect(@session.find(:label, for: /_other_title/)['for']).to eq 'form_other_title'
19
+ end
20
+
17
21
  it 'finds a label from nested input using :for filter with id string' do
18
22
  expect(@session.find(:label, for: 'nested_label').text).to eq 'Nested Label'
19
23
  end
20
24
 
25
+ it 'finds a label from nested input using :for filter with id regexp' do
26
+ expect(@session.find(:label, for: /nested_lab/).text).to eq 'Nested Label'
27
+ end
28
+
21
29
  it 'finds a label from nested input using :for filter with element' do
22
30
  input = @session.find(:id, 'nested_label')
23
31
  expect(@session.find(:label, for: input).text).to eq 'Nested Label'
@@ -0,0 +1,49 @@
1
+ <html>
2
+ <head>
3
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
4
+ <title>with_animation</title>
5
+ <script src="/jquery.js" type="text/javascript" charset="utf-8"></script>
6
+ <script>
7
+ $(document).on('contextmenu', function(e){ e.preventDefault(); });
8
+ </script>
9
+ <style>
10
+ div {
11
+ width: 400px;
12
+ height: 400px;
13
+ position: absolute;
14
+ }
15
+ #obscured {
16
+ z-index: 1;
17
+ background-color: red;
18
+ }
19
+ #cover {
20
+ z-index: 2;
21
+ background-color: blue;
22
+ }
23
+ #offscreen {
24
+ top: 2000px;
25
+ left: 2000px;
26
+ background-color: green;
27
+ }
28
+ #offscreen_wrapper {
29
+ top: 2000px;
30
+ left: 2000px;
31
+ overflow-x: scroll;
32
+ background-color: yellow;
33
+ }
34
+ </style>
35
+ </head>
36
+
37
+ <body id="with_animation">
38
+ <div id="obscured">
39
+ <input id="obscured_input"/>
40
+ </div>
41
+ <div id="cover"></div>
42
+ <div id="offscreen_wrapper">
43
+ <div id="offscreen"></div>
44
+ </div>
45
+ </body>
46
+
47
+ <iframe id="frameOne" src="/frame_one"></iframe>
48
+ </html>
49
+
@@ -5,5 +5,6 @@
5
5
  </head>
6
6
  <body>
7
7
  <div id="divInFrameOne">This is the text of divInFrameOne</div>
8
+ <div id="otherDivInFrameOne">Some other text</div>
8
9
  </body>
9
10
  </html>
@@ -1,15 +1,13 @@
1
1
  <html>
2
2
  <head>
3
3
  <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
4
- <title>with_animation</title>
5
- <script src="/jquery.js" type="text/javascript" charset="utf-8"></script>
6
- <script>
7
- $(document).on('contextmenu', function(e){ e.preventDefault(); });
8
- </script>
4
+ <title>Obscured</title>
9
5
  <style>
10
6
  div {
11
- width: 400px;
12
- height: 400px;
7
+ width: 200px;
8
+ height: 200px;
9
+ }
10
+ #cover, #offscreen, #offscreen_wrapper {
13
11
  position: absolute;
14
12
  }
15
13
  #obscured {
@@ -17,6 +15,7 @@
17
15
  background-color: red;
18
16
  }
19
17
  #cover {
18
+ top: 0px;
20
19
  z-index: 2;
21
20
  background-color: blue;
22
21
  }
@@ -33,12 +32,13 @@
33
32
  }
34
33
  </style>
35
34
  </head>
36
-
37
- <body id="with_animation">
35
+ <body>
38
36
  <div id="obscured">
39
37
  <input id="obscured_input"/>
40
38
  </div>
41
39
  <div id="cover"></div>
40
+ <iframe id="frameOne" height="10px" src="/frame_one"></iframe>
41
+ <iframe id="nestedFrames" src="/frame_parent"></iframe>
42
42
  <div id="offscreen_wrapper">
43
43
  <div id="offscreen"></div>
44
44
  </div>
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Capybara
4
- VERSION = '3.19.0'
4
+ VERSION = '3.20.0'
5
5
  end
@@ -5,6 +5,7 @@ require 'selenium-webdriver'
5
5
 
6
6
  require 'sauce_whisk'
7
7
  # require 'shared_selenium_session'
8
+ # require 'shared_selenium_node'
8
9
  # require 'rspec/shared_spec_matchers'
9
10
 
10
11
  Capybara.register_driver :sauce_chrome do |app|
@@ -3,6 +3,7 @@
3
3
  require 'spec_helper'
4
4
  require 'selenium-webdriver'
5
5
  require 'shared_selenium_session'
6
+ require 'shared_selenium_node'
6
7
  require 'rspec/shared_spec_matchers'
7
8
 
8
9
  CHROME_DRIVER = :selenium_chrome
@@ -27,6 +28,11 @@ Capybara.register_driver :selenium_chrome_not_clear_storage do |app|
27
28
  Capybara::Selenium::Driver.new(app, chrome_options.merge(clear_local_storage: false, clear_session_storage: false))
28
29
  end
29
30
 
31
+ Capybara.register_driver :selenium_driver_subclass_with_chrome do |app|
32
+ subclass = Class.new(Capybara::Selenium::Driver)
33
+ subclass.new(app, browser: :chrome, options: browser_options, timeout: 30)
34
+ end
35
+
30
36
  module TestSessions
31
37
  Chrome = Capybara::Session.new(CHROME_DRIVER, TestApp)
32
38
  end
@@ -46,8 +52,9 @@ end
46
52
 
47
53
  RSpec.describe 'Capybara::Session with chrome' do
48
54
  include Capybara::SpecHelper
49
- include_examples 'Capybara::Session', TestSessions::Chrome, CHROME_DRIVER
50
- include_examples Capybara::RSpecMatchers, TestSessions::Chrome, CHROME_DRIVER
55
+ ['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|
56
+ include_examples examples, TestSessions::Chrome, CHROME_DRIVER
57
+ end
51
58
 
52
59
  context 'storage' do
53
60
  describe '#reset!' do
@@ -106,4 +113,12 @@ RSpec.describe 'Capybara::Session with chrome' do
106
113
  expect(Time.parse(extract_results(session)['datetime'])).to eq datetime
107
114
  end
108
115
  end
116
+
117
+ describe 'using subclass of selenium driver' do
118
+ it 'works' do
119
+ session = Capybara::Session.new(:selenium_driver_subclass_with_chrome, TestApp)
120
+ session.visit('/form')
121
+ expect(session).to have_current_path('/form')
122
+ end
123
+ end
109
124
  end
@@ -3,6 +3,7 @@
3
3
  require 'spec_helper'
4
4
  require 'selenium-webdriver'
5
5
  require 'shared_selenium_session'
6
+ require 'shared_selenium_node'
6
7
  require 'rspec/shared_spec_matchers'
7
8
 
8
9
  def selenium_host
@@ -72,8 +73,9 @@ end
72
73
 
73
74
  RSpec.describe 'Capybara::Session with remote Chrome' do
74
75
  include Capybara::SpecHelper
75
- include_examples 'Capybara::Session', TestSessions::Chrome, CHROME_REMOTE_DRIVER
76
- include_examples Capybara::RSpecMatchers, TestSessions::Chrome, CHROME_REMOTE_DRIVER
76
+ ['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|
77
+ include_examples examples, TestSessions::Chrome, CHROME_REMOTE_DRIVER
78
+ end
77
79
 
78
80
  it 'is considered to be chrome' do
79
81
  expect(session.driver.browser.browser).to eq :chrome
@@ -3,6 +3,7 @@
3
3
  require 'spec_helper'
4
4
  require 'selenium-webdriver'
5
5
  require 'shared_selenium_session'
6
+ require 'shared_selenium_node'
6
7
  require 'rspec/shared_spec_matchers'
7
8
 
8
9
  Capybara.register_driver :selenium_edge do |app|
@@ -27,6 +28,7 @@ end
27
28
 
28
29
  RSpec.describe 'Capybara::Session with Edge', capybara_skip: skipped_tests do
29
30
  include Capybara::SpecHelper
30
- include_examples 'Capybara::Session', TestSessions::SeleniumEdge, :selenium_edge
31
- include_examples Capybara::RSpecMatchers, TestSessions::SeleniumEdge, :selenium_edge
31
+ ['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|
32
+ include_examples examples, TestSessions::SeleniumEdge, :selenium_edge
33
+ end
32
34
  end
@@ -3,6 +3,7 @@
3
3
  require 'spec_helper'
4
4
  require 'selenium-webdriver'
5
5
  require 'shared_selenium_session'
6
+ require 'shared_selenium_node'
6
7
  require 'rspec/shared_spec_matchers'
7
8
 
8
9
  browser_options = ::Selenium::WebDriver::Firefox::Options.new
@@ -68,8 +69,9 @@ end
68
69
 
69
70
  RSpec.describe 'Capybara::Session with firefox' do # rubocop:disable RSpec/MultipleDescribes
70
71
  include Capybara::SpecHelper
71
- include_examples 'Capybara::Session', TestSessions::SeleniumFirefox, :selenium_firefox
72
- include_examples Capybara::RSpecMatchers, TestSessions::SeleniumFirefox, :selenium_firefox
72
+ ['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|
73
+ include_examples examples, TestSessions::SeleniumFirefox, :selenium_firefox
74
+ end
73
75
 
74
76
  describe 'filling in Firefox-specific date and time fields with keystrokes' do
75
77
  let(:datetime) { Time.new(1983, 6, 19, 6, 30) }
@@ -198,13 +200,4 @@ RSpec.describe Capybara::Selenium::Node do
198
200
  expect(session).to have_link('Has been alt control meta')
199
201
  end
200
202
  end
201
-
202
- context '#send_keys' do
203
- it 'should process space' do
204
- session = TestSessions::SeleniumFirefox
205
- session.visit('/form')
206
- session.find(:css, '#address1_city').send_keys('ocean', [:shift, :space, 'side'])
207
- expect(session.find(:css, '#address1_city').value).to eq 'ocean SIDE'
208
- end
209
- end
210
203
  end
@@ -3,6 +3,7 @@
3
3
  require 'spec_helper'
4
4
  require 'selenium-webdriver'
5
5
  require 'shared_selenium_session'
6
+ require 'shared_selenium_node'
6
7
  require 'rspec/shared_spec_matchers'
7
8
 
8
9
  def selenium_host
@@ -77,8 +78,9 @@ end
77
78
 
78
79
  RSpec.describe 'Capybara::Session with remote firefox' do
79
80
  include Capybara::SpecHelper
80
- include_examples 'Capybara::Session', TestSessions::RemoteFirefox, FIREFOX_REMOTE_DRIVER
81
- include_examples Capybara::RSpecMatchers, TestSessions::RemoteFirefox, FIREFOX_REMOTE_DRIVER
81
+ ['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|
82
+ include_examples examples, TestSessions::RemoteFirefox, FIREFOX_REMOTE_DRIVER
83
+ end
82
84
 
83
85
  it 'is considered to be firefox' do
84
86
  expect(session.driver.browser.browser).to eq :firefox
@@ -3,6 +3,7 @@
3
3
  require 'spec_helper'
4
4
  require 'selenium-webdriver'
5
5
  require 'shared_selenium_session'
6
+ require 'shared_selenium_node'
6
7
  require 'rspec/shared_spec_matchers'
7
8
 
8
9
  if ENV['CI']
@@ -39,7 +40,6 @@ Capybara.register_driver :selenium_ie do |app|
39
40
  browser: :remote,
40
41
  options: options,
41
42
  url: url).tap do |driver|
42
- puts driver.browser.capabilities.inspect
43
43
  driver.browser.file_detector = lambda do |args|
44
44
  str = args.first.to_s
45
45
  str if File.exist?(str)
@@ -50,9 +50,7 @@ Capybara.register_driver :selenium_ie do |app|
50
50
  app,
51
51
  browser: :ie,
52
52
  options: options
53
- ).tap do |driver|
54
- puts driver.browser.capabilities.inspect
55
- end
53
+ )
56
54
  end
57
55
  end
58
56
 
@@ -117,8 +115,9 @@ end
117
115
 
118
116
  RSpec.describe 'Capybara::Session with Internet Explorer', capybara_skip: skipped_tests do # rubocop:disable RSpec/MultipleDescribes
119
117
  include Capybara::SpecHelper
120
- include_examples 'Capybara::Session', TestSessions::SeleniumIE, :selenium_ie
121
- include_examples Capybara::RSpecMatchers, TestSessions::SeleniumIE, :selenium_ie
118
+ ['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|
119
+ include_examples examples, TestSessions::SeleniumIE, :selenium_ie
120
+ end
122
121
  end
123
122
 
124
123
  RSpec.describe Capybara::Selenium::Node do
@@ -3,6 +3,7 @@
3
3
  require 'spec_helper'
4
4
  require 'selenium-webdriver'
5
5
  require 'shared_selenium_session'
6
+ require 'shared_selenium_node'
6
7
  require 'rspec/shared_spec_matchers'
7
8
 
8
9
  SAFARI_DRIVER = :selenium_safari
@@ -54,13 +55,6 @@ Capybara::SpecHelper.run_specs TestSessions::Safari, SAFARI_DRIVER.to_s, capybar
54
55
  pending 'safaridriver thinks these links are non-interactable for some unknown reason'
55
56
  when /Capybara::Session selenium_safari #attach_file with a block can upload by clicking the file input/
56
57
  skip "safaridriver doesn't allow clicking on file inputs"
57
- when /Capybara::Session selenium_safari #attach_file with a block can upload by clicking the label/
58
- skip 'hangs tests'
59
- when /Capybara::Session selenium_safari #check when checkbox hidden with Capybara.automatic_label_click == false with allow_label_click == true should check via the label if input is visible but blocked by another element/,
60
- 'Capybara::Session selenium_safari node #click should not retry clicking when wait is disabled',
61
- 'Capybara::Session selenium_safari node #click should allow to retry longer',
62
- 'Capybara::Session selenium_safari node #click should retry clicking'
63
- pending "safaridriver doesn't return a specific enough error to deal with this"
64
58
  when /Capybara::Session selenium_safari #within_frame works if the frame is closed/,
65
59
  /Capybara::Session selenium_safari #switch_to_frame works if the frame is closed/
66
60
  skip 'Safari has a race condition when clicking an element that causes the frame to close. It will sometimes raise a NoSuchFrameError'
@@ -79,15 +73,14 @@ Capybara::SpecHelper.run_specs TestSessions::Safari, SAFARI_DRIVER.to_s, capybar
79
73
  when 'Capybara::Session selenium_safari #go_back should fetch a response from the driver from the previous page',
80
74
  'Capybara::Session selenium_safari #go_forward should fetch a response from the driver from the previous page'
81
75
  skip 'safaridriver loses the ability to find elements in the document after `go_back`'
82
- when 'Capybara::Session selenium_safari node #send_keys should hold modifiers at top level'
83
- skip 'Need to look into this'
84
76
  end
85
77
  end
86
78
 
87
79
  RSpec.describe 'Capybara::Session with safari' do
88
80
  include Capybara::SpecHelper
89
- include_examples 'Capybara::Session', TestSessions::Safari, SAFARI_DRIVER
90
- include_examples Capybara::RSpecMatchers, TestSessions::Safari, SAFARI_DRIVER
81
+ ['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|
82
+ include_examples examples, TestSessions::Safari, SAFARI_DRIVER
83
+ end
91
84
 
92
85
  context 'storage' do
93
86
  describe '#reset!' do
@@ -125,17 +118,18 @@ RSpec.describe 'Capybara::Session with safari' do
125
118
  let(:session) { TestSessions::Safari }
126
119
 
127
120
  before do
128
- skip 'Too many other things broken currently'
129
121
  session.visit('/form')
130
122
  end
131
123
 
132
124
  it 'should fill in a date input with a String' do
125
+ pending "Safari doesn't support date inputs"
133
126
  session.fill_in('form_date', with: '06/19/1983')
134
127
  session.click_button('awesome')
135
128
  expect(Date.parse(extract_results(session)['date'])).to eq datetime.to_date
136
129
  end
137
130
 
138
131
  it 'should fill in a time input with a String' do
132
+ # Safari doesn't support time inputs - so this is just a text input
139
133
  session.fill_in('form_time', with: '06:30A')
140
134
  session.click_button('awesome')
141
135
  results = extract_results(session)['time']
@@ -143,6 +137,7 @@ RSpec.describe 'Capybara::Session with safari' do
143
137
  end
144
138
 
145
139
  it 'should fill in a datetime input with a String' do
140
+ pending "Safari doesn't support datetime inputs"
146
141
  session.fill_in('form_datetime', with: "06/19/1983\t06:30A")
147
142
  session.click_button('awesome')
148
143
  expect(Time.parse(extract_results(session)['datetime'])).to eq datetime
data/spec/server_spec.rb CHANGED
@@ -83,8 +83,10 @@ RSpec.describe Capybara::Server do
83
83
  server = Capybara::Server.new(app).boot
84
84
 
85
85
  expect do
86
- Net::HTTP.start(server.host, server.port, max_retries: 0) { |http| http.get('/__idntify__') }
87
- end.to raise_error(EOFError)
86
+ Net::HTTP.start(server.host, server.port, max_retries: 0) { |http| http.get('/__identify__') }
87
+ end.to(raise_error do |e|
88
+ expect(e.is_a?(EOFError) || e.is_a?(Net::ReadTimeout)).to be true
89
+ end)
88
90
 
89
91
  res = Net::HTTP.start(server.host, server.port, use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE) do |https|
90
92
  https.get('/')
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'selenium-webdriver'
5
+
6
+ RSpec.shared_examples 'Capybara::Node' do |session, _mode|
7
+ let(:session) { session }
8
+
9
+ context '#content_editable?' do
10
+ it 'returns true when the element is content editable' do
11
+ session.visit('/with_js')
12
+ expect(session.find(:css, '#existing_content_editable').base.content_editable?).to be true
13
+ expect(session.find(:css, '#existing_content_editable_child').base.content_editable?).to be true
14
+ end
15
+
16
+ it 'returns false when the element is not content editable' do
17
+ session.visit('/with_js')
18
+ expect(session.find(:css, '#drag').base.content_editable?).to be false
19
+ end
20
+ end
21
+
22
+ context '#send_keys' do
23
+ it 'should process space' do
24
+ session.visit('/form')
25
+ session.find(:css, '#address1_city').send_keys('ocean', [:shift, :space, 'side'])
26
+ expect(session.find(:css, '#address1_city').value).to eq 'ocean SIDE'
27
+ end
28
+ end
29
+ 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: 3.19.0
4
+ version: 3.20.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: 2019-05-09 00:00:00.000000000 Z
13
+ date: 2019-05-15 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: addressable
@@ -96,6 +96,20 @@ dependencies:
96
96
  - - "~>"
97
97
  - !ruby/object:Gem::Version
98
98
  version: '1.2'
99
+ - !ruby/object:Gem::Dependency
100
+ name: uglifier
101
+ requirement: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ type: :runtime
107
+ prerelease: false
108
+ version_requirements: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
99
113
  - !ruby/object:Gem::Dependency
100
114
  name: xpath
101
115
  requirement: !ruby/object:Gem::Requirement
@@ -487,6 +501,10 @@ files:
487
501
  - lib/capybara/selector/regexp_disassembler.rb
488
502
  - lib/capybara/selector/selector.rb
489
503
  - lib/capybara/selector/xpath_extensions.rb
504
+ - lib/capybara/selenium/atoms/getAttribute.min.js
505
+ - lib/capybara/selenium/atoms/isDisplayed.min.js
506
+ - lib/capybara/selenium/atoms/src/getAttribute.js
507
+ - lib/capybara/selenium/atoms/src/isDisplayed.js
490
508
  - lib/capybara/selenium/driver.rb
491
509
  - lib/capybara/selenium/driver_specializations/chrome_driver.rb
492
510
  - lib/capybara/selenium/driver_specializations/firefox_driver.rb
@@ -501,6 +519,7 @@ files:
501
519
  - lib/capybara/selenium/nodes/firefox_node.rb
502
520
  - lib/capybara/selenium/nodes/ie_node.rb
503
521
  - lib/capybara/selenium/nodes/safari_node.rb
522
+ - lib/capybara/selenium/patches/atoms.rb
504
523
  - lib/capybara/selenium/patches/pause_duration_fix.rb
505
524
  - lib/capybara/selenium/patches/persistent_client.rb
506
525
  - lib/capybara/server.rb
@@ -607,6 +626,7 @@ files:
607
626
  - lib/capybara/spec/session/within_spec.rb
608
627
  - lib/capybara/spec/spec_helper.rb
609
628
  - lib/capybara/spec/test_app.rb
629
+ - lib/capybara/spec/views/animated.erb
610
630
  - lib/capybara/spec/views/buttons.erb
611
631
  - lib/capybara/spec/views/fieldsets.erb
612
632
  - lib/capybara/spec/views/form.erb
@@ -680,6 +700,7 @@ files:
680
700
  - spec/selenium_spec_safari.rb
681
701
  - spec/server_spec.rb
682
702
  - spec/session_spec.rb
703
+ - spec/shared_selenium_node.rb
683
704
  - spec/shared_selenium_session.rb
684
705
  - spec/spec_helper.rb
685
706
  - spec/xpath_builder_spec.rb