capybara 2.13.0 → 2.18.0

Sign up to get free protection for your applications and to get access to all the features.
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,67 @@
1
+ # frozen_string_literal: true
2
+ require 'spec_helper'
3
+ require 'capybara/dsl'
4
+
5
+ RSpec.describe Capybara::SessionConfig do
6
+ describe "threadsafe" do
7
+ it "defaults to global session options" do
8
+ Capybara.threadsafe = true
9
+ session = Capybara::Session.new(:rack_test, TestApp)
10
+ [:default_host, :app_host, :save_and_open_page_path,
11
+ :always_include_port, :run_server, :default_selector, :default_max_wait_time, :ignore_hidden_elements,
12
+ :automatic_reload, :match, :exact, :raise_server_errors, :visible_text_only, :wait_on_first_by_default,
13
+ :automatic_label_click, :enable_aria_label,
14
+ :save_path, :exact_options, :asset_host].each do |m|
15
+ expect(session.config.public_send(m)).to eq Capybara.public_send(m)
16
+ end
17
+ end
18
+
19
+ it "doesn't change global session when changed" do
20
+ Capybara.threadsafe = true
21
+ host = "http://my.example.com"
22
+ session = Capybara::Session.new(:rack_test, TestApp) do |config|
23
+ config.default_host = host
24
+ config.automatic_label_click = !config.automatic_label_click
25
+ config.server_errors << ArgumentError
26
+ end
27
+ expect(Capybara.default_host).not_to eq host
28
+ expect(session.config.default_host).to eq host
29
+ expect(Capybara.automatic_label_click).not_to eq session.config.automatic_label_click
30
+ expect(Capybara.server_errors).not_to eq session.config.server_errors
31
+ end
32
+
33
+ it "doesn't allow session configuration block when false" do
34
+ Capybara.threadsafe = false
35
+ expect do
36
+ Capybara::Session.new(:rack_test, TestApp) { |config| }
37
+ end.to raise_error "A configuration block is only accepted when Capybara.threadsafe == true"
38
+ end
39
+
40
+ it "doesn't allow session config when false" do
41
+ Capybara.threadsafe = false
42
+ session = Capybara::Session.new(:rack_test, TestApp)
43
+ expect { session.config.default_selector = :title }.to raise_error(/Per session settings are only supported when Capybara.threadsafe == true/)
44
+ expect do
45
+ session.configure do |config|
46
+ config.exact = true
47
+ end
48
+ end.to raise_error(/Session configuration is only supported when Capybara.threadsafe == true/)
49
+ end
50
+
51
+ it "uses the config from the session" do
52
+ Capybara.threadsafe = true
53
+ session = Capybara::Session.new(:rack_test, TestApp) do |config|
54
+ config.default_selector = :link
55
+ end
56
+ session.visit('/with_html')
57
+ expect(session.find('foo').tag_name).to eq 'a'
58
+ end
59
+
60
+ it "won't change threadsafe once a session is created" do
61
+ Capybara.threadsafe = true
62
+ Capybara.threadsafe = false
63
+ Capybara::Session.new(:rack_test, TestApp)
64
+ expect { Capybara.threadsafe = true }.to raise_error(/Threadsafe setting cannot be changed once a session is created/)
65
+ end
66
+ end
67
+ end
data/spec/result_spec.rb CHANGED
@@ -71,6 +71,26 @@ RSpec.describe Capybara::Result do
71
71
  expect(result[-1].text).to eq 'Delta'
72
72
  end
73
73
 
74
+ it 'works with filter blocks' do
75
+ result = string.all('//li') { |node| node.text == 'Alpha' }
76
+ expect(result.size).to eq 1
77
+ end
78
+
79
+ it 'should catch invalid element errors during filtering' do
80
+ allow_any_instance_of(Capybara::Node::Simple).to receive(:text).and_raise(StandardError)
81
+ allow_any_instance_of(Capybara::Node::Simple).to receive(:session).and_return(double("session", driver: double("driver", invalid_element_errors: [StandardError] )))
82
+ result = string.all('//li', text: 'Alpha')
83
+ expect(result.size).to eq 0
84
+ end
85
+
86
+ it 'should return non-invalid element errors during filtering' do
87
+ allow_any_instance_of(Capybara::Node::Simple).to receive(:text).and_raise(StandardError)
88
+ allow_any_instance_of(Capybara::Node::Simple).to receive(:session).and_return(double("session", driver: double("driver", invalid_element_errors: [ArgumentError] )))
89
+ expect do
90
+ string.all('//li', text: 'Alpha').to_a
91
+ end.to raise_error(StandardError)
92
+ end
93
+
74
94
  #Not a great test but it indirectly tests what is needed
75
95
  it "should evaluate filters lazily" do
76
96
  skip 'JRuby has an issue with lazy enumerator evaluation' if RUBY_PLATFORM == 'java'
@@ -2,6 +2,7 @@
2
2
  require 'spec_helper'
3
3
  require 'capybara/dsl'
4
4
  require 'capybara/rspec/matchers'
5
+ require 'benchmark'
5
6
 
6
7
  RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
7
8
 
@@ -10,7 +11,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
10
11
 
11
12
  describe "have_css matcher" do
12
13
  it "gives proper description" do
13
- expect(have_css('h1').description).to eq("have css \"h1\"")
14
+ expect(have_css('h1').description).to eq("have visible css \"h1\"")
14
15
  end
15
16
 
16
17
  context "on a string" do
@@ -22,7 +23,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
22
23
  it "fails if has_css? returns false" do
23
24
  expect do
24
25
  expect("<h1>Text</h1>").to have_css('h2')
25
- end.to raise_error(/expected to find css "h2" but there were no matches/)
26
+ end.to raise_error(/expected to find visible css "h2" but there were no matches/)
26
27
  end
27
28
 
28
29
  it "passes if matched node count equals expected count" do
@@ -32,25 +33,25 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
32
33
  it "fails if matched node count does not equal expected count" do
33
34
  expect do
34
35
  expect("<h1>Text</h1>").to have_css('h1', count: 2)
35
- end.to raise_error("expected to find css \"h1\" 2 times, found 1 match: \"Text\"")
36
+ end.to raise_error("expected to find visible css \"h1\" 2 times, found 1 match: \"Text\"")
36
37
  end
37
38
 
38
39
  it "fails if matched node count is less than expected minimum count" do
39
40
  expect do
40
41
  expect("<h1>Text</h1>").to have_css('p', minimum: 1)
41
- end.to raise_error("expected to find css \"p\" at least 1 time but there were no matches")
42
+ end.to raise_error("expected to find visible css \"p\" at least 1 time but there were no matches")
42
43
  end
43
44
 
44
45
  it "fails if matched node count is more than expected maximum count" do
45
46
  expect do
46
47
  expect("<h1>Text</h1><h1>Text</h1><h1>Text</h1>").to have_css('h1', maximum: 2)
47
- end.to raise_error('expected to find css "h1" at most 2 times, found 3 matches: "Text", "Text", "Text"')
48
+ end.to raise_error('expected to find visible css "h1" at most 2 times, found 3 matches: "Text", "Text", "Text"')
48
49
  end
49
50
 
50
51
  it "fails if matched node count does not belong to expected range" do
51
52
  expect do
52
53
  expect("<h1>Text</h1>").to have_css('h1', between: 2..3)
53
- end.to raise_error("expected to find css \"h1\" between 2 and 3 times, found 1 match: \"Text\"")
54
+ end.to raise_error("expected to find visible css \"h1\" between 2 and 3 times, found 1 match: \"Text\"")
54
55
  end
55
56
 
56
57
  end
@@ -63,7 +64,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
63
64
  it "fails if has_no_css? returns false" do
64
65
  expect do
65
66
  expect("<h1>Text</h1>").not_to have_css('h1')
66
- end.to raise_error(/expected not to find css "h1"/)
67
+ end.to raise_error(/expected not to find visible css "h1"/)
67
68
  end
68
69
 
69
70
  it "passes if matched node count does not equal expected count" do
@@ -73,7 +74,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
73
74
  it "fails if matched node count equals expected count" do
74
75
  expect do
75
76
  expect("<h1>Text</h1>").not_to have_css('h1', count: 1)
76
- end.to raise_error(/expected not to find css "h1"/)
77
+ end.to raise_error(/expected not to find visible css "h1"/)
77
78
  end
78
79
  end
79
80
 
@@ -96,7 +97,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
96
97
  it "fails if has_css? returns false" do
97
98
  expect do
98
99
  expect(page).to have_css('h1#doesnotexist')
99
- end.to raise_error(/expected to find css "h1#doesnotexist" but there were no matches/)
100
+ end.to raise_error(/expected to find visible css "h1#doesnotexist" but there were no matches/)
100
101
  end
101
102
  end
102
103
 
@@ -108,7 +109,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
108
109
  it "fails if has_no_css? returns false" do
109
110
  expect do
110
111
  expect(page).not_to have_css('h1')
111
- end.to raise_error(/expected not to find css "h1"/)
112
+ end.to raise_error(/expected not to find visible css "h1"/)
112
113
  end
113
114
  end
114
115
  end
@@ -116,7 +117,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
116
117
 
117
118
  describe "have_xpath matcher" do
118
119
  it "gives proper description" do
119
- expect(have_xpath('//h1').description).to eq("have xpath \"\/\/h1\"")
120
+ expect(have_xpath('//h1').description).to eq("have visible xpath \"\/\/h1\"")
120
121
  end
121
122
 
122
123
  context "on a string" do
@@ -128,7 +129,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
128
129
  it "fails if has_xpath? returns false" do
129
130
  expect do
130
131
  expect("<h1>Text</h1>").to have_xpath('//h2')
131
- end.to raise_error(%r(expected to find xpath "//h2" but there were no matches))
132
+ end.to raise_error(%r(expected to find visible xpath "//h2" but there were no matches))
132
133
  end
133
134
  end
134
135
 
@@ -140,7 +141,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
140
141
  it "fails if has_no_xpath? returns false" do
141
142
  expect do
142
143
  expect("<h1>Text</h1>").not_to have_xpath('//h1')
143
- end.to raise_error(%r(expected not to find xpath "//h1"))
144
+ end.to raise_error(%r(expected not to find visible xpath "//h1"))
144
145
  end
145
146
  end
146
147
 
@@ -163,7 +164,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
163
164
  it "fails if has_xpath? returns false" do
164
165
  expect do
165
166
  expect(page).to have_xpath("//h1[@id='doesnotexist']")
166
- end.to raise_error(%r(expected to find xpath "//h1\[@id='doesnotexist'\]" but there were no matches))
167
+ end.to raise_error(%r(expected to find visible xpath "//h1\[@id='doesnotexist'\]" but there were no matches))
167
168
  end
168
169
  end
169
170
 
@@ -175,7 +176,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
175
176
  it "fails if has_no_xpath? returns false" do
176
177
  expect do
177
178
  expect(page).not_to have_xpath('//h1')
178
- end.to raise_error(%r(expected not to find xpath "//h1"))
179
+ end.to raise_error(%r(expected not to find visible xpath "//h1"))
179
180
  end
180
181
  end
181
182
  end
@@ -185,7 +186,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
185
186
  it "gives proper description" do
186
187
  matcher = have_selector('//h1')
187
188
  expect("<h1>Text</h1>").to matcher
188
- expect(matcher.description).to eq("have xpath \"//h1\"")
189
+ expect(matcher.description).to eq("have visible xpath \"//h1\"")
189
190
  end
190
191
 
191
192
  context "on a string" do
@@ -197,7 +198,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
197
198
  it "fails if has_selector? returns false" do
198
199
  expect do
199
200
  expect("<h1>Text</h1>").to have_selector('//h2')
200
- end.to raise_error(%r(expected to find xpath "//h2" but there were no matches))
201
+ end.to raise_error(%r(expected to find visible xpath "//h2" but there were no matches))
201
202
  end
202
203
  end
203
204
 
@@ -209,7 +210,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
209
210
  it "fails if has_no_selector? returns false" do
210
211
  expect do
211
212
  expect("<h1>Text</h1>").not_to have_selector(:css, 'h1')
212
- end.to raise_error(%r(expected not to find css "h1"))
213
+ end.to raise_error(%r(expected not to find visible css "h1"))
213
214
  end
214
215
  end
215
216
  end
@@ -227,13 +228,13 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
227
228
  it "fails if has_selector? returns false" do
228
229
  expect do
229
230
  expect(page).to have_selector("//h1[@id='doesnotexist']")
230
- end.to raise_error(%r(expected to find xpath "//h1\[@id='doesnotexist'\]" but there were no matches))
231
+ end.to raise_error(%r(expected to find visible xpath "//h1\[@id='doesnotexist'\]" but there were no matches))
231
232
  end
232
233
 
233
234
  it "includes text in error message" do
234
235
  expect do
235
236
  expect(page).to have_selector("//h1", text: 'wrong text')
236
- end.to raise_error(%r(expected to find xpath "//h1" with text "wrong text" but there were no matches))
237
+ end.to raise_error(%r(expected to find visible xpath "//h1" with text "wrong text" but there were no matches))
237
238
  end
238
239
  end
239
240
 
@@ -245,7 +246,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
245
246
  it "fails if has_no_selector? returns false" do
246
247
  expect do
247
248
  expect(page).not_to have_selector(:css, 'h1', text: 'test')
248
- end.to raise_error(%r(expected not to find css "h1" with text "test"))
249
+ end.to raise_error(%r(expected not to find visible css "h1" with text "test"))
249
250
  end
250
251
  end
251
252
  end
@@ -483,7 +484,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
483
484
  let(:html) { '<a href="#">Just a link</a><a href="#">Another link</a>' }
484
485
 
485
486
  it "gives proper description" do
486
- expect(have_link('Just a link').description).to eq("have link \"Just a link\"")
487
+ expect(have_link('Just a link').description).to eq("have visible link \"Just a link\"")
487
488
  end
488
489
 
489
490
  it "passes if there is such a button" do
@@ -493,7 +494,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
493
494
  it "fails if there is no such button" do
494
495
  expect do
495
496
  expect(html).to have_link('No such Link')
496
- end.to raise_error(/expected to find link "No such Link"/)
497
+ end.to raise_error(/expected to find visible link "No such Link"/)
497
498
  end
498
499
 
499
500
  it "supports compounding" do
@@ -555,8 +556,8 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
555
556
 
556
557
  it "doesn't wait if wait time is less than timeout" do
557
558
  @session.click_link("Change title")
558
- using_wait_time 0 do
559
- expect(@session).not_to have_title('changed title')
559
+ using_wait_time 3 do
560
+ expect(@session).not_to have_title('changed title', wait: 0)
560
561
  end
561
562
  end
562
563
  end
@@ -617,7 +618,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
617
618
  let(:html) { '<button>A button</button><input type="submit" value="Another button"/>' }
618
619
 
619
620
  it "gives proper description" do
620
- expect(have_button('A button').description).to eq("have button \"A button\"")
621
+ expect(have_button('A button').description).to eq("have visible button \"A button\"")
621
622
  end
622
623
 
623
624
  it "passes if there is such a button" do
@@ -627,7 +628,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
627
628
  it "fails if there is no such button" do
628
629
  expect do
629
630
  expect(html).to have_button('No such Button')
630
- end.to raise_error(/expected to find button "No such Button"/)
631
+ end.to raise_error(/expected to find visible button "No such Button"/)
631
632
  end
632
633
 
633
634
  it "supports compounding" do
@@ -639,11 +640,11 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
639
640
  let(:html) { '<p><label>Text field<input type="text" value="some value"/></label></p>' }
640
641
 
641
642
  it "gives proper description" do
642
- expect(have_field('Text field').description).to eq("have field \"Text field\"")
643
+ expect(have_field('Text field').description).to eq("have visible field \"Text field\" that is not disabled")
643
644
  end
644
645
 
645
646
  it "gives proper description for a given value" do
646
- expect(have_field('Text field', with: 'some value').description).to eq("have field \"Text field\" with value \"some value\"")
647
+ expect(have_field('Text field', with: 'some value').description).to eq("have visible field \"Text field\" that is not disabled with value \"some value\"")
647
648
  end
648
649
 
649
650
  it "passes if there is such a field" do
@@ -657,13 +658,13 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
657
658
  it "fails if there is no such field" do
658
659
  expect do
659
660
  expect(html).to have_field('No such Field')
660
- end.to raise_error(/expected to find field "No such Field"/)
661
+ end.to raise_error(/expected to find visible field "No such Field"/)
661
662
  end
662
663
 
663
664
  it "fails if there is such field but with false value" do
664
665
  expect do
665
666
  expect(html).to have_field('Text field', with: 'false value')
666
- end.to raise_error(/expected to find field "Text field"/)
667
+ end.to raise_error(/expected to find visible field "Text field"/)
667
668
  end
668
669
 
669
670
  it "treats a given value as a string" do
@@ -687,7 +688,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
687
688
  end
688
689
 
689
690
  it "gives proper description" do
690
- expect(have_checked_field('it is checked').description).to eq("have field \"it is checked\" that is checked")
691
+ expect(have_checked_field('it is checked').description).to eq("have visible field \"it is checked\" that is checked and not disabled")
691
692
  end
692
693
 
693
694
  context "with should" do
@@ -698,13 +699,13 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
698
699
  it "fails if there is such a field but it is not checked" do
699
700
  expect do
700
701
  expect(html).to have_checked_field('unchecked field')
701
- end.to raise_error(/expected to find field "unchecked field"/)
702
+ end.to raise_error(/expected to find visible field "unchecked field"/)
702
703
  end
703
704
 
704
705
  it "fails if there is no such field" do
705
706
  expect do
706
707
  expect(html).to have_checked_field('no such field')
707
- end.to raise_error(/expected to find field "no such field"/)
708
+ end.to raise_error(/expected to find visible field "no such field"/)
708
709
  end
709
710
  end
710
711
 
@@ -712,7 +713,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
712
713
  it "fails if there is such a field and it is checked" do
713
714
  expect do
714
715
  expect(html).not_to have_checked_field('it is checked')
715
- end.to raise_error(/expected not to find field "it is checked"/)
716
+ end.to raise_error(/expected not to find visible field "it is checked"/)
716
717
  end
717
718
 
718
719
  it "passes if there is such a field but it is not checked" do
@@ -736,7 +737,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
736
737
  end
737
738
 
738
739
  it "gives proper description" do
739
- expect(have_unchecked_field('unchecked field').description).to eq("have field \"unchecked field\" that is not checked")
740
+ expect(have_unchecked_field('unchecked field').description).to eq("have visible field \"unchecked field\" that is not checked and not disabled")
740
741
  end
741
742
 
742
743
  context "with should" do
@@ -747,13 +748,13 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
747
748
  it "fails if there is such a field but it is checked" do
748
749
  expect do
749
750
  expect(html).to have_unchecked_field('it is checked')
750
- end.to raise_error(/expected to find field "it is checked"/)
751
+ end.to raise_error(/expected to find visible field "it is checked"/)
751
752
  end
752
753
 
753
754
  it "fails if there is no such field" do
754
755
  expect do
755
756
  expect(html).to have_unchecked_field('no such field')
756
- end.to raise_error(/expected to find field "no such field"/)
757
+ end.to raise_error(/expected to find visible field "no such field"/)
757
758
  end
758
759
  end
759
760
 
@@ -761,7 +762,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
761
762
  it "fails if there is such a field and it is not checked" do
762
763
  expect do
763
764
  expect(html).not_to have_unchecked_field('unchecked field')
764
- end.to raise_error(/expected not to find field "unchecked field"/)
765
+ end.to raise_error(/expected not to find visible field "unchecked field"/)
765
766
  end
766
767
 
767
768
  it "passes if there is such a field but it is checked" do
@@ -782,11 +783,11 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
782
783
  let(:html) { '<label>Select Box<select></select></label>' }
783
784
 
784
785
  it "gives proper description" do
785
- expect(have_select('Select Box').description).to eq("have select box \"Select Box\"")
786
+ expect(have_select('Select Box').description).to eq("have visible select box \"Select Box\" that is not disabled")
786
787
  end
787
788
 
788
789
  it "gives proper description for a given selected value" do
789
- expect(have_select('Select Box', selected: 'some value').description).to eq("have select box \"Select Box\" with \"some value\" selected")
790
+ expect(have_select('Select Box', selected: 'some value').description).to eq('have visible select box "Select Box" that is not disabled with "some value" selected')
790
791
  end
791
792
 
792
793
  it "passes if there is such a select" do
@@ -796,7 +797,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
796
797
  it "fails if there is no such select" do
797
798
  expect do
798
799
  expect(html).to have_select('No such Select box')
799
- end.to raise_error(/expected to find select box "No such Select box"/)
800
+ end.to raise_error(/expected to find visible select box "No such Select box"/)
800
801
  end
801
802
 
802
803
  it "supports compounding" do
@@ -808,7 +809,14 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
808
809
  let(:html) { '<table><caption>Lovely table</caption></table>' }
809
810
 
810
811
  it "gives proper description" do
811
- expect(have_table('Lovely table').description).to eq("have table \"Lovely table\"")
812
+ expect(have_table('Lovely table').description).to eq("have visible table \"Lovely table\"")
813
+ end
814
+
815
+ it "gives proper description when :visible option passed" do
816
+ expect(have_table('Lovely table', visible: true).description).to eq("have visible table \"Lovely table\"")
817
+ expect(have_table('Lovely table', visible: :hidden).description).to eq("have non-visible table \"Lovely table\"")
818
+ expect(have_table('Lovely table', visible: :all).description).to eq("have table \"Lovely table\"")
819
+ expect(have_table('Lovely table', visible: false).description).to eq("have table \"Lovely table\"")
812
820
  end
813
821
 
814
822
  it "passes if there is such a select" do
@@ -818,11 +826,107 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, mode|
818
826
  it "fails if there is no such select" do
819
827
  expect do
820
828
  expect(html).to have_table('No such Table')
821
- end.to raise_error(/expected to find table "No such Table"/)
829
+ end.to raise_error(/expected to find visible table "No such Table"/)
822
830
  end
823
831
 
824
832
  it "supports compounding" do
825
833
  expect(html).to have_table('nope').or have_table('Lovely table')
826
834
  end if RSpec::Version::STRING.to_f >= 3.0
827
835
  end
836
+
837
+ if RSpec::Version::STRING.to_f >= 3.0
838
+ context "compounding", requires: [:js] do
839
+ before(:each) do
840
+ @session = session
841
+ @session.visit('/with_js')
842
+ @el = @session.find(:css, '#reload-me')
843
+ end
844
+
845
+ context "#and" do
846
+ it "should run 'concurrently'" do
847
+ Capybara.using_wait_time(2) do
848
+ matcher = have_text('this is not there').and have_text('neither is this')
849
+ expect(Benchmark.realtime do
850
+ expect {
851
+ expect(@el).to matcher
852
+ }.to raise_error RSpec::Expectations::ExpectationNotMetError
853
+ end).to be_between(2,3)
854
+ end
855
+ end
856
+
857
+ it "should run 'concurrently' and retry" do
858
+ @session.click_link('reload-link')
859
+ @session.using_wait_time(2) do
860
+ expect(Benchmark.realtime do
861
+ expect {
862
+ expect(@el).to have_text('waiting to be reloaded').and(have_text('has been reloaded'))
863
+ }.to raise_error RSpec::Expectations::ExpectationNotMetError, /expected to find text "waiting to be reloaded" in "has been reloaded"/
864
+ end).to be_between(2,3)
865
+ end
866
+ end
867
+
868
+ it "should ignore :wait options" do
869
+ @session.using_wait_time(2) do
870
+ matcher = have_text('this is not there', wait: 5).and have_text('neither is this', wait: 6)
871
+ expect(Benchmark.realtime do
872
+ expect {
873
+ expect(@el).to matcher
874
+ }.to raise_error RSpec::Expectations::ExpectationNotMetError
875
+ end).to be_between(2,3)
876
+ end
877
+ end
878
+
879
+ it "should work on the session" do
880
+ @session.using_wait_time(2) do
881
+ @session.click_link('reload-link')
882
+ expect(@session).to have_selector(:css, 'h1', text: 'FooBar').and have_text('has been reloaded')
883
+ end
884
+ end
885
+ end
886
+
887
+ context "#and_then" do
888
+ it "should run sequentially" do
889
+ @session.click_link('reload-link')
890
+ expect(@el).to have_text('waiting to be reloaded').and_then have_text('has been reloaded')
891
+ end
892
+ end
893
+
894
+ context "#or" do
895
+ it "should run 'concurrently'" do
896
+ @session.using_wait_time(3) do
897
+ expect(Benchmark.realtime do
898
+ expect(@el).to have_text('has been reloaded').or have_text('waiting to be reloaded')
899
+ end).to be < 1
900
+ end
901
+ end
902
+
903
+ it "should retry" do
904
+ @session.using_wait_time(3) do
905
+ expect(Benchmark.realtime do
906
+ expect {
907
+ expect(@el).to have_text('has been reloaded').or have_text('random stuff')
908
+ }.to raise_error RSpec::Expectations::ExpectationNotMetError
909
+ end).to be > 3
910
+ end
911
+ end
912
+
913
+ it "should ignore :wait options" do
914
+ @session.using_wait_time(2) do
915
+ expect(Benchmark.realtime do
916
+ expect {
917
+ expect(@el).to have_text('this is not there', wait: 10).or have_text('neither is this', wait: 15)
918
+ }.to raise_error RSpec::Expectations::ExpectationNotMetError
919
+ end).to be_between(2,3)
920
+ end
921
+ end
922
+
923
+ it "should work on the session" do
924
+ @session.using_wait_time(2) do
925
+ @session.click_link('reload-link')
926
+ expect(@session).to have_selector(:css, 'h1', text: 'Not on the page').or have_text('has been reloaded')
927
+ end
928
+ end
929
+ end
930
+ end
931
+ end
828
932
  end
@@ -5,4 +5,8 @@ RSpec.describe "capybara/rspec", type: :view do
5
5
  it "allows matchers to be used on strings" do
6
6
  expect(%{<h1>Test header</h1>}).to have_css("h1", text: "Test header")
7
7
  end
8
+
9
+ it "doesn't include RSpecMatcherProxies" do
10
+ expect(self.class.ancestors).not_to include(Capybara::RSpecMatcherProxies)
11
+ end
8
12
  end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+ require 'spec_helper'
3
+
4
+ RSpec.describe 'Capybara RSpec Matchers', :type => :feature do
5
+ context "after called on session" do
6
+ it "HaveSelector should allow getting a description of the matcher" do
7
+ visit('/with_html')
8
+ matcher = have_selector(:css, 'h2.head', minimum: 3)
9
+ expect(page).to matcher
10
+ expect { matcher.description }.not_to raise_error
11
+ end
12
+
13
+ it "HaveText should allow getting a description" do
14
+ visit('/with_html')
15
+ matcher = have_text("Lorem")
16
+ expect(page).to matcher
17
+ expect { matcher.description }.not_to raise_error
18
+ end
19
+ end
20
+
21
+ context "after called on element" do
22
+ it "HaveSelector should allow getting a description" do
23
+ visit('/with_html')
24
+ el = find(:css, '#first')
25
+ matcher = have_selector(:css, 'a#foo')
26
+ expect(el).to matcher
27
+ expect { matcher.description }.not_to raise_error
28
+ end
29
+
30
+ it "MatchSelector should allow getting a description" do
31
+ visit('/with_html')
32
+ el = find(:css, '#first')
33
+ matcher = match_selector(:css, '#first')
34
+ expect(el).to matcher
35
+ expect { matcher.description }.not_to raise_error
36
+ end
37
+
38
+ it "HaveText should allow getting a description" do
39
+ visit('/with_html')
40
+ el = find(:css, '#first')
41
+ matcher = have_text("Lorem")
42
+ expect(el).to matcher
43
+ expect { matcher.description }.not_to raise_error
44
+ end
45
+ end
46
+ end