capybara 2.13.0 → 2.18.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 (122) hide show
  1. checksums.yaml +5 -5
  2. data/History.md +218 -18
  3. data/README.md +54 -23
  4. data/lib/capybara/config.rb +132 -0
  5. data/lib/capybara/cucumber.rb +1 -0
  6. data/lib/capybara/driver/base.rb +14 -0
  7. data/lib/capybara/dsl.rb +1 -3
  8. data/lib/capybara/helpers.rb +3 -3
  9. data/lib/capybara/minitest/spec.rb +14 -37
  10. data/lib/capybara/minitest.rb +95 -114
  11. data/lib/capybara/node/actions.rb +10 -10
  12. data/lib/capybara/node/base.rb +7 -2
  13. data/lib/capybara/node/element.rb +9 -3
  14. data/lib/capybara/node/finders.rb +92 -18
  15. data/lib/capybara/node/matchers.rb +21 -9
  16. data/lib/capybara/node/simple.rb +5 -0
  17. data/lib/capybara/queries/ancestor_query.rb +25 -0
  18. data/lib/capybara/queries/base_query.rb +12 -3
  19. data/lib/capybara/queries/current_path_query.rb +13 -9
  20. data/lib/capybara/queries/selector_query.rb +62 -23
  21. data/lib/capybara/queries/sibling_query.rb +25 -0
  22. data/lib/capybara/queries/text_query.rb +10 -5
  23. data/lib/capybara/queries/title_query.rb +1 -0
  24. data/lib/capybara/rack_test/browser.rb +13 -5
  25. data/lib/capybara/rack_test/driver.rb +6 -1
  26. data/lib/capybara/rack_test/form.rb +4 -3
  27. data/lib/capybara/rack_test/node.rb +1 -1
  28. data/lib/capybara/rspec/compound.rb +95 -0
  29. data/lib/capybara/rspec/matcher_proxies.rb +45 -0
  30. data/lib/capybara/rspec/matchers.rb +108 -7
  31. data/lib/capybara/rspec.rb +3 -1
  32. data/lib/capybara/selector/filter.rb +13 -41
  33. data/lib/capybara/selector/filter_set.rb +30 -4
  34. data/lib/capybara/selector/filters/base.rb +33 -0
  35. data/lib/capybara/selector/filters/expression_filter.rb +40 -0
  36. data/lib/capybara/selector/filters/node_filter.rb +27 -0
  37. data/lib/capybara/selector/selector.rb +36 -15
  38. data/lib/capybara/selector.rb +63 -42
  39. data/lib/capybara/selenium/driver.rb +177 -33
  40. data/lib/capybara/selenium/node.rb +106 -55
  41. data/lib/capybara/server.rb +6 -5
  42. data/lib/capybara/session/config.rb +114 -0
  43. data/lib/capybara/session/matchers.rb +15 -4
  44. data/lib/capybara/session.rb +178 -65
  45. data/lib/capybara/spec/fixtures/no_extension +1 -0
  46. data/lib/capybara/spec/public/test.js +18 -3
  47. data/lib/capybara/spec/session/accept_alert_spec.rb +9 -1
  48. data/lib/capybara/spec/session/accept_prompt_spec.rb +29 -1
  49. data/lib/capybara/spec/session/all_spec.rb +13 -1
  50. data/lib/capybara/spec/session/ancestor_spec.rb +85 -0
  51. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +24 -8
  52. data/lib/capybara/spec/session/assert_selector.rb +1 -1
  53. data/lib/capybara/spec/session/assert_text.rb +8 -0
  54. data/lib/capybara/spec/session/assert_title.rb +22 -9
  55. data/lib/capybara/spec/session/attach_file_spec.rb +8 -1
  56. data/lib/capybara/spec/session/check_spec.rb +4 -4
  57. data/lib/capybara/spec/session/choose_spec.rb +2 -2
  58. data/lib/capybara/spec/session/click_button_spec.rb +1 -1
  59. data/lib/capybara/spec/session/click_link_or_button_spec.rb +3 -3
  60. data/lib/capybara/spec/session/click_link_spec.rb +1 -1
  61. data/lib/capybara/spec/session/current_url_spec.rb +3 -3
  62. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +3 -3
  63. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +1 -1
  64. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +22 -0
  65. data/lib/capybara/spec/session/evaluate_script_spec.rb +1 -1
  66. data/lib/capybara/spec/session/fill_in_spec.rb +8 -2
  67. data/lib/capybara/spec/session/find_field_spec.rb +1 -0
  68. data/lib/capybara/spec/session/find_spec.rb +8 -6
  69. data/lib/capybara/spec/session/first_spec.rb +10 -5
  70. data/lib/capybara/spec/session/has_all_selectors_spec.rb +69 -0
  71. data/lib/capybara/spec/session/has_css_spec.rb +11 -0
  72. data/lib/capybara/spec/session/has_current_path_spec.rb +52 -7
  73. data/lib/capybara/spec/session/has_link_spec.rb +4 -4
  74. data/lib/capybara/spec/session/has_none_selectors_spec.rb +76 -0
  75. data/lib/capybara/spec/session/has_select_spec.rb +64 -6
  76. data/lib/capybara/spec/session/has_selector_spec.rb +1 -3
  77. data/lib/capybara/spec/session/has_text_spec.rb +5 -3
  78. data/lib/capybara/spec/session/has_title_spec.rb +4 -2
  79. data/lib/capybara/spec/session/has_xpath_spec.rb +5 -3
  80. data/lib/capybara/spec/session/node_spec.rb +50 -26
  81. data/lib/capybara/spec/session/refresh_spec.rb +28 -0
  82. data/lib/capybara/spec/session/reset_session_spec.rb +3 -3
  83. data/lib/capybara/spec/session/select_spec.rb +3 -2
  84. data/lib/capybara/spec/session/sibling_spec.rb +52 -0
  85. data/lib/capybara/spec/session/uncheck_spec.rb +2 -2
  86. data/lib/capybara/spec/session/unselect_spec.rb +2 -2
  87. data/lib/capybara/spec/session/visit_spec.rb +56 -1
  88. data/lib/capybara/spec/session/window/become_closed_spec.rb +11 -11
  89. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +11 -9
  90. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +4 -4
  91. data/lib/capybara/spec/session/window/within_window_spec.rb +27 -2
  92. data/lib/capybara/spec/spec_helper.rb +28 -4
  93. data/lib/capybara/spec/test_app.rb +3 -1
  94. data/lib/capybara/spec/views/form.erb +27 -1
  95. data/lib/capybara/spec/views/initial_alert.erb +10 -0
  96. data/lib/capybara/spec/views/with_fixed_header_footer.erb +17 -0
  97. data/lib/capybara/spec/views/with_hover.erb +5 -0
  98. data/lib/capybara/spec/views/with_html.erb +33 -2
  99. data/lib/capybara/spec/views/with_js.erb +12 -0
  100. data/lib/capybara/spec/views/with_windows.erb +4 -0
  101. data/lib/capybara/version.rb +1 -1
  102. data/lib/capybara/window.rb +1 -1
  103. data/lib/capybara.rb +102 -124
  104. data/spec/capybara_spec.rb +43 -21
  105. data/spec/dsl_spec.rb +1 -0
  106. data/spec/filter_set_spec.rb +28 -0
  107. data/spec/minitest_spec.rb +9 -1
  108. data/spec/minitest_spec_spec.rb +19 -5
  109. data/spec/per_session_config_spec.rb +67 -0
  110. data/spec/result_spec.rb +20 -0
  111. data/spec/rspec/shared_spec_matchers.rb +148 -44
  112. data/spec/rspec/views_spec.rb +4 -0
  113. data/spec/rspec_matchers_spec.rb +46 -0
  114. data/spec/rspec_spec.rb +77 -0
  115. data/spec/selector_spec.rb +2 -1
  116. data/spec/selenium_spec_chrome.rb +25 -17
  117. data/spec/selenium_spec_firefox.rb +2 -1
  118. data/spec/selenium_spec_marionette.rb +18 -5
  119. data/spec/session_spec.rb +44 -0
  120. data/spec/shared_selenium_session.rb +72 -8
  121. data/spec/spec_helper.rb +4 -0
  122. metadata +55 -8
data/spec/rspec_spec.rb CHANGED
@@ -7,6 +7,10 @@ RSpec.describe 'capybara/rspec', :type => :feature do
7
7
  expect(page.body).to include('Another World')
8
8
  end
9
9
 
10
+ it "should include RSpec matcher proxies" do
11
+ expect(self.class.ancestors).to include Capybara::RSpecMatcherProxies
12
+ end
13
+
10
14
  context "resetting session" do
11
15
  it "sets a cookie in one example..." do
12
16
  visit('/set_cookie')
@@ -36,6 +40,79 @@ RSpec.describe 'capybara/rspec', :type => :feature do
36
40
  it "switches to the given driver when giving it as metadata", :driver => :culerity do
37
41
  expect(Capybara.current_driver).to eq(:culerity)
38
42
  end
43
+
44
+ context "#all" do
45
+ it "allows access to the Capybara finder" do
46
+ visit('/with_html')
47
+ expect(all(:css, 'h2.head').size).to eq(5)
48
+ end
49
+
50
+ it "allows access to the RSpec matcher" do
51
+ skip "RSpec < 3 doesn't have an `all` matcher" if rspec2?
52
+
53
+ visit('/with_html')
54
+ expect(["test1", "test2"]).to all(be_a(String))
55
+ end
56
+ end
57
+
58
+ context "#within" do
59
+ it "allows access to the Capybara scoper" do
60
+ visit('/with_html')
61
+ expect do
62
+ within(:css, "#does_not_exist") { click_link "Go to simple" }
63
+ end.to raise_error(Capybara::ElementNotFound)
64
+ end
65
+
66
+ it "allows access to the RSpec matcher" do
67
+ skip "RSpec version doesn't have a 'within' matcher" unless ::RSpec::Matchers.instance_methods.include?(:within)
68
+ visit('/with_html')
69
+ # This reads terribly, but must call #within
70
+ expect(find(:css, 'span.number').text.to_i).to within(1).of(41)
71
+ end
72
+ end
73
+ end
74
+
75
+ RSpec.describe 'capybara/rspec', :type => :other do
76
+ context "when RSpec::Matchers is included after Capybara::DSL" do
77
+ before do
78
+ class DSL_MatchersTest
79
+ include Capybara::DSL
80
+ include RSpec::Matchers
81
+ end
82
+
83
+ @test_class_instance = DSL_MatchersTest.new
84
+ end
85
+
86
+ context "#all" do
87
+ it "allows access to the Capybara finder" do
88
+ @test_class_instance.visit('/with_html')
89
+ expect(@test_class_instance.all(:css, 'h2.head').size).to eq(5)
90
+ end
91
+
92
+ it "allows access to the RSpec matcher" do
93
+ skip "RSpec < 3 doesn't have an `all` matcher" if rspec2?
94
+
95
+ @test_class_instance.visit('/with_html')
96
+ expect(["test1", "test2"]).to @test_class_instance.all(be_a(String))
97
+ end
98
+ end
99
+
100
+ context "#within" do
101
+ it "allows access to the Capybara scoper" do
102
+ @test_class_instance.visit('/with_html')
103
+ expect do
104
+ @test_class_instance.within(:css, "#does_not_exist") { @test_class_instance.click_link "Go to simple" }
105
+ end.to raise_error(Capybara::ElementNotFound)
106
+ end
107
+
108
+ it "allows access to the RSpec matcher" do
109
+ skip "RSpec version doesn't have a 'within' matcher" unless ::RSpec::Matchers.instance_methods.include?(:within)
110
+ @test_class_instance.visit('/with_html')
111
+ # This reads terribly, but must call #within
112
+ expect(@test_class_instance.find(:css, 'span.number').text.to_i).to @test_class_instance.within(1).of(41)
113
+ end
114
+ end
115
+ end
39
116
  end
40
117
 
41
118
  RSpec.describe 'capybara/rspec', :type => :other do
@@ -28,7 +28,7 @@ RSpec.describe Capybara do
28
28
  <input type="hidden" id="hidden_field" value="this is hidden"/>
29
29
  <a href="#">link</a>
30
30
  <fieldset></fieldset>
31
- <select>
31
+ <select id="select">
32
32
  <option value="a">A</option>
33
33
  <option value="b" disabled>B</option>
34
34
  <option value="c" selected>C</option>
@@ -177,6 +177,7 @@ RSpec.describe Capybara do
177
177
 
178
178
  it "finds by type" do
179
179
  expect(string.find(:field, type: 'file')[:id]).to eq 'file'
180
+ expect(string.find(:field, type: 'select')[:id]).to eq 'select'
180
181
  end
181
182
  end
182
183
 
@@ -3,30 +3,34 @@ require 'spec_helper'
3
3
  require 'selenium-webdriver'
4
4
  require 'shared_selenium_session'
5
5
 
6
- Capybara.register_driver :selenium_chrome do |app|
7
- args = ENV['TRAVIS'] ? ['no-sandbox' ] : []
8
- Capybara::Selenium::Driver.new(app, :browser => :chrome, :args => args)
9
- end
6
+ CHROME_DRIVER = if ENV['HEADLESS'] then :selenium_chrome_headless else :selenium_chrome end
7
+
8
+ # if ENV['HEADLESS'] && ENV['TRAVIS']
9
+ # Selenium::WebDriver::Chrome.path='/usr/bin/google-chrome-beta'
10
+ # end
10
11
 
11
12
  Capybara.register_driver :selenium_chrome_clear_storage do |app|
12
- args = ENV['TRAVIS'] ? ['no-sandbox' ] : []
13
- Capybara::Selenium::Driver.new(app, :browser => :chrome,
14
- :args => args,
15
- clear_local_storage: true,
16
- clear_session_storage: true)
13
+ chrome_options = {
14
+ browser: :chrome,
15
+ options: ::Selenium::WebDriver::Chrome::Options.new()
16
+ }
17
+ chrome_options[:options].args << 'headless' if ENV['HEADLESS']
18
+ Capybara::Selenium::Driver.new(app, chrome_options.merge(clear_local_storage: true, clear_session_storage: true))
17
19
  end
18
20
 
19
21
  module TestSessions
20
- Chrome = Capybara::Session.new(:selenium_chrome, TestApp)
22
+ Chrome = Capybara::Session.new(CHROME_DRIVER, TestApp)
21
23
  end
22
24
 
23
25
  skipped_tests = [:response_headers, :status_code, :trigger]
24
- skipped_tests << :windows if ENV['TRAVIS'] && !ENV['WINDOW_TEST']
26
+ # skip window tests when headless for now - closing a window not supported by chromedriver/chrome
27
+ skipped_tests << :windows if ENV['TRAVIS'] && (ENV['SKIP_WINDOW'] || ENV['HEADLESS'])
25
28
 
26
- Capybara::SpecHelper.run_specs TestSessions::Chrome, "selenium_chrome", capybara_skip: skipped_tests
29
+ Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_DRIVER.to_s, capybara_skip: skipped_tests
27
30
 
28
31
  RSpec.describe "Capybara::Session with chrome" do
29
- include_examples "Capybara::Session", TestSessions::Chrome, :selenium_chrome
32
+ include Capybara::SpecHelper
33
+ include_examples "Capybara::Session", TestSessions::Chrome, CHROME_DRIVER
30
34
 
31
35
  context "storage" do
32
36
  describe "#reset!" do
@@ -36,8 +40,10 @@ RSpec.describe "Capybara::Session with chrome" do
36
40
  @session.find(:css, '#set-storage').click
37
41
  @session.reset!
38
42
  @session.visit('/with_js')
39
- expect(@session.driver.browser.local_storage.keys).not_to be_empty
40
- expect(@session.driver.browser.session_storage.keys).not_to be_empty
43
+ # expect(@session.driver.browser.local_storage.keys).not_to be_empty
44
+ # expect(@session.driver.browser.session_storage.keys).not_to be_empty
45
+ expect(@session.evaluate_script('Object.keys(localStorage)')).not_to be_empty
46
+ expect(@session.evaluate_script('Object.keys(sessionStorage)')).not_to be_empty
41
47
  end
42
48
 
43
49
  it "clears storage when set" do
@@ -46,8 +52,10 @@ RSpec.describe "Capybara::Session with chrome" do
46
52
  @session.find(:css, '#set-storage').click
47
53
  @session.reset!
48
54
  @session.visit('/with_js')
49
- expect(@session.driver.browser.local_storage.keys).to be_empty
50
- expect(@session.driver.browser.session_storage.keys).to be_empty
55
+ # expect(@session.driver.browser.local_storage.keys).to be_empty
56
+ # expect(@session.driver.browser.session_storage.keys).to be_empty
57
+ expect(@session.evaluate_script('Object.keys(localStorage)')).to be_empty
58
+ expect(@session.evaluate_script('Object.keys(sessionStorage)')).to be_empty
51
59
  end
52
60
  end
53
61
  end
@@ -31,11 +31,12 @@ skipped_tests = [
31
31
  :status_code,
32
32
  :trigger
33
33
  ]
34
- skipped_tests << :windows if ENV['TRAVIS'] && !ENV['WINDOW_TEST']
34
+ skipped_tests << :windows if ENV['TRAVIS'] && ENV['SKIP_WINDOW']
35
35
 
36
36
  Capybara::SpecHelper.run_specs TestSessions::Selenium, "selenium", capybara_skip: skipped_tests
37
37
 
38
38
  RSpec.describe "Capybara::Session with legacy firefox" do
39
+ include Capybara::SpecHelper
39
40
  include_examples "Capybara::Session", TestSessions::Selenium, :selenium_firefox
40
41
  include_examples Capybara::RSpecMatchers, TestSessions::Selenium, :selenium_firefox
41
42
 
@@ -4,11 +4,20 @@ require "selenium-webdriver"
4
4
  require 'shared_selenium_session'
5
5
  require 'rspec/shared_spec_matchers'
6
6
 
7
+ browser_options = ::Selenium::WebDriver::Firefox::Options.new()
8
+ browser_options.args << '--headless' if ENV['HEADLESS']
9
+ browser_options.add_preference 'dom.file.createInChild', true
10
+ # browser_options.add_option("log", {"level": "trace"})
11
+
7
12
  Capybara.register_driver :selenium_marionette do |app|
13
+ # ::Selenium::WebDriver.logger.level = "debug"
8
14
  Capybara::Selenium::Driver.new(
9
15
  app,
10
16
  browser: :firefox,
11
- desired_capabilities: Selenium::WebDriver::Remote::Capabilities.firefox(marionette: true)
17
+ desired_capabilities: {marionette: true, 'moz:webdriverClick': true},
18
+ options: browser_options
19
+ # Get a trace level log from geckodriver
20
+ # :driver_opts => { args: ['-vv'] }
12
21
  )
13
22
  end
14
23
 
@@ -16,12 +25,15 @@ Capybara.register_driver :selenium_marionette_clear_storage do |app|
16
25
  Capybara::Selenium::Driver.new(
17
26
  app,
18
27
  browser: :firefox,
19
- desired_capabilities: Selenium::WebDriver::Remote::Capabilities.firefox(marionette: true),
28
+ desired_capabilities: {marionette: true},
20
29
  clear_local_storage: true,
21
- clear_session_storage: true
30
+ clear_session_storage: true,
31
+ options: browser_options
22
32
  )
23
33
  end
24
34
 
35
+
36
+
25
37
  module TestSessions
26
38
  SeleniumMarionette = Capybara::Session.new(:selenium_marionette, TestApp)
27
39
  end
@@ -31,18 +43,19 @@ skipped_tests = [
31
43
  :status_code,
32
44
  :trigger
33
45
  ]
34
- skipped_tests << :windows if ENV['TRAVIS'] && !ENV['WINDOW_TEST']
46
+ skipped_tests << :windows if ENV['TRAVIS'] && ENV['SKIP_WINDOW']
35
47
 
36
48
  Capybara::SpecHelper.run_specs TestSessions::SeleniumMarionette, "selenium", capybara_skip: skipped_tests
37
49
 
38
50
  RSpec.describe "Capybara::Session with firefox" do
51
+ include Capybara::SpecHelper
39
52
  include_examples "Capybara::Session", TestSessions::SeleniumMarionette, :selenium_marionette
40
53
  include_examples Capybara::RSpecMatchers, TestSessions::SeleniumMarionette, :selenium_marionette
41
54
  end
42
55
 
43
56
  RSpec.describe Capybara::Selenium::Driver do
44
57
  before do
45
- @driver = Capybara::Selenium::Driver.new(TestApp, browser: :firefox)
58
+ @driver = Capybara::Selenium::Driver.new(TestApp, browser: :firefox, options: browser_options)
46
59
  end
47
60
 
48
61
  describe '#quit' do
data/spec/session_spec.rb CHANGED
@@ -7,4 +7,48 @@ RSpec.describe Capybara::Session do
7
7
  Capybara::Session.new(:unknown, { random: "hash"})
8
8
  end.to raise_error TypeError, "The second parameter to Session::new should be a rack app if passed."
9
9
  end
10
+
11
+ context "current_driver" do
12
+ it "is global when threadsafe false" do
13
+ Capybara.threadsafe = false
14
+ Capybara.current_driver = :selenium
15
+ thread = Thread.new do
16
+ Capybara.current_driver = :random
17
+ end
18
+ thread.join
19
+ expect(Capybara.current_driver).to eq :random
20
+ end
21
+
22
+ it "is thread specific threadsafe true" do
23
+ Capybara.threadsafe = true
24
+ Capybara.current_driver = :selenium
25
+ thread = Thread.new do
26
+ Capybara.current_driver = :random
27
+ end
28
+ thread.join
29
+ expect(Capybara.current_driver).to eq :selenium
30
+ end
31
+ end
32
+
33
+ context "session_name" do
34
+ it "is global when threadsafe false" do
35
+ Capybara.threadsafe = false
36
+ Capybara.session_name = "sess1"
37
+ thread = Thread.new do
38
+ Capybara.session_name = "sess2"
39
+ end
40
+ thread.join
41
+ expect(Capybara.session_name).to eq "sess2"
42
+ end
43
+
44
+ it "is thread specific when threadsafe true" do
45
+ Capybara.threadsafe = true
46
+ Capybara.session_name = "sess1"
47
+ thread = Thread.new do
48
+ Capybara.session_name = "sess2"
49
+ end
50
+ thread.join
51
+ expect(Capybara.session_name).to eq "sess1"
52
+ end
53
+ end
10
54
  end
@@ -34,6 +34,8 @@ RSpec.shared_examples "Capybara::Session" do |session, mode|
34
34
  before do
35
35
  @current_dir = Dir.getwd
36
36
  Dir.chdir(File.join(File.dirname(__FILE__), '..'))
37
+ @env = { 'SELENIUM_BROWSER' => @session.driver.options[:browser].to_s }
38
+ @env['LEGACY_FIREFOX'] = 'TRUE' if mode == :selenium_firefox
37
39
  end
38
40
 
39
41
  after do
@@ -41,16 +43,14 @@ RSpec.shared_examples "Capybara::Session" do |session, mode|
41
43
  end
42
44
 
43
45
  it "should have return code 1 when running selenium_driver_rspec_failure.rb" do
44
- env = { 'SELENIUM_BROWSER' => @session.driver.options[:browser].to_s,
45
- 'LEGACY_FIREFOX' => (mode == :selenium_firefox ? 'TRUE' : nil) }
46
- system(env, 'rspec spec/fixtures/selenium_driver_rspec_failure.rb', out: File::NULL, err: File::NULL)
46
+ skip if ENV['HEADLESS']
47
+ system(@env, 'rspec spec/fixtures/selenium_driver_rspec_failure.rb', out: File::NULL, err: File::NULL)
47
48
  expect($?.exitstatus).to eq(1)
48
49
  end
49
50
 
50
51
  it "should have return code 0 when running selenium_driver_rspec_success.rb" do
51
- env = { 'SELENIUM_BROWSER' => @session.driver.options[:browser].to_s,
52
- 'LEGACY_FIREFOX' => (mode == :selenium_firefox ? 'TRUE' : nil) }
53
- system(env, 'rspec spec/fixtures/selenium_driver_rspec_success.rb', out: File::NULL, err: File::NULL)
52
+ skip if ENV['HEADLESS']
53
+ system(@env, 'rspec spec/fixtures/selenium_driver_rspec_success.rb', out: File::NULL, err: File::NULL)
54
54
  expect($?.exitstatus).to eq(0)
55
55
  end
56
56
  end
@@ -60,7 +60,24 @@ RSpec.shared_examples "Capybara::Session" do |session, mode|
60
60
  @session.visit('/with_js')
61
61
  @session.click_link('Open alert')
62
62
  @session.accept_alert
63
- expect{@session.driver.browser.switch_to.alert}.to raise_error(Selenium::WebDriver::Error::NoAlertPresentError)
63
+ expect{@session.driver.browser.switch_to.alert}.to raise_error(@session.driver.send(:modal_error))
64
+ end
65
+
66
+ it "can be called before visiting" do
67
+ @session.accept_alert "Initial alert" do
68
+ @session.visit('/initial_alert')
69
+ end
70
+ expect(@session).to have_text('Initial alert page')
71
+ end
72
+ end
73
+
74
+ context '#fill_in_with empty string and no options' do
75
+ it 'should trigger change when clearing a field' do
76
+ @session.visit('/with_js')
77
+ @session.fill_in('with_change_event', with: '')
78
+ # click outside the field to trigger the change event
79
+ @session.find(:css, 'body').click
80
+ expect(@session).to have_selector(:css, '.change_event_triggered', match: :one)
64
81
  end
65
82
  end
66
83
 
@@ -89,6 +106,15 @@ RSpec.shared_examples "Capybara::Session" do |session, mode|
89
106
  @session.find(:css, 'body').click
90
107
  expect(@session).to have_selector(:css, '.change_event_triggered', match: :one)
91
108
  end
109
+
110
+ it 'should trigger input event field_value.length times' do
111
+ @session.visit('/with_js')
112
+ @session.fill_in('with_change_event', with: '',
113
+ fill_options: { :clear => :backspace })
114
+ # click outside the field to trigger the change event
115
+ @session.find(:css, 'body').click
116
+ expect(@session).to have_xpath('//p[@class="input_event_triggered"]', count: 13)
117
+ end
92
118
  end
93
119
 
94
120
  context "#fill_in with { clear: :none } fill_options" do
@@ -102,7 +128,7 @@ RSpec.shared_examples "Capybara::Session" do |session, mode|
102
128
 
103
129
  context "#fill_in with { clear: Array } fill_options" do
104
130
  it 'should pass the array through to the element' do
105
- pending "selenium-webdriver/geckodriver doesn't support complex sets of characters" if @session.driver.marionette?
131
+ pending "selenium-webdriver/geckodriver doesn't support complex sets of characters" if marionette?(@session)
106
132
  #this is mainly for use with [[:control, 'a'], :backspace] - however since that is platform dependant I'm testing with something less useful
107
133
  @session.visit('/form')
108
134
  @session.fill_in('form_first_name', with: 'Harry',
@@ -120,6 +146,14 @@ RSpec.shared_examples "Capybara::Session" do |session, mode|
120
146
  end
121
147
  end
122
148
 
149
+ describe "all with disappearing elements" do
150
+ it "ignores stale elements in results" do
151
+ @session.visit('/path')
152
+ elements = @session.all(:link) { |node| raise Selenium::WebDriver::Error::StaleElementReferenceError }
153
+ expect(elements.size).to eq 0
154
+ end
155
+ end
156
+
123
157
  describe "#evaluate_script" do
124
158
  it "can return an element" do
125
159
  @session.visit('/form')
@@ -146,6 +180,36 @@ RSpec.shared_examples "Capybara::Session" do |session, mode|
146
180
  }
147
181
  })
148
182
  end
183
+
184
+ describe "#evaluate_async_script" do
185
+ it "will timeout if the script takes too long" do
186
+ @session.visit('/with_js')
187
+ expect do
188
+ @session.using_wait_time(1) do
189
+ @session.evaluate_async_script("var cb = arguments[0]; setTimeout(function(){ cb(null) }, 3000)")
190
+ end
191
+ end.to raise_error Selenium::WebDriver::Error::ScriptTimeoutError
192
+ end
193
+ end
194
+ end
195
+
196
+ describe "Element#inspect" do
197
+ it "outputs obsolete elements" do
198
+ @session.visit('/form')
199
+ el = @session.find(:button, 'Click me!').click
200
+ expect(@session).to have_no_button('Click me!')
201
+ expect(el).not_to receive(:synchronize)
202
+ expect(el.inspect).to eq "Obsolete #<Capybara::Node::Element>"
203
+ end
204
+ end
205
+
206
+ describe "Element#click" do
207
+ it "should handle fixed headers/footers" do
208
+ @session.visit('/with_fixed_header_footer')
209
+ # @session.click_link('Go to root')
210
+ @session.find(:link, 'Go to root').click
211
+ expect(@session).to have_current_path('/')
212
+ end
149
213
  end
150
214
  end
151
215
  end
data/spec/spec_helper.rb CHANGED
@@ -8,3 +8,7 @@ RSpec.configure do |config|
8
8
  config.filter_run_including focus_: true unless ENV['TRAVIS']
9
9
  config.run_all_when_everything_filtered = true
10
10
  end
11
+
12
+ def rspec2?
13
+ !defined?(::RSpec::Expectations::Version) || (Gem::Version.new(RSpec::Expectations::Version::STRING) < Gem::Version.new('3.0'))
14
+ end