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
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+ Capybara::SpecHelper.spec '#have_all_selectors' do
3
+ before do
4
+ @session.visit('/with_html')
5
+ end
6
+
7
+ it "should be true if the given selectors are on the page" do
8
+ expect(@session).to have_all_of_selectors(:css, "p a#foo", "h2#h2one", "h2#h2two" )
9
+ end
10
+
11
+ it "should be false if any of the given selectors are not on the page" do
12
+ expect {
13
+ expect(@session).to have_all_of_selectors(:css, "p a#foo", "h2#h2three", "h2#h2one")
14
+ }.to raise_error ::RSpec::Expectations::ExpectationNotMetError
15
+ end
16
+
17
+ it "should use default selector" do
18
+ Capybara.default_selector = :css
19
+ expect(@session).to have_all_of_selectors("p a#foo", "h2#h2two", "h2#h2one" )
20
+ expect {
21
+ expect(@session).to have_all_of_selectors("p a#foo", "h2#h2three", "h2#h2one")
22
+ }.to raise_error ::RSpec::Expectations::ExpectationNotMetError
23
+ end
24
+
25
+ context "should respect scopes" do
26
+ it "when used with `within`" do
27
+ @session.within "//p[@id='first']" do
28
+ expect(@session).to have_all_of_selectors(".//a[@id='foo']")
29
+ expect {
30
+ expect(@session).to have_all_of_selectors(".//a[@id='red']")
31
+ }.to raise_error ::RSpec::Expectations::ExpectationNotMetError
32
+ end
33
+ end
34
+
35
+ it "when called on elements" do
36
+ el = @session.find "//p[@id='first']"
37
+ expect(el).to have_all_of_selectors(".//a[@id='foo']")
38
+ expect {
39
+ expect(el).to have_all_of_selectors(".//a[@id='red']")
40
+ }.to raise_error ::RSpec::Expectations::ExpectationNotMetError
41
+ end
42
+ end
43
+
44
+ context "with options" do
45
+ it "should apply options to all locators" do
46
+ expect(@session).to have_all_of_selectors(:field, 'normal', 'additional_newline', type: :textarea)
47
+ expect {
48
+ expect(@session).to have_all_of_selectors(:field, 'normal', 'test_field', 'additional_newline', type: :textarea)
49
+ }.to raise_error ::RSpec::Expectations::ExpectationNotMetError
50
+ end
51
+ end
52
+
53
+ context "with wait", requires: [:js] do
54
+ it "should not raise error if all the elements appear before given wait duration" do
55
+ Capybara.using_wait_time(0.1) do
56
+ @session.visit('/with_js')
57
+ @session.click_link('Click me')
58
+ expect(@session).to have_all_of_selectors(:css, "a#clickable", "a#has-been-clicked", '#drag', wait: 0.9)
59
+ end
60
+ end
61
+ end
62
+
63
+ it "cannot be negated" do
64
+ expect {
65
+ expect(@session).not_to have_all_of_selectors(:css, "p a#foo", "h2#h2one", "h2#h2two")
66
+ }.to raise_error ArgumentError
67
+ end
68
+ end
69
+
@@ -112,6 +112,17 @@ Capybara::SpecHelper.spec '#has_css?' do
112
112
  expect(@session).not_to have_css("p a", text: /Red$/)
113
113
  end
114
114
  end
115
+
116
+ it "should allow escapes in the CSS selector" do
117
+ if (defined?(TestClass) && @session.is_a?(TestClass)) || @session.driver.is_a?(Capybara::RackTest::Driver)
118
+ # Nokogiri doesn't unescape CSS selectors when converting from CSS to XPath
119
+ # See: https://github.com/teamcapybara/capybara/issues/1866
120
+ # Also: https://github.com/sparklemotion/nokogiri/pull/1646
121
+ pending "Current Nokogiri doesn't handle escapes in CSS attribute selectors correctly"
122
+ end
123
+ expect(@session).to have_css('p[data-random="abc\\\\def"]')
124
+ expect(@session).to have_css("p[data-random='#{Capybara::Selector::CSS.escape('abc\def')}']")
125
+ end
115
126
  end
116
127
 
117
128
  Capybara::SpecHelper.spec '#has_no_css?' do
@@ -13,6 +13,12 @@ Capybara::SpecHelper.spec '#has_current_path?' do
13
13
  expect(@session).not_to have_current_path(/monkey/)
14
14
  end
15
15
 
16
+ it "should not raise an error when non-http" do
17
+ @session.reset_session!
18
+ expect(@session.has_current_path?(/monkey/)).to eq false
19
+ expect(@session.has_current_path?("/with_js")).to eq false
20
+ end
21
+
16
22
  it "should handle non-escaped query options" do
17
23
  @session.click_link("Non-escaped query options")
18
24
  expect(@session).to have_current_path("/with_html?options[]=things")
@@ -25,7 +31,7 @@ Capybara::SpecHelper.spec '#has_current_path?' do
25
31
 
26
32
  it "should wait for current_path", requires: [:js] do
27
33
  @session.click_link("Change page")
28
- expect(@session).to have_current_path("/with_html")
34
+ expect(@session).to have_current_path("/with_html", wait: 3)
29
35
  end
30
36
 
31
37
  it "should be false if the page has not the given current_path" do
@@ -37,20 +43,47 @@ Capybara::SpecHelper.spec '#has_current_path?' do
37
43
  expect(@session).to have_current_path('/with_js?test=test')
38
44
  end
39
45
 
40
- it "should compare the full url" do
46
+ it "should compare the full url if url: true is used" do
41
47
  expect(@session).to have_current_path(%r{\Ahttp://[^/]*/with_js\Z}, url: true)
48
+ domain_port = if @session.respond_to?(:server) && @session.server
49
+ "#{@session.server.host}:#{@session.server.port}"
50
+ else
51
+ "www.example.com"
52
+ end
53
+ expect(@session).to have_current_path("http://#{domain_port}/with_js", url: true)
54
+ end
55
+
56
+ it "should not compare the full url if url: true is not passed" do
57
+ expect(@session).to have_current_path(%r{^/with_js\Z})
58
+ expect(@session).to have_current_path('/with_js')
59
+ end
60
+
61
+ it "should not compare the full url if url: false is passed" do
62
+ expect(@session).to have_current_path(%r{^/with_js\Z}, url: false)
63
+ expect(@session).to have_current_path('/with_js', url: false)
64
+ end
65
+
66
+ it "should default to full url if value is a url" do
67
+ url = @session.current_url
68
+ expect(url).to match /with_js$/
69
+ expect(@session).to have_current_path(url)
70
+ expect(@session).not_to have_current_path("http://www.not_example.com/with_js")
42
71
  end
43
72
 
44
73
  it "should ignore the query" do
45
74
  @session.visit('/with_js?test=test')
46
75
  expect(@session).to have_current_path('/with_js?test=test')
47
76
  expect(@session).to have_current_path('/with_js', only_path: true)
77
+ expect(@session).to have_current_path('/with_js', ignore_query: true)
78
+ uri = ::Addressable::URI.parse(@session.current_url)
79
+ uri.query = nil
80
+ expect(@session).to have_current_path(uri.to_s, ignore_query: true)
48
81
  end
49
82
 
50
83
  it "should not allow url and only_path at the same time" do
51
84
  expect {
52
85
  expect(@session).to have_current_path('/with_js', url: true, only_path: true)
53
- }. to raise_error ArgumentError
86
+ }.to raise_error ArgumentError
54
87
  end
55
88
 
56
89
  it "should not raise an exception if the current_url is nil" do
@@ -59,12 +92,17 @@ Capybara::SpecHelper.spec '#has_current_path?' do
59
92
  # Without only_path option
60
93
  expect {
61
94
  expect(@session).to have_current_path(nil)
62
- }. not_to raise_exception
95
+ }.not_to raise_exception
63
96
 
64
97
  # With only_path option
65
98
  expect {
66
99
  expect(@session).to have_current_path(nil, only_path: true)
67
- }. not_to raise_exception
100
+ }.not_to raise_exception
101
+
102
+ # With ignore_query option
103
+ expect {
104
+ expect(@session).to have_current_path(nil, ignore_query: true)
105
+ }.not_to raise_exception
68
106
  end
69
107
  end
70
108
 
@@ -83,8 +121,10 @@ Capybara::SpecHelper.spec '#has_no_current_path?' do
83
121
  end
84
122
 
85
123
  it "should wait for current_path to disappear", requires: [:js] do
86
- @session.click_link("Change page")
87
- expect(@session).to have_no_current_path('/with_js')
124
+ Capybara.using_wait_time(3) do
125
+ @session.click_link("Change page")
126
+ expect(@session).to have_no_current_path('/with_js')
127
+ end
88
128
  end
89
129
 
90
130
  it "should be true if the page has not the given current_path" do
@@ -103,5 +143,10 @@ Capybara::SpecHelper.spec '#has_no_current_path?' do
103
143
  expect {
104
144
  expect(@session).not_to have_current_path('/with_js', only_path: true)
105
145
  }. not_to raise_exception
146
+
147
+ # With ignore_query option
148
+ expect {
149
+ expect(@session).not_to have_current_path('/with_js', ignore_query: true)
150
+ }. not_to raise_exception
106
151
  end
107
152
  end
@@ -14,8 +14,8 @@ Capybara::SpecHelper.spec '#has_link?' do
14
14
 
15
15
  it "should be false if the given link is not on the page" do
16
16
  expect(@session).not_to have_link('monkey')
17
- expect(@session).not_to have_link('A link', href: '/non-existant-href')
18
- expect(@session).not_to have_link('A link', href: /non-existant/)
17
+ expect(@session).not_to have_link('A link', href: '/nonexistent-href')
18
+ expect(@session).not_to have_link('A link', href: /nonexistent/)
19
19
  end
20
20
  end
21
21
 
@@ -32,7 +32,7 @@ Capybara::SpecHelper.spec '#has_no_link?' do
32
32
 
33
33
  it "should be true if the given link is not on the page" do
34
34
  expect(@session).to have_no_link('monkey')
35
- expect(@session).to have_no_link('A link', href: '/non-existant-href')
36
- expect(@session).to have_no_link('A link', href: /\/non-existant-href/)
35
+ expect(@session).to have_no_link('A link', href: '/nonexistent-href')
36
+ expect(@session).to have_no_link('A link', href: /\/nonexistent-href/)
37
37
  end
38
38
  end
@@ -0,0 +1,76 @@
1
+ Capybara::SpecHelper.spec '#have_none_of_selectors' do
2
+ before do
3
+ @session.visit('/with_html')
4
+ end
5
+
6
+ it "should be false if any of the given locators are on the page" do
7
+ expect {
8
+ expect(@session).to have_none_of_selectors(:xpath, "//p", "//a")
9
+ }.to raise_error ::RSpec::Expectations::ExpectationNotMetError
10
+ expect {
11
+ expect(@session).to have_none_of_selectors(:css, "p a#foo")
12
+ }.to raise_error ::RSpec::Expectations::ExpectationNotMetError
13
+ end
14
+
15
+ it "should be true if none of the given locators are on the page" do
16
+ expect(@session).to have_none_of_selectors(:xpath, "//abbr", "//td" )
17
+ expect(@session).to have_none_of_selectors(:css, "p a#doesnotexist", "abbr")
18
+ end
19
+
20
+ it "should use default selector" do
21
+ Capybara.default_selector = :css
22
+ expect(@session).to have_none_of_selectors("p a#doesnotexist", "abbr")
23
+ expect {
24
+ expect(@session).to have_none_of_selectors("abbr", "p a#foo")
25
+ }.to raise_error ::RSpec::Expectations::ExpectationNotMetError
26
+ end
27
+
28
+ context "should respect scopes" do
29
+ it "when used with `within`" do
30
+ @session.within "//p[@id='first']" do
31
+ expect {
32
+ expect(@session).to have_none_of_selectors(".//a[@id='foo']")
33
+ }.to raise_error ::RSpec::Expectations::ExpectationNotMetError
34
+ expect(@session).to have_none_of_selectors(".//a[@id='red']")
35
+ end
36
+ end
37
+
38
+ it "when called on an element" do
39
+ el = @session.find "//p[@id='first']"
40
+ expect {
41
+ expect(el).to have_none_of_selectors(".//a[@id='foo']")
42
+ }.to raise_error ::RSpec::Expectations::ExpectationNotMetError
43
+ expect(el).to have_none_of_selectors(".//a[@id='red']")
44
+ end
45
+ end
46
+
47
+ context "with options" do
48
+ it "should apply the options to all locators" do
49
+ expect {
50
+ expect(@session).to have_none_of_selectors("//p//a", text: "Redirect")
51
+ }.to raise_error ::RSpec::Expectations::ExpectationNotMetError
52
+ expect(@session).to have_none_of_selectors("//p", text: "Doesnotexist")
53
+ end
54
+
55
+ it "should discard all matches where the given regexp is matched" do
56
+ expect {
57
+ expect(@session).to have_none_of_selectors("//p//a", text: /re[dab]i/i, count: 1)
58
+ }.to raise_error ::RSpec::Expectations::ExpectationNotMetError
59
+ expect(@session).to have_none_of_selectors("//p//a", text: /Red$/)
60
+ end
61
+ end
62
+
63
+ context "with wait", requires: [:js] do
64
+ it "should not find elements if they appear after given wait duration" do
65
+ @session.visit('/with_js')
66
+ @session.click_link('Click me')
67
+ expect(@session).to have_none_of_selectors(:css, "#new_field", "a#has-been-clicked", wait: 0.1)
68
+ end
69
+ end
70
+
71
+ it "cannot be negated" do
72
+ expect {
73
+ expect(@session).not_to have_none_of_selectors(:css, "p a#foo", "h2#h2one", "h2#h2two")
74
+ }.to raise_error ArgumentError
75
+ end
76
+ end
@@ -27,7 +27,7 @@ Capybara::SpecHelper.spec '#has_select?' do
27
27
  expect(@session).not_to have_select('Does not exist', selected: 'John')
28
28
  expect(@session).not_to have_select('City', selected: 'Not there')
29
29
  expect(@session).not_to have_select('Underwear', selected: [
30
- 'Boxerbriefs', 'Briefs', 'Commando', "Frenchman's Pantalons", 'Long Johns', 'Nonexistant'
30
+ 'Boxerbriefs', 'Briefs', 'Commando', "Frenchman's Pantalons", 'Long Johns', 'Nonexistent'
31
31
  ])
32
32
  expect(@session).not_to have_select('Underwear', selected: [
33
33
  'Boxerbriefs', 'Briefs', 'Boxers', 'Commando', "Frenchman's Pantalons", 'Long Johns'
@@ -67,6 +67,36 @@ Capybara::SpecHelper.spec '#has_select?' do
67
67
  end
68
68
  end
69
69
 
70
+ context 'with partial select' do
71
+ it "should be true if a field with the given partial values is on the page" do
72
+ expect(@session).to have_select('Underwear', with_selected: ['Boxerbriefs', 'Briefs'])
73
+ end
74
+
75
+ it "should be false if a field with the given partial values is not on the page" do
76
+ expect(@session).not_to have_select('Underwear', with_selected: ['Boxerbriefs', 'Boxers'])
77
+ end
78
+
79
+ it "should be true after the given partial value is selected" do
80
+ @session.select('Boxers', from: 'Underwear')
81
+ expect(@session).to have_select('Underwear', with_selected: ['Boxerbriefs', 'Boxers'])
82
+ end
83
+
84
+ it "should be false after one of the given partial values is unselected" do
85
+ @session.unselect('Briefs', from: 'Underwear')
86
+ expect(@session).not_to have_select('Underwear', with_selected: ['Boxerbriefs', 'Briefs'])
87
+ end
88
+
89
+ it "should be true even when the selected values are invisible, regardless of the select's visibility" do
90
+ expect(@session).to have_select('Dessert', visible: false, with_options: ['Pudding', 'Tiramisu'])
91
+ expect(@session).to have_select('Cake', with_selected: ['Chocolate Cake', 'Sponge Cake'])
92
+ end
93
+
94
+ it "should support non array partial values" do
95
+ expect(@session).to have_select('Underwear', with_selected: 'Briefs')
96
+ expect(@session).not_to have_select('Underwear', with_selected: 'Boxers')
97
+ end
98
+ end
99
+
70
100
  context 'with exact options' do
71
101
  it "should be true if a field with the given options is on the page" do
72
102
  expect(@session).to have_select('Region', options: ['Norway', 'Sweden', 'Finland'])
@@ -81,10 +111,9 @@ Capybara::SpecHelper.spec '#has_select?' do
81
111
  expect(@session).not_to have_select('Region', options: ['Norway', 'Norway', 'Norway'])
82
112
  end
83
113
 
84
- it" should be true even when the options are invisible, if the select itself is invisible" do
114
+ it "should be true even when the options are invisible, if the select itself is invisible" do
85
115
  expect(@session).to have_select("Icecream", visible: false, options: ['Chocolate', 'Vanilla', 'Strawberry'])
86
116
  end
87
-
88
117
  end
89
118
 
90
119
  context 'with partial options' do
@@ -99,7 +128,7 @@ Capybara::SpecHelper.spec '#has_select?' do
99
128
  expect(@session).not_to have_select('Region', with_options: ['Norway', 'Sweden', 'Finland', 'Latvia'])
100
129
  end
101
130
 
102
- it" should be true even when the options are invisible, if the select itself is invisible" do
131
+ it "should be true even when the options are invisible, if the select itself is invisible" do
103
132
  expect(@session).to have_select("Icecream", visible: false, with_options: ['Vanilla', 'Strawberry'])
104
133
  end
105
134
  end
@@ -123,7 +152,9 @@ Capybara::SpecHelper.spec '#has_select?' do
123
152
 
124
153
  it "should support locator-less usage" do
125
154
  expect(@session.has_select?(with_options: ['Norway', 'Sweden'])).to eq true
126
- expect(@session).to have_select(with_options: ['London'] )
155
+ expect(@session).to have_select(with_options: ['London'])
156
+ expect(@session.has_select?(with_selected: ['Commando', 'Boxerbriefs'])).to eq true
157
+ expect(@session).to have_select(with_selected: ['Briefs'])
127
158
  end
128
159
  end
129
160
 
@@ -154,7 +185,7 @@ Capybara::SpecHelper.spec '#has_no_select?' do
154
185
  expect(@session).to have_no_select('Does not exist', selected: 'John')
155
186
  expect(@session).to have_no_select('City', selected: 'Not there')
156
187
  expect(@session).to have_no_select('Underwear', selected: [
157
- 'Boxerbriefs', 'Briefs', 'Commando', "Frenchman's Pantalons", 'Long Johns', 'Nonexistant'
188
+ 'Boxerbriefs', 'Briefs', 'Commando', "Frenchman's Pantalons", 'Long Johns', 'Nonexistent'
158
189
  ])
159
190
  expect(@session).to have_no_select('Underwear', selected: [
160
191
  'Boxerbriefs', 'Briefs', 'Boxers', 'Commando', "Frenchman's Pantalons", 'Long Johns'
@@ -189,6 +220,31 @@ Capybara::SpecHelper.spec '#has_no_select?' do
189
220
  end
190
221
  end
191
222
 
223
+ context 'with partial select' do
224
+ it "should be false if a field with the given partial values is on the page" do
225
+ expect(@session).not_to have_no_select('Underwear', with_selected: ['Boxerbriefs', 'Briefs'])
226
+ end
227
+
228
+ it "should be true if a field with the given partial values is not on the page" do
229
+ expect(@session).to have_no_select('Underwear', with_selected: ['Boxerbriefs', 'Boxers'])
230
+ end
231
+
232
+ it "should be false after the given partial value is selected" do
233
+ @session.select('Boxers', from: 'Underwear')
234
+ expect(@session).not_to have_no_select('Underwear', with_selected: ['Boxerbriefs', 'Boxers'])
235
+ end
236
+
237
+ it "should be true after one of the given partial values is unselected" do
238
+ @session.unselect('Briefs', from: 'Underwear')
239
+ expect(@session).to have_no_select('Underwear', with_selected: ['Boxerbriefs', 'Briefs'])
240
+ end
241
+
242
+ it "should support non array partial values" do
243
+ expect(@session).not_to have_no_select('Underwear', with_selected: 'Briefs')
244
+ expect(@session).to have_no_select('Underwear', with_selected: 'Boxers')
245
+ end
246
+ end
247
+
192
248
  context 'with exact options' do
193
249
  it "should be false if a field with the given options is on the page" do
194
250
  expect(@session).not_to have_no_select('Region', options: ['Norway', 'Sweden', 'Finland'])
@@ -219,5 +275,7 @@ Capybara::SpecHelper.spec '#has_no_select?' do
219
275
  it "should support locator-less usage" do
220
276
  expect(@session.has_no_select?(with_options: ['Norway', 'Sweden', 'Finland', 'Latvia'])).to eq true
221
277
  expect(@session).to have_no_select(with_options: ['New London'] )
278
+ expect(@session.has_no_select?(with_selected: ['Boxers'])).to eq true
279
+ expect(@session).to have_no_select(with_selected: ['Commando', 'Boxers'])
222
280
  end
223
281
  end
@@ -131,9 +131,7 @@ Capybara::SpecHelper.spec '#has_no_selector?' do
131
131
  end
132
132
 
133
133
  it "should accept a filter block" do
134
- if !defined?(::RSpec::Expectations::Version) || (Gem::Version.new(RSpec::Expectations::Version::STRING) < Gem::Version.new('3.0'))
135
- skip "RSpec < 3 doesn't pass the block along to the matcher for the Builtin::Has matcher"
136
- end
134
+ skip "RSpec < 3 doesn't pass the block along to the matcher for the Builtin::Has matcher" if rspec2?
137
135
  expect(@session).to have_no_selector(:css, "a#foo") { |el| el[:id] != "foo" }
138
136
  end
139
137
 
@@ -125,9 +125,11 @@ Capybara::SpecHelper.spec '#has_text?' do
125
125
  end
126
126
 
127
127
  it "should wait for text to appear", requires: [:js] do
128
- @session.visit('/with_js')
129
- @session.click_link('Click me')
130
- expect(@session).to have_text("Has been clicked")
128
+ Capybara.using_wait_time(3) do
129
+ @session.visit('/with_js')
130
+ @session.click_link('Click me')
131
+ expect(@session).to have_text("Has been clicked")
132
+ end
131
133
  end
132
134
 
133
135
  context "with between" do
@@ -53,8 +53,10 @@ Capybara::SpecHelper.spec '#has_no_title?' do
53
53
  end
54
54
 
55
55
  it "should wait for title to disappear", requires: [:js] do
56
- @session.click_link("Change title")
57
- expect(@session).to have_no_title('with_js')
56
+ Capybara.using_wait_time(5) do
57
+ @session.click_link("Change title") # triggers title change after 400ms
58
+ expect(@session).to have_no_title('with_js')
59
+ end
58
60
  end
59
61
 
60
62
  it "should be true if the page has not the given title" do
@@ -29,9 +29,11 @@ Capybara::SpecHelper.spec '#has_xpath?' do
29
29
  end
30
30
 
31
31
  it "should wait for content to appear", requires: [:js] do
32
- @session.visit('/with_js')
33
- @session.click_link('Click me')
34
- expect(@session).to have_xpath("//input[@type='submit' and @value='New Here']")
32
+ Capybara.using_wait_time(3) do
33
+ @session.visit('/with_js')
34
+ @session.click_link('Click me') # updates page after 500ms
35
+ expect(@session).to have_xpath("//input[@type='submit' and @value='New Here']")
36
+ end
35
37
  end
36
38
 
37
39
  context "with count" do
@@ -122,23 +122,25 @@ Capybara::SpecHelper.spec "node" do
122
122
  expect(@session.first('//textarea[@readonly]').set('changed')).to raise_error(Capybara::ReadOnlyElementError)
123
123
  end if Capybara::VERSION.to_f > 3.0
124
124
 
125
- it 'should allow me to change the contents of a contenteditable element', requires: [:js] do
126
- @session.visit('/with_js')
127
- @session.find(:css,'#existing_content_editable').set('WYSIWYG')
128
- expect(@session.find(:css,'#existing_content_editable').text).to eq('WYSIWYG')
129
- end
125
+ context "with a contenteditable element", requires: [:js] do
126
+ it 'should allow me to change the contents' do
127
+ @session.visit('/with_js')
128
+ @session.find(:css,'#existing_content_editable').set('WYSIWYG')
129
+ expect(@session.find(:css,'#existing_content_editable').text).to eq('WYSIWYG')
130
+ end
130
131
 
131
- it 'should allow me to set the contents of a contenteditable element', requires: [:js] do
132
- @session.visit('/with_js')
133
- @session.find(:css,'#blank_content_editable').set('WYSIWYG')
134
- expect(@session.find(:css,'#blank_content_editable').text).to eq('WYSIWYG')
135
- end
132
+ it 'should allow me to set the contents' do
133
+ @session.visit('/with_js')
134
+ @session.find(:css,'#blank_content_editable').set('WYSIWYG')
135
+ expect(@session.find(:css,'#blank_content_editable').text).to eq('WYSIWYG')
136
+ end
136
137
 
137
- it 'should allow me to change the contents of a contenteditable elements child', requires: [:js] do
138
- @session.visit('/with_js')
139
- @session.find(:css,'#existing_content_editable_child').set('WYSIWYG')
140
- expect(@session.find(:css,'#existing_content_editable_child').text).to eq('WYSIWYG')
141
- expect(@session.find(:css,'#existing_content_editable_child_parent').text).to eq('Some content WYSIWYG')
138
+ it 'should allow me to change the contents of a child element' do
139
+ @session.visit('/with_js')
140
+ @session.find(:css,'#existing_content_editable_child').set('WYSIWYG')
141
+ expect(@session.find(:css,'#existing_content_editable_child').text).to eq('WYSIWYG')
142
+ expect(@session.find(:css,'#existing_content_editable_child_parent').text).to eq('Some content WYSIWYG')
143
+ end
142
144
  end
143
145
  end
144
146
 
@@ -289,22 +291,35 @@ Capybara::SpecHelper.spec "node" do
289
291
 
290
292
  describe '#drag_to', requires: [:js, :drag] do
291
293
  it "should drag and drop an object" do
292
- pending "selenium-webdriver/geckodriver doesn't support mouse move_to" if marionette?(@session)
293
294
  @session.visit('/with_js')
294
295
  element = @session.find('//div[@id="drag"]')
295
296
  target = @session.find('//div[@id="drop"]')
296
297
  element.drag_to(target)
297
298
  expect(@session.find('//div[contains(., "Dropped!")]')).not_to be_nil
298
299
  end
300
+
301
+ it "should drag and drop if scrolling is needed" do
302
+ @session.visit('/with_js')
303
+ element = @session.find('//div[@id="drag_scroll"]')
304
+ target = @session.find('//div[@id="drop_scroll"]')
305
+ element.drag_to(target)
306
+ expect(@session.find('//div[contains(., "Dropped!")]')).not_to be_nil
307
+ end
299
308
  end
300
309
 
301
310
  describe '#hover', requires: [:hover] do
302
311
  it "should allow hovering on an element" do
303
- pending "selenium-webdriver/geckodriver doesn't support mouse move_to" if marionette?(@session)
304
312
  @session.visit('/with_hover')
305
- expect(@session.find(:css,'.hidden_until_hover', visible: false)).not_to be_visible
306
- @session.find(:css,'.wrapper').hover
307
- expect(@session.find(:css, '.hidden_until_hover', visible: false)).to be_visible
313
+ expect(@session.find(:css, '.wrapper:not(.scroll_needed) .hidden_until_hover', visible: false)).not_to be_visible
314
+ @session.find(:css,'.wrapper:not(.scroll_needed)').hover
315
+ expect(@session.find(:css, '.wrapper:not(.scroll_needed) .hidden_until_hover', visible: false)).to be_visible
316
+ end
317
+
318
+ it "should allow hovering on an element that needs to be scrolled into view" do
319
+ @session.visit('/with_hover')
320
+ expect(@session.find(:css, '.wrapper.scroll_needed .hidden_until_hover', visible: false)).not_to be_visible
321
+ @session.find(:css,'.wrapper.scroll_needed').hover
322
+ expect(@session.find(:css, '.wrapper.scroll_needed .hidden_until_hover', visible: false)).to be_visible
308
323
  end
309
324
  end
310
325
 
@@ -314,6 +329,12 @@ Capybara::SpecHelper.spec "node" do
314
329
  expect(@session.current_url).to match(%r{/with_html$})
315
330
  end
316
331
 
332
+ it "should go to the same page if href is blank" do
333
+ @session.find(:css, '#link_blank_href').click
334
+ sleep 1
335
+ expect(@session).to have_current_path('/with_html')
336
+ end
337
+
317
338
  it "should be able to check a checkbox" do
318
339
  @session.visit('form')
319
340
  cbox = @session.find(:checkbox, 'form_terms_of_use')
@@ -341,7 +362,7 @@ Capybara::SpecHelper.spec "node" do
341
362
 
342
363
  describe '#double_click', requires: [:js] do
343
364
  it "should double click an element" do
344
- pending "selenium-webdriver/geckodriver doesn't support mouse move_to" if marionette?(@session)
365
+ pending "selenium-webdriver/geckodriver doesn't generate double click event" if marionette?(@session)
345
366
  @session.visit('/with_js')
346
367
  @session.find(:css, '#click-test').double_click
347
368
  expect(@session.find(:css, '#has-been-double-clicked')).to be
@@ -350,7 +371,6 @@ Capybara::SpecHelper.spec "node" do
350
371
 
351
372
  describe '#right_click', requires: [:js] do
352
373
  it "should right click an element" do
353
- pending "selenium-webdriver/geckodriver doesn't support mouse move_to" if marionette?(@session)
354
374
  @session.visit('/with_js')
355
375
  @session.find(:css, '#click-test').right_click
356
376
  expect(@session.find(:css, '#has-been-right-clicked')).to be
@@ -422,11 +442,15 @@ Capybara::SpecHelper.spec "node" do
422
442
  end
423
443
 
424
444
  context "with automatic reload" do
445
+ before do
446
+ Capybara.default_max_wait_time = 4
447
+ end
448
+
425
449
  it "should reload the current context of the node automatically" do
426
450
  @session.visit('/with_js')
427
451
  node = @session.find(:css, '#reload-me')
428
452
  @session.click_link('Reload!')
429
- sleep(0.3)
453
+ sleep(1)
430
454
  expect(node.text).to eq('has been reloaded')
431
455
  end
432
456
 
@@ -434,7 +458,7 @@ Capybara::SpecHelper.spec "node" do
434
458
  @session.visit('/with_js')
435
459
  node = @session.find(:css, '#reload-me').find(:css, 'em')
436
460
  @session.click_link('Reload!')
437
- sleep(0.3)
461
+ sleep(1)
438
462
  expect(node.text).to eq('has been reloaded')
439
463
  end
440
464
 
@@ -442,7 +466,7 @@ Capybara::SpecHelper.spec "node" do
442
466
  @session.visit('/with_js')
443
467
  node = @session.find(:css, '#reload-me')
444
468
  @session.click_link('Reload!')
445
- sleep(0.3)
469
+ sleep(1)
446
470
  expect(node.find(:css, 'a').text).to eq('has been reloaded')
447
471
  end
448
472
 
@@ -450,7 +474,7 @@ Capybara::SpecHelper.spec "node" do
450
474
  @session.visit('/with_js')
451
475
  node = @session.all(:css, '#the-list li')[1]
452
476
  @session.click_link('Fetch new list!')
453
- sleep(0.3)
477
+ sleep(1)
454
478
 
455
479
  expect do
456
480
  expect(node).to have_text('Foo')