capybara 3.32.2 → 3.33.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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +21 -1
  3. data/README.md +10 -3
  4. data/lib/capybara.rb +17 -7
  5. data/lib/capybara/cucumber.rb +1 -1
  6. data/lib/capybara/minitest.rb +2 -3
  7. data/lib/capybara/node/actions.rb +16 -20
  8. data/lib/capybara/node/matchers.rb +4 -6
  9. data/lib/capybara/queries/selector_query.rb +8 -1
  10. data/lib/capybara/queries/style_query.rb +1 -1
  11. data/lib/capybara/queries/text_query.rb +6 -0
  12. data/lib/capybara/registration_container.rb +44 -0
  13. data/lib/capybara/selector.rb +10 -1
  14. data/lib/capybara/selector/definition.rb +5 -4
  15. data/lib/capybara/selector/definition/button.rb +1 -0
  16. data/lib/capybara/selector/definition/fillable_field.rb +1 -1
  17. data/lib/capybara/selector/definition/link.rb +8 -0
  18. data/lib/capybara/selector/definition/table.rb +1 -1
  19. data/lib/capybara/selector/selector.rb +4 -0
  20. data/lib/capybara/selenium/driver.rb +2 -0
  21. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +7 -9
  22. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +7 -9
  23. data/lib/capybara/selenium/node.rb +3 -2
  24. data/lib/capybara/selenium/nodes/firefox_node.rb +1 -1
  25. data/lib/capybara/selenium/patches/logs.rb +3 -5
  26. data/lib/capybara/session.rb +3 -3
  27. data/lib/capybara/session/config.rb +3 -1
  28. data/lib/capybara/spec/public/test.js +7 -0
  29. data/lib/capybara/spec/session/click_button_spec.rb +11 -0
  30. data/lib/capybara/spec/session/has_button_spec.rb +16 -0
  31. data/lib/capybara/spec/session/has_current_path_spec.rb +2 -2
  32. data/lib/capybara/spec/session/has_field_spec.rb +16 -0
  33. data/lib/capybara/spec/session/has_select_spec.rb +4 -4
  34. data/lib/capybara/spec/session/has_selector_spec.rb +4 -4
  35. data/lib/capybara/spec/session/node_spec.rb +6 -6
  36. data/lib/capybara/spec/spec_helper.rb +1 -0
  37. data/lib/capybara/spec/test_app.rb +14 -18
  38. data/lib/capybara/spec/views/form.erb +2 -1
  39. data/lib/capybara/spec/views/with_dragula.erb +3 -1
  40. data/lib/capybara/spec/views/with_js.erb +1 -0
  41. data/lib/capybara/version.rb +1 -1
  42. data/spec/capybara_spec.rb +1 -1
  43. data/spec/dsl_spec.rb +14 -1
  44. data/spec/minitest_spec.rb +1 -1
  45. data/spec/rack_test_spec.rb +1 -0
  46. data/spec/rspec/shared_spec_matchers.rb +63 -51
  47. data/spec/selector_spec.rb +1 -1
  48. data/spec/selenium_spec_chrome.rb +0 -2
  49. data/spec/server_spec.rb +41 -49
  50. data/spec/shared_selenium_session.rb +10 -1
  51. data/spec/spec_helper.rb +1 -1
  52. metadata +4 -3
@@ -140,7 +140,7 @@
140
140
 
141
141
  <p>
142
142
  <label for="form_zipcode">Zipcode</label>
143
- <input type="text" maxlength="5" name="form[zipcode]" id="form_zipcode" />
143
+ <input type="text" maxlength="5" name="form[zipcode]" id="form_zipcode" pattern="[0-9]{5,9}" />
144
144
  </p>
145
145
 
146
146
  <p>
@@ -457,6 +457,7 @@ New line after and before textarea tag
457
457
  <button id="no_type">No Type!</button>
458
458
  <button><img alt="A horse eating hay"/></button>
459
459
  <input type="button" disabled="disabled" value="Disabled button"/>
460
+ <span role="button">ARIA button</span>
460
461
  </p>
461
462
 
462
463
  <p>
@@ -15,7 +15,9 @@
15
15
  </div>
16
16
  <script src="https://cdnjs.cloudflare.com/ajax/libs/dragula/3.7.2/dragula.js" type="text/javascript"></script>
17
17
  <script>
18
- dragula([document.getElementById("sortable")]);
18
+ let container = document.getElementById("sortable");
19
+ dragula([container]);
20
+ container.className = "ready"
19
21
  </script>
20
22
  </body>
21
23
  </html>
@@ -35,6 +35,7 @@
35
35
 
36
36
  <p><a href="#" id="clickable">Click me</a></p>
37
37
  <p><a href="#" id="slow-click">Slowly</a></p>
38
+ <p><span id="aria-button" role="button">ARIA button</span></p>
38
39
 
39
40
  <p>
40
41
  <select id="waiter">
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Capybara
4
- VERSION = '3.32.2'
4
+ VERSION = '3.33.0'
5
5
  end
@@ -32,7 +32,7 @@ RSpec.describe Capybara do
32
32
  # do nothing
33
33
  end
34
34
 
35
- expect(described_class.servers).to have_key(:blob)
35
+ expect(described_class.servers[:blob]).to be_truthy
36
36
  end
37
37
  end
38
38
 
@@ -8,7 +8,7 @@ class TestClass
8
8
  end
9
9
 
10
10
  Capybara::SpecHelper.run_specs TestClass.new, 'DSL', capybara_skip: %i[
11
- js modals screenshot frames windows send_keys server hover about_scheme psc download css driver scroll spatial
11
+ js modals screenshot frames windows send_keys server hover about_scheme psc download css driver scroll spatial html_validation
12
12
  ] do |example|
13
13
  case example.metadata[:full_description]
14
14
  when /has_css\? should support case insensitive :class and :id options/
@@ -19,6 +19,10 @@ Capybara::SpecHelper.run_specs TestClass.new, 'DSL', capybara_skip: %i[
19
19
  end
20
20
 
21
21
  RSpec.describe Capybara::DSL do
22
+ before do
23
+ Capybara.use_default_driver
24
+ end
25
+
22
26
  after do
23
27
  Capybara.session_name = nil
24
28
  Capybara.default_driver = nil
@@ -238,6 +242,15 @@ RSpec.describe Capybara::DSL do
238
242
  end
239
243
  expect(Capybara.current_session).to eq(original_session)
240
244
  end
245
+
246
+ it 'should pass the new session if block accepts' do
247
+ original_session = Capybara.current_session
248
+ Capybara.using_session(:administrator) do |admin_session, prev_session|
249
+ expect(admin_session).to be(Capybara.current_session)
250
+ expect(prev_session).to be(original_session)
251
+ expect(prev_session).not_to be(admin_session)
252
+ end
253
+ end
241
254
  end
242
255
 
243
256
  describe '#session_name' do
@@ -16,7 +16,7 @@ class MinitestTest < Minitest::Test
16
16
  end
17
17
 
18
18
  def test_assert_text
19
- assert_text('Form')
19
+ assert_text('Form', normalize_ws: false)
20
20
  assert_no_text('Not on the page')
21
21
  refute_text('Also Not on the page')
22
22
  end
@@ -26,6 +26,7 @@ skipped_tests = %i[
26
26
  css
27
27
  scroll
28
28
  spatial
29
+ html_validation
29
30
  ]
30
31
  Capybara::SpecHelper.run_specs TestSessions::RackTest, 'RackTest', capybara_skip: skipped_tests do |example|
31
32
  case example.metadata[:full_description]
@@ -89,29 +89,29 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
89
89
 
90
90
  context 'on a page or node' do
91
91
  before do
92
- visit('/with_html')
92
+ session.visit('/with_html')
93
93
  end
94
94
 
95
95
  context 'with should' do
96
96
  it 'passes if has_css? returns true' do
97
- expect(page).to have_css('h1')
97
+ expect(session).to have_css('h1')
98
98
  end
99
99
 
100
100
  it 'fails if has_css? returns false' do
101
101
  expect do
102
- expect(page).to have_css('h1#doesnotexist')
102
+ expect(session).to have_css('h1#doesnotexist')
103
103
  end.to raise_error(/expected to find css "h1#doesnotexist" but there were no matches/)
104
104
  end
105
105
  end
106
106
 
107
107
  context 'with should_not' do
108
108
  it 'passes if has_no_css? returns true' do
109
- expect(page).not_to have_css('h1#doesnotexist')
109
+ expect(session).not_to have_css('h1#doesnotexist')
110
110
  end
111
111
 
112
112
  it 'fails if has_no_css? returns false' do
113
113
  expect do
114
- expect(page).not_to have_css('h1')
114
+ expect(session).not_to have_css('h1')
115
115
  end.to raise_error(/expected not to find visible css "h1"/)
116
116
  end
117
117
  end
@@ -158,29 +158,29 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
158
158
 
159
159
  context 'on a page or node' do
160
160
  before do
161
- visit('/with_html')
161
+ session.visit('/with_html')
162
162
  end
163
163
 
164
164
  context 'with should' do
165
165
  it 'passes if has_xpath? returns true' do
166
- expect(page).to have_xpath('//h1')
166
+ expect(session).to have_xpath('//h1')
167
167
  end
168
168
 
169
169
  it 'fails if has_xpath? returns false' do
170
170
  expect do
171
- expect(page).to have_xpath("//h1[@id='doesnotexist']")
171
+ expect(session).to have_xpath("//h1[@id='doesnotexist']")
172
172
  end.to raise_error(%r{expected to find xpath "//h1\[@id='doesnotexist'\]" but there were no matches})
173
173
  end
174
174
  end
175
175
 
176
176
  context 'with should_not' do
177
177
  it 'passes if has_no_xpath? returns true' do
178
- expect(page).not_to have_xpath('//h1[@id="doesnotexist"]')
178
+ expect(session).not_to have_xpath('//h1[@id="doesnotexist"]')
179
179
  end
180
180
 
181
181
  it 'fails if has_no_xpath? returns false' do
182
182
  expect do
183
- expect(page).not_to have_xpath('//h1')
183
+ expect(session).not_to have_xpath('//h1')
184
184
  end.to raise_error(%r{expected not to find visible xpath "//h1"})
185
185
  end
186
186
  end
@@ -222,35 +222,35 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
222
222
 
223
223
  context 'on a page or node' do
224
224
  before do
225
- visit('/with_html')
225
+ session.visit('/with_html')
226
226
  end
227
227
 
228
228
  context 'with should' do
229
229
  it 'passes if has_selector? returns true' do
230
- expect(page).to have_selector('//h1', text: 'test')
230
+ expect(session).to have_selector('//h1', text: 'test')
231
231
  end
232
232
 
233
233
  it 'fails if has_selector? returns false' do
234
234
  expect do
235
- expect(page).to have_selector("//h1[@id='doesnotexist']")
235
+ expect(session).to have_selector("//h1[@id='doesnotexist']")
236
236
  end.to raise_error(%r{expected to find xpath "//h1\[@id='doesnotexist'\]" but there were no matches})
237
237
  end
238
238
 
239
239
  it 'includes text in error message' do
240
240
  expect do
241
- expect(page).to have_selector('//h1', text: 'wrong text')
241
+ expect(session).to have_selector('//h1', text: 'wrong text')
242
242
  end.to raise_error(%r{expected to find visible xpath "//h1" with text "wrong text" but there were no matches})
243
243
  end
244
244
  end
245
245
 
246
246
  context 'with should_not' do
247
247
  it 'passes if has_no_css? returns true' do
248
- expect(page).not_to have_selector(:css, 'h1#doesnotexist')
248
+ expect(session).not_to have_selector(:css, 'h1#doesnotexist')
249
249
  end
250
250
 
251
251
  it 'fails if has_no_selector? returns false' do
252
252
  expect do
253
- expect(page).not_to have_selector(:css, 'h1', text: 'test')
253
+ expect(session).not_to have_selector(:css, 'h1', text: 'test')
254
254
  end.to raise_error(/expected not to find visible css "h1" with text "test"/)
255
255
  end
256
256
  end
@@ -304,21 +304,21 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
304
304
 
305
305
  context 'on a page or node' do
306
306
  before do
307
- visit('/with_html')
307
+ session.visit('/with_html')
308
308
  end
309
309
 
310
310
  context 'with should' do
311
311
  it 'passes if has_content? returns true' do
312
- expect(page).to have_content('This is a test')
312
+ expect(session).to have_content('This is a test')
313
313
  end
314
314
 
315
315
  it 'passes if has_content? returns true using regexp' do
316
- expect(page).to have_content(/test/)
316
+ expect(session).to have_content(/test/)
317
317
  end
318
318
 
319
319
  it 'fails if has_content? returns false' do
320
320
  expect do
321
- expect(page).to have_content('No such Text')
321
+ expect(session).to have_content('No such Text')
322
322
  end.to raise_error(/expected to find text "No such Text" in "(.*)This is a test(.*)"/)
323
323
  end
324
324
 
@@ -329,7 +329,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
329
329
 
330
330
  it 'fails if has_content? returns false' do
331
331
  expect do
332
- expect(page).to have_content('No such Text')
332
+ expect(session).to have_content('No such Text')
333
333
  end.to raise_error(/expected to find text "No such Text" in "(.*)This is a test(.*)"/)
334
334
  end
335
335
  end
@@ -337,14 +337,26 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
337
337
 
338
338
  context 'with should_not' do
339
339
  it 'passes if has_no_content? returns true' do
340
- expect(page).not_to have_content('No such Text')
340
+ expect(session).not_to have_content('No such Text')
341
341
  end
342
342
 
343
343
  it 'fails if has_no_content? returns false' do
344
344
  expect do
345
- expect(page).not_to have_content('This is a test')
345
+ expect(session).not_to have_content('This is a test')
346
346
  end.to raise_error(/expected not to find text "This is a test"/)
347
347
  end
348
+
349
+ it 'not_to have_content behaves the same as to have_no_content' do
350
+ Capybara.using_wait_time(5) do
351
+ expect(session).to have_content('This is a test')
352
+ start = Time.now
353
+ expect(session).to have_no_content('No such Text')
354
+ to_time = Time.now
355
+ expect(session).not_to have_content('No such Text')
356
+ not_to_time = Time.now
357
+ expect(not_to_time - to_time).to be_within(0.5).of(to_time - start)
358
+ end
359
+ end
348
360
  end
349
361
  end
350
362
 
@@ -432,30 +444,30 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
432
444
 
433
445
  context 'on a page or node' do
434
446
  before do
435
- visit('/with_html')
447
+ session.visit('/with_html')
436
448
  end
437
449
 
438
450
  context 'with should' do
439
451
  it 'passes if has_text? returns true' do
440
- expect(page).to have_text('This is a test')
452
+ expect(session).to have_text('This is a test')
441
453
  end
442
454
 
443
455
  it 'passes if has_text? returns true using regexp' do
444
- expect(page).to have_text(/test/)
456
+ expect(session).to have_text(/test/)
445
457
  end
446
458
 
447
459
  it 'can check for all text' do
448
- expect(page).to have_text(:all, 'Some of this text is hidden!')
460
+ expect(session).to have_text(:all, 'Some of this text is hidden!')
449
461
  end
450
462
 
451
463
  it 'can check for visible text' do
452
- expect(page).to have_text(:visible, 'Some of this text is')
453
- expect(page).not_to have_text(:visible, 'Some of this text is hidden!')
464
+ expect(session).to have_text(:visible, 'Some of this text is')
465
+ expect(session).not_to have_text(:visible, 'Some of this text is hidden!')
454
466
  end
455
467
 
456
468
  it 'fails if has_text? returns false' do
457
469
  expect do
458
- expect(page).to have_text('No such Text')
470
+ expect(session).to have_text('No such Text')
459
471
  end.to raise_error(/expected to find text "No such Text" in "(.*)This is a test(.*)"/)
460
472
  end
461
473
 
@@ -466,7 +478,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
466
478
 
467
479
  it 'fails if has_text? returns false' do
468
480
  expect do
469
- expect(page).to have_text('No such Text')
481
+ expect(session).to have_text('No such Text')
470
482
  end.to raise_error(/expected to find text "No such Text" in "(.*)This is a test(.*)"/)
471
483
  end
472
484
  end
@@ -474,12 +486,12 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
474
486
 
475
487
  context 'with should_not' do
476
488
  it 'passes if has_no_text? returns true' do
477
- expect(page).not_to have_text('No such Text')
489
+ expect(session).not_to have_text('No such Text')
478
490
  end
479
491
 
480
492
  it 'fails if has_no_text? returns false' do
481
493
  expect do
482
- expect(page).not_to have_text('This is a test')
494
+ expect(session).not_to have_text('This is a test')
483
495
  end.to raise_error(/expected not to find text "This is a test"/)
484
496
  end
485
497
  end
@@ -542,15 +554,15 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
542
554
 
543
555
  context 'on a page or node' do
544
556
  it 'passes if there is such a title' do
545
- visit('/with_js')
546
- expect(page).to have_title('with_js')
557
+ session.visit('/with_js')
558
+ expect(session).to have_title('with_js')
547
559
  end
548
560
 
549
561
  it 'fails if there is no such title' do
550
- visit('/with_js')
562
+ session.visit('/with_js')
551
563
  expect do
552
- expect(page).to have_title('No such title')
553
- end.to raise_error('expected "with_js" to include "No such title"')
564
+ expect(session).to have_title('No such title')
565
+ end.to raise_error(/ to include "No such title"/)
554
566
  end
555
567
 
556
568
  context 'with wait' do
@@ -560,14 +572,14 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
560
572
 
561
573
  it 'waits if wait time is more than timeout' do
562
574
  session.click_link('Change title')
563
- using_wait_time 0 do
575
+ session.using_wait_time 0 do
564
576
  expect(session).to have_title('changed title', wait: 2)
565
577
  end
566
578
  end
567
579
 
568
580
  it "doesn't wait if wait time is less than timeout" do
569
581
  session.click_link('Change title')
570
- using_wait_time 3 do
582
+ session.using_wait_time 3 do
571
583
  expect(session).not_to have_title('changed title', wait: 0)
572
584
  end
573
585
  end
@@ -586,15 +598,15 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
586
598
 
587
599
  context 'on a page or node' do
588
600
  it 'passes if there is such a current path' do
589
- visit('/with_js')
590
- expect(page).to have_current_path('/with_js')
601
+ session.visit('/with_js')
602
+ expect(session).to have_current_path('/with_js')
591
603
  end
592
604
 
593
605
  it 'fails if there is no such current_path' do
594
606
  visit('/with_js')
595
607
  expect do
596
- expect(page).to have_current_path('/not_with_js')
597
- end.to raise_error('expected "/with_js" to equal "/not_with_js"')
608
+ expect(session).to have_current_path('/not_with_js')
609
+ end.to raise_error(%r{to equal "/not_with_js"})
598
610
  end
599
611
 
600
612
  context 'with wait' do
@@ -604,14 +616,14 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
604
616
 
605
617
  it 'waits if wait time is more than timeout' do
606
618
  session.click_link('Change page')
607
- using_wait_time 0 do
619
+ session.using_wait_time 0 do
608
620
  expect(session).to have_current_path('/with_html', wait: 2)
609
621
  end
610
622
  end
611
623
 
612
624
  it "doesn't wait if wait time is less than timeout" do
613
625
  session.click_link('Change page')
614
- using_wait_time 0 do
626
+ session.using_wait_time 0 do
615
627
  expect(session).not_to have_current_path('/with_html')
616
628
  end
617
629
  end
@@ -619,8 +631,8 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
619
631
  end
620
632
 
621
633
  it 'supports compounding' do
622
- visit('/with_html')
623
- expect(page).to have_current_path('/not_with_html').or have_current_path('/with_html')
634
+ session.visit('/with_html')
635
+ expect(session).to have_current_path('/not_with_html').or have_current_path('/with_html')
624
636
  end
625
637
  end
626
638
 
@@ -828,10 +840,10 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
828
840
  end
829
841
 
830
842
  it 'gives proper description when :visible option passed' do
831
- expect(have_table('Lovely table', visible: true).description).to eq('have visible table "Lovely table"')
843
+ expect(have_table('Lovely table', visible: true).description).to eq('have visible table "Lovely table"') # rubocop:disable Capybara/VisibilityMatcher
832
844
  expect(have_table('Lovely table', visible: :hidden).description).to eq('have non-visible table "Lovely table"')
833
845
  expect(have_table('Lovely table', visible: :all).description).to eq('have table "Lovely table"')
834
- expect(have_table('Lovely table', visible: false).description).to eq('have table "Lovely table"')
846
+ expect(have_table('Lovely table', visible: false).description).to eq('have table "Lovely table"') # rubocop:disable Capybara/VisibilityMatcher
835
847
  end
836
848
 
837
849
  it 'passes if there is such a table' do
@@ -859,7 +871,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
859
871
 
860
872
  describe '#and' do
861
873
  it "should run 'concurrently'" do
862
- Capybara.using_wait_time(2) do
874
+ session.using_wait_time(2) do
863
875
  matcher = have_text('this is not there').and have_text('neither is this')
864
876
  expect(Benchmark.realtime do
865
877
  expect do
@@ -476,7 +476,7 @@ RSpec.describe Capybara do
476
476
  end
477
477
 
478
478
  describe ':link_or_button selector' do
479
- around(:all) do |example|
479
+ around do |example|
480
480
  described_class.modify_selector(:link_or_button) do
481
481
  expression_filter(:random) { |xpath, _| xpath } # do nothing filter
482
482
  end