capybara 2.10.1 → 2.11.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.
- checksums.yaml +4 -4
- data/History.md +22 -0
- data/README.md +48 -29
- data/lib/capybara/node/actions.rb +39 -48
- data/lib/capybara/node/document.rb +4 -0
- data/lib/capybara/node/document_matchers.rb +13 -14
- data/lib/capybara/node/element.rb +21 -0
- data/lib/capybara/node/finders.rb +3 -3
- data/lib/capybara/node/matchers.rb +38 -31
- data/lib/capybara/node/simple.rb +3 -0
- data/lib/capybara/queries/selector_query.rb +4 -2
- data/lib/capybara/rack_test/node.rb +1 -1
- data/lib/capybara/result.rb +3 -1
- data/lib/capybara/rspec/matchers.rb +53 -95
- data/lib/capybara/selector/selector.rb +10 -5
- data/lib/capybara/selector.rb +7 -7
- data/lib/capybara/selenium/driver.rb +34 -7
- data/lib/capybara/selenium/node.rb +5 -1
- data/lib/capybara/session/matchers.rb +12 -14
- data/lib/capybara/session.rb +30 -29
- data/lib/capybara/spec/public/test.js +4 -0
- data/lib/capybara/spec/session/accept_alert_spec.rb +1 -1
- data/lib/capybara/spec/session/attach_file_spec.rb +1 -1
- data/lib/capybara/spec/session/check_spec.rb +8 -0
- data/lib/capybara/spec/session/choose_spec.rb +5 -0
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +5 -0
- data/lib/capybara/spec/session/click_link_spec.rb +5 -0
- data/lib/capybara/spec/session/element/assert_match_selector.rb +5 -0
- data/lib/capybara/spec/session/element/match_css_spec.rb +6 -0
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +2 -0
- data/lib/capybara/spec/session/fill_in_spec.rb +5 -0
- data/lib/capybara/spec/session/find_spec.rb +1 -1
- data/lib/capybara/spec/session/first_spec.rb +10 -0
- data/lib/capybara/spec/session/has_selector_spec.rb +11 -0
- data/lib/capybara/spec/session/node_spec.rb +12 -1
- data/lib/capybara/spec/session/text_spec.rb +3 -4
- data/lib/capybara/spec/test_app.rb +10 -1
- data/lib/capybara/spec/views/with_js.erb +3 -1
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara/window.rb +18 -2
- data/lib/capybara.rb +8 -9
- data/spec/basic_node_spec.rb +1 -1
- data/spec/capybara_spec.rb +4 -1
- data/spec/fixtures/selenium_driver_rspec_failure.rb +4 -1
- data/spec/fixtures/selenium_driver_rspec_success.rb +4 -1
- data/spec/result_spec.rb +28 -2
- data/spec/rspec/{matchers_spec.rb → shared_spec_matchers.rb} +4 -3
- data/spec/selector_spec.rb +1 -1
- data/spec/selenium_spec_chrome.rb +36 -5
- data/spec/selenium_spec_firefox.rb +67 -0
- data/spec/selenium_spec_marionette.rb +114 -0
- data/spec/shared_selenium_session.rb +6 -4
- metadata +15 -8
- data/spec/selenium_firefox_spec.rb +0 -44
|
@@ -17,13 +17,7 @@ module Capybara
|
|
|
17
17
|
# @return [true]
|
|
18
18
|
#
|
|
19
19
|
def assert_current_path(path, options={})
|
|
20
|
-
query
|
|
21
|
-
document.synchronize(query.wait) do
|
|
22
|
-
unless query.resolves_for?(self)
|
|
23
|
-
raise Capybara::ExpectationNotMet, query.failure_message
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
return true
|
|
20
|
+
_verify_current_path(path,options) { |query| raise Capybara::ExpectationNotMet, query.failure_message unless query.resolves_for?(self) }
|
|
27
21
|
end
|
|
28
22
|
|
|
29
23
|
##
|
|
@@ -34,13 +28,7 @@ module Capybara
|
|
|
34
28
|
# @return [true]
|
|
35
29
|
#
|
|
36
30
|
def assert_no_current_path(path, options={})
|
|
37
|
-
query
|
|
38
|
-
document.synchronize(query.wait) do
|
|
39
|
-
if query.resolves_for?(self)
|
|
40
|
-
raise Capybara::ExpectationNotMet, query.negative_failure_message
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
return true
|
|
31
|
+
_verify_current_path(path,options) { |query| raise Capybara::ExpectationNotMet, query.negative_failure_message if query.resolves_for?(self) }
|
|
44
32
|
end
|
|
45
33
|
|
|
46
34
|
##
|
|
@@ -66,5 +54,15 @@ module Capybara
|
|
|
66
54
|
rescue Capybara::ExpectationNotMet
|
|
67
55
|
return false
|
|
68
56
|
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
def _verify_current_path(path, options)
|
|
61
|
+
query = Capybara::Queries::CurrentPathQuery.new(path, options)
|
|
62
|
+
document.synchronize(query.wait) do
|
|
63
|
+
yield(query)
|
|
64
|
+
end
|
|
65
|
+
return true
|
|
66
|
+
end
|
|
69
67
|
end
|
|
70
68
|
end
|
data/lib/capybara/session.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
require 'capybara/session/matchers'
|
|
3
|
+
require 'addressable/uri'
|
|
3
4
|
|
|
4
5
|
module Capybara
|
|
5
6
|
|
|
@@ -125,7 +126,8 @@ module Capybara
|
|
|
125
126
|
begin
|
|
126
127
|
raise CapybaraError, "Your application server raised an error - It has been raised in your test code because Capybara.raise_server_errors == true"
|
|
127
128
|
rescue CapybaraError
|
|
128
|
-
|
|
129
|
+
#needed to get the cause set correctly in JRuby -- otherwise we could just do raise @server.error
|
|
130
|
+
raise @server.error, @server.error.message, @server.error.backtrace
|
|
129
131
|
end
|
|
130
132
|
end
|
|
131
133
|
ensure
|
|
@@ -167,7 +169,11 @@ module Capybara
|
|
|
167
169
|
# @return [String] Path of the current page, without any domain information
|
|
168
170
|
#
|
|
169
171
|
def current_path
|
|
170
|
-
|
|
172
|
+
# Addressable parsing is more lenient than URI
|
|
173
|
+
uri = Addressable::URI.parse(current_url)
|
|
174
|
+
# Addressable doesn't support opaque URIs - we want nil here
|
|
175
|
+
return nil if uri.scheme == "about"
|
|
176
|
+
path = uri.path
|
|
171
177
|
path if path and not path.empty?
|
|
172
178
|
end
|
|
173
179
|
|
|
@@ -263,7 +269,7 @@ module Capybara
|
|
|
263
269
|
# block, any command to Capybara will be handled as though it were scoped
|
|
264
270
|
# to the given element.
|
|
265
271
|
#
|
|
266
|
-
# within(:xpath, '
|
|
272
|
+
# within(:xpath, './/div[@id="delivery-address"]') do
|
|
267
273
|
# fill_in('Street', with: '12 Main Street')
|
|
268
274
|
# end
|
|
269
275
|
#
|
|
@@ -587,11 +593,7 @@ module Capybara
|
|
|
587
593
|
# @raise [Capybara::ModalNotFound] if modal dialog hasn't been found
|
|
588
594
|
#
|
|
589
595
|
def accept_alert(text_or_options=nil, options={}, &blk)
|
|
590
|
-
text_or_options, options
|
|
591
|
-
options[:text] ||= text_or_options unless text_or_options.nil?
|
|
592
|
-
options[:wait] ||= Capybara.default_max_wait_time
|
|
593
|
-
|
|
594
|
-
driver.accept_modal(:alert, options, &blk)
|
|
596
|
+
accept_modal(:alert, text_or_options, options, &blk)
|
|
595
597
|
end
|
|
596
598
|
|
|
597
599
|
##
|
|
@@ -601,11 +603,7 @@ module Capybara
|
|
|
601
603
|
# @macro modal_params
|
|
602
604
|
#
|
|
603
605
|
def accept_confirm(text_or_options=nil, options={}, &blk)
|
|
604
|
-
text_or_options, options
|
|
605
|
-
options[:text] ||= text_or_options unless text_or_options.nil?
|
|
606
|
-
options[:wait] ||= Capybara.default_max_wait_time
|
|
607
|
-
|
|
608
|
-
driver.accept_modal(:confirm, options, &blk)
|
|
606
|
+
accept_modal(:confirm, text_or_options, options, &blk)
|
|
609
607
|
end
|
|
610
608
|
|
|
611
609
|
##
|
|
@@ -615,11 +613,7 @@ module Capybara
|
|
|
615
613
|
# @macro modal_params
|
|
616
614
|
#
|
|
617
615
|
def dismiss_confirm(text_or_options=nil, options={}, &blk)
|
|
618
|
-
text_or_options, options
|
|
619
|
-
options[:text] ||= text_or_options unless text_or_options.nil?
|
|
620
|
-
options[:wait] ||= Capybara.default_max_wait_time
|
|
621
|
-
|
|
622
|
-
driver.dismiss_modal(:confirm, options, &blk)
|
|
616
|
+
dismiss_modal(:confirm, text_or_options, options, &blk)
|
|
623
617
|
end
|
|
624
618
|
|
|
625
619
|
##
|
|
@@ -630,11 +624,7 @@ module Capybara
|
|
|
630
624
|
# @option options [String] :with Response to provide to the prompt
|
|
631
625
|
#
|
|
632
626
|
def accept_prompt(text_or_options=nil, options={}, &blk)
|
|
633
|
-
text_or_options, options
|
|
634
|
-
options[:text] ||= text_or_options unless text_or_options.nil?
|
|
635
|
-
options[:wait] ||= Capybara.default_max_wait_time
|
|
636
|
-
|
|
637
|
-
driver.accept_modal(:prompt, options, &blk)
|
|
627
|
+
accept_modal(:prompt, text_or_options, options, &blk)
|
|
638
628
|
end
|
|
639
629
|
|
|
640
630
|
##
|
|
@@ -644,11 +634,7 @@ module Capybara
|
|
|
644
634
|
# @macro modal_params
|
|
645
635
|
#
|
|
646
636
|
def dismiss_prompt(text_or_options=nil, options={}, &blk)
|
|
647
|
-
text_or_options, options
|
|
648
|
-
options[:text] ||= text_or_options unless text_or_options.nil?
|
|
649
|
-
options[:wait] ||= Capybara.default_max_wait_time
|
|
650
|
-
|
|
651
|
-
driver.dismiss_modal(:prompt, options, &blk)
|
|
637
|
+
dismiss_modal(:prompt, text_or_options, options, &blk)
|
|
652
638
|
end
|
|
653
639
|
|
|
654
640
|
##
|
|
@@ -751,6 +737,21 @@ module Capybara
|
|
|
751
737
|
end
|
|
752
738
|
|
|
753
739
|
private
|
|
740
|
+
def accept_modal(type, text_or_options, options, &blk)
|
|
741
|
+
driver.accept_modal(type, modal_options(text_or_options, options), &blk)
|
|
742
|
+
end
|
|
743
|
+
|
|
744
|
+
def dismiss_modal(type, text_or_options, options, &blk)
|
|
745
|
+
driver.dismiss_modal(type, modal_options(text_or_options, options), &blk)
|
|
746
|
+
end
|
|
747
|
+
|
|
748
|
+
def modal_options(text_or_options, options)
|
|
749
|
+
text_or_options, options = nil, text_or_options if text_or_options.is_a?(Hash)
|
|
750
|
+
options[:text] ||= text_or_options unless text_or_options.nil?
|
|
751
|
+
options[:wait] ||= Capybara.default_max_wait_time
|
|
752
|
+
options
|
|
753
|
+
end
|
|
754
|
+
|
|
754
755
|
|
|
755
756
|
def open_file(path)
|
|
756
757
|
begin
|
|
@@ -774,7 +775,7 @@ module Capybara
|
|
|
774
775
|
|
|
775
776
|
def default_fn(extension)
|
|
776
777
|
timestamp = Time.new.strftime("%Y%m%d%H%M%S")
|
|
777
|
-
|
|
778
|
+
"capybara-#{timestamp}#{rand(10**10)}.#{extension}"
|
|
778
779
|
end
|
|
779
780
|
|
|
780
781
|
def scopes
|
|
@@ -26,7 +26,7 @@ Capybara::SpecHelper.spec '#accept_alert', requires: [:modals] do
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
it "should accept the alert if the text matches a regexp" do
|
|
29
|
-
@session.accept_alert
|
|
29
|
+
@session.accept_alert(/op.{2}ed/) do
|
|
30
30
|
@session.click_link('Open alert')
|
|
31
31
|
end
|
|
32
32
|
expect(@session).to have_xpath("//a[@id='open-alert' and @opened='true']")
|
|
@@ -65,7 +65,7 @@ Capybara::SpecHelper.spec "#attach_file" do
|
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
it "should not break when using HTML5 multiple file input uploading multiple files" do
|
|
68
|
-
pending "Selenium is buggy on this, see http://code.google.com/p/selenium/issues/detail?id=2239" if @session.respond_to?(:mode) && @session.mode.to_s =~ /^
|
|
68
|
+
pending "Selenium is buggy on this, see http://code.google.com/p/selenium/issues/detail?id=2239" if @session.respond_to?(:mode) && @session.mode.to_s =~ /^selenium_(firefox|marionette)/
|
|
69
69
|
@session.attach_file "Multiple Documents", [@test_file_path, @another_test_file_path]
|
|
70
70
|
@session.click_button('Upload Multiple')
|
|
71
71
|
expect(@session.body).to include("2 | ")#number of files
|
|
@@ -169,6 +169,14 @@ Capybara::SpecHelper.spec "#check" do
|
|
|
169
169
|
expect(extract_results(@session)['cars']).to include('tesla')
|
|
170
170
|
end
|
|
171
171
|
|
|
172
|
+
it "should not wait the full time if label can be clicked" do
|
|
173
|
+
expect(@session.find(:checkbox, 'form_cars_tesla', unchecked: true, visible: :hidden)).to be
|
|
174
|
+
start_time = Time.now
|
|
175
|
+
@session.check('form_cars_tesla', allow_label_click: true, wait: 10)
|
|
176
|
+
end_time = Time.now
|
|
177
|
+
expect(end_time - start_time).to be < 10
|
|
178
|
+
end
|
|
179
|
+
|
|
172
180
|
it "should check via the label if input is moved off the left edge of the page" do
|
|
173
181
|
expect(@session.find(:checkbox, 'form_cars_pagani', unchecked: true, visible: :all)).to be
|
|
174
182
|
@session.check('form_cars_pagani', allow_label_click: true)
|
|
@@ -108,6 +108,11 @@ Capybara::SpecHelper.spec '#click_link_or_button' do
|
|
|
108
108
|
@session.click_link_or_button('Disabled button', disabled: false)
|
|
109
109
|
end.to raise_error(Capybara::ElementNotFound)
|
|
110
110
|
end
|
|
111
|
+
end
|
|
111
112
|
|
|
113
|
+
it "should return the element clicked" do
|
|
114
|
+
@session.visit('/with_html')
|
|
115
|
+
link = @session.find(:link, 'Blank Anchor')
|
|
116
|
+
expect(@session.click_link_or_button('Blank Anchor')).to eq link
|
|
112
117
|
end
|
|
113
118
|
end
|
|
@@ -186,4 +186,9 @@ Capybara::SpecHelper.spec '#click_link' do
|
|
|
186
186
|
expect(@session).to have_content('Another World')
|
|
187
187
|
end
|
|
188
188
|
end
|
|
189
|
+
|
|
190
|
+
it "should return element clicked" do
|
|
191
|
+
el = @session.find(:link, 'Normal Anchor')
|
|
192
|
+
expect(@session.click_link('Normal Anchor')).to eq el
|
|
193
|
+
end
|
|
189
194
|
end
|
|
@@ -28,4 +28,9 @@ Capybara::SpecHelper.spec '#assert_matches_selector' do
|
|
|
28
28
|
it "should not accept count options" do
|
|
29
29
|
expect { @element.assert_matches_selector(:css, '.number', count: 1) }.to raise_error(ArgumentError)
|
|
30
30
|
end
|
|
31
|
+
|
|
32
|
+
it "should accept a filter block" do
|
|
33
|
+
@element.assert_matches_selector(:css, 'span') { |el| el[:class] == "number" }
|
|
34
|
+
@element.assert_not_matches_selector(:css,'span') { |el| el[:class] == "not_number" }
|
|
35
|
+
end
|
|
31
36
|
end
|
|
@@ -14,4 +14,10 @@ Capybara::SpecHelper.spec '#match_css?' do
|
|
|
14
14
|
expect(@element).not_to match_css("p a#doesnotexist")
|
|
15
15
|
expect(@element).not_to match_css("p.nosuchclass")
|
|
16
16
|
end
|
|
17
|
+
|
|
18
|
+
it "should accept an optional filter block" do
|
|
19
|
+
# This would be better done with
|
|
20
|
+
expect(@element).to match_css('span') { |el| el[:class] == "number" }
|
|
21
|
+
expect(@element).not_to match_css('span') { |el| el[:class] == "not_number" }
|
|
22
|
+
end
|
|
17
23
|
end
|
|
@@ -52,6 +52,8 @@ Capybara::SpecHelper.spec '#match_selector?' do
|
|
|
52
52
|
it 'should accept a custom filter block' do
|
|
53
53
|
@session.visit('/form')
|
|
54
54
|
cbox = @session.find(:css, '#form_pets_dog')
|
|
55
|
+
expect(cbox).to match_selector(:checkbox){ |node| node[:id] == "form_pets_dog"}
|
|
56
|
+
expect(cbox).not_to match_selector(:checkbox){ |node| node[:id] != "form_pets_dog"}
|
|
55
57
|
expect(cbox.matches_selector?(:checkbox){ |node| node[:id] == "form_pets_dog"}).to be true
|
|
56
58
|
expect(cbox.matches_selector?(:checkbox){ |node| node[:id] != "form_pets_dog"}).to be false
|
|
57
59
|
end
|
|
@@ -181,4 +181,9 @@ Capybara::SpecHelper.spec "#fill_in" do
|
|
|
181
181
|
end.to raise_error(Capybara::ElementNotFound)
|
|
182
182
|
end
|
|
183
183
|
end
|
|
184
|
+
|
|
185
|
+
it "should return the element filled in" do
|
|
186
|
+
el = @session.find(:fillable_field, 'form_first_name')
|
|
187
|
+
expect(@session.fill_in('form_first_name', with: 'Harry')).to eq el
|
|
188
|
+
end
|
|
184
189
|
end
|
|
@@ -320,7 +320,7 @@ Capybara::SpecHelper.spec '#find' do
|
|
|
320
320
|
end
|
|
321
321
|
it "raises an error when there is a single inexact matches" do
|
|
322
322
|
expect do
|
|
323
|
-
|
|
323
|
+
@session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular but")], match: :smart, exact: true)
|
|
324
324
|
end.to raise_error(Capybara::ElementNotFound)
|
|
325
325
|
end
|
|
326
326
|
it "raises an error if there is no match" do
|
|
@@ -19,6 +19,11 @@ Capybara::SpecHelper.spec '#first' do
|
|
|
19
19
|
expect(@session.first(@xpath).value).to eq('John')
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
+
it "should warn when unused parameters are passed" do
|
|
23
|
+
expect_any_instance_of(Kernel).to receive(:warn).with(/Unused parameters passed.*unused text/)
|
|
24
|
+
@session.first(:css, '.header h2', 'unused text')
|
|
25
|
+
end
|
|
26
|
+
|
|
22
27
|
context "with css selectors" do
|
|
23
28
|
it "should find the first element using the given selector" do
|
|
24
29
|
expect(@session.first(:css, 'h1').text).to eq('This is a test')
|
|
@@ -48,21 +53,26 @@ Capybara::SpecHelper.spec '#first' do
|
|
|
48
53
|
|
|
49
54
|
it "should find nodes regardless of whether they are invisible when false" do
|
|
50
55
|
expect(@session.first(:css, "a#invisible", visible: false)).not_to be_nil
|
|
56
|
+
expect(@session.first(:css, "a#invisible", visible: false, text: 'hidden link')).not_to be_nil
|
|
51
57
|
expect(@session.first(:css, "a#visible", visible: false)).not_to be_nil
|
|
52
58
|
end
|
|
53
59
|
|
|
54
60
|
it "should find nodes regardless of whether they are invisible when :all" do
|
|
55
61
|
expect(@session.first(:css, "a#invisible", visible: :all)).not_to be_nil
|
|
62
|
+
expect(@session.first(:css, "a#invisible", visible: :all, text: 'hidden link')).not_to be_nil
|
|
56
63
|
expect(@session.first(:css, "a#visible", visible: :all)).not_to be_nil
|
|
57
64
|
end
|
|
58
65
|
|
|
59
66
|
it "should find only hidden nodes when :hidden" do
|
|
60
67
|
expect(@session.first(:css, "a#invisible", visible: :hidden)).not_to be_nil
|
|
68
|
+
expect(@session.first(:css, "a#invisible", visible: :hidden, text: 'hidden link')).not_to be_nil
|
|
69
|
+
expect(@session.first(:css, "a#invisible", visible: :hidden, text: 'not hidden link')).to be_nil
|
|
61
70
|
expect(@session.first(:css, "a#visible", visible: :hidden)).to be_nil
|
|
62
71
|
end
|
|
63
72
|
|
|
64
73
|
it "should find only visible nodes when :visible" do
|
|
65
74
|
expect(@session.first(:css, "a#invisible", visible: :visible)).to be_nil
|
|
75
|
+
expect(@session.first(:css, "a#invisible", visible: :visible, text: 'hidden link')).to be_nil
|
|
66
76
|
expect(@session.first(:css, "a#visible", visible: :visible)).not_to be_nil
|
|
67
77
|
end
|
|
68
78
|
|
|
@@ -29,6 +29,10 @@ Capybara::SpecHelper.spec '#has_selector?' do
|
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
it "should accept a filter block" do
|
|
33
|
+
expect(@session).to have_selector(:css, "a", count: 1) { |el| el[:id] == "foo" }
|
|
34
|
+
end
|
|
35
|
+
|
|
32
36
|
context "with count" do
|
|
33
37
|
it "should be true if the content is on the page the given number of times" do
|
|
34
38
|
expect(@session).to have_selector("//p", count: 3)
|
|
@@ -105,6 +109,13 @@ Capybara::SpecHelper.spec '#has_no_selector?' do
|
|
|
105
109
|
end
|
|
106
110
|
end
|
|
107
111
|
|
|
112
|
+
it "should accept a filter block" do
|
|
113
|
+
if !defined?(::RSpec::Expectations::Version) || (Gem::Version.new(RSpec::Expectations::Version::STRING) < Gem::Version.new('3.0'))
|
|
114
|
+
skip "RSpec < 3 doesn't pass the block along to the matcher for the Builtin::Has matcher"
|
|
115
|
+
end
|
|
116
|
+
expect(@session).to have_no_selector(:css, "a#foo") { |el| el[:id] != "foo" }
|
|
117
|
+
end
|
|
118
|
+
|
|
108
119
|
context "with count" do
|
|
109
120
|
it "should be false if the content is on the page the given number of times" do
|
|
110
121
|
expect(@session).not_to have_no_selector("//p", count: 3)
|
|
@@ -425,7 +425,18 @@ Capybara::SpecHelper.spec "node" do
|
|
|
425
425
|
@session.find(:css, 'span')
|
|
426
426
|
end.to raise_error(TestApp::TestAppError) do |e|
|
|
427
427
|
expect(e.cause).to be_a Capybara::CapybaraError
|
|
428
|
-
expect(e.cause.message).to match
|
|
428
|
+
expect(e.cause.message).to match(/Your application server raised an error/)
|
|
429
|
+
end
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
it "sets an explanatory exception as the cause of server exceptions with errors with initializers", requires: [:server, :js] do
|
|
433
|
+
skip "This version of ruby doesn't support exception causes" unless Exception.instance_methods.include? :cause
|
|
434
|
+
quietly { @session.visit("/other_error") }
|
|
435
|
+
expect do
|
|
436
|
+
@session.find(:css, 'span')
|
|
437
|
+
end.to raise_error(TestApp::TestAppOtherError) do |e|
|
|
438
|
+
expect(e.cause).to be_a Capybara::CapybaraError
|
|
439
|
+
expect(e.cause.message).to match(/Your application server raised an error/)
|
|
429
440
|
end
|
|
430
441
|
end
|
|
431
442
|
end
|
|
@@ -35,7 +35,7 @@ Capybara::SpecHelper.spec '#text' do
|
|
|
35
35
|
Capybara.ignore_hidden_elements = false
|
|
36
36
|
expect(@session.find(:id, "hidden-text").text).to eq('Some of this text is')
|
|
37
37
|
end
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
it "ignores invisible text if ancestor is invisible" do
|
|
40
40
|
@session.visit('/with_html')
|
|
41
41
|
expect(@session.find(:id, "hidden_via_ancestor", visible: false).text).to eq('')
|
|
@@ -52,8 +52,7 @@ Capybara::SpecHelper.spec '#text' do
|
|
|
52
52
|
|
|
53
53
|
it "should strip whitespace" do
|
|
54
54
|
@session.visit('/with_html')
|
|
55
|
-
|
|
56
|
-
expect(@session.find(:css, '#second').text).to match
|
|
57
|
-
/\ADuis aute .* text with whitespace .* est laborum\.\z/
|
|
55
|
+
@session.find(:css, '#second')
|
|
56
|
+
expect(@session.find(:css, '#second').text).to match(/\ADuis aute .* text with whitespace .* est laborum\.\z/)
|
|
58
57
|
end
|
|
59
58
|
end
|
|
@@ -6,7 +6,12 @@ require 'yaml'
|
|
|
6
6
|
|
|
7
7
|
class TestApp < Sinatra::Base
|
|
8
8
|
class TestAppError < StandardError; end
|
|
9
|
-
|
|
9
|
+
class TestAppOtherError < StandardError
|
|
10
|
+
def initialize(string1, msg)
|
|
11
|
+
@something = string1
|
|
12
|
+
@message = msg
|
|
13
|
+
end
|
|
14
|
+
end
|
|
10
15
|
set :root, File.dirname(__FILE__)
|
|
11
16
|
set :static, true
|
|
12
17
|
set :raise_errors, true
|
|
@@ -125,6 +130,10 @@ class TestApp < Sinatra::Base
|
|
|
125
130
|
raise TestAppError, "some error"
|
|
126
131
|
end
|
|
127
132
|
|
|
133
|
+
get '/other_error' do
|
|
134
|
+
raise TestAppOtherError.new("something", "other error")
|
|
135
|
+
end
|
|
136
|
+
|
|
128
137
|
get '/load_error' do
|
|
129
138
|
raise LoadError
|
|
130
139
|
end
|
data/lib/capybara/version.rb
CHANGED
data/lib/capybara/window.rb
CHANGED
|
@@ -85,7 +85,7 @@ module Capybara
|
|
|
85
85
|
# @param height [String] the new window height in pixels
|
|
86
86
|
#
|
|
87
87
|
def resize_to(width, height)
|
|
88
|
-
@driver.resize_window_to(handle, width, height)
|
|
88
|
+
wait_for_stable_size { @driver.resize_window_to(handle, width, height) }
|
|
89
89
|
end
|
|
90
90
|
|
|
91
91
|
##
|
|
@@ -97,7 +97,7 @@ module Capybara
|
|
|
97
97
|
# @macro about_current
|
|
98
98
|
#
|
|
99
99
|
def maximize
|
|
100
|
-
@driver.maximize_window(handle)
|
|
100
|
+
wait_for_stable_size { @driver.maximize_window(handle) }
|
|
101
101
|
end
|
|
102
102
|
|
|
103
103
|
def eql?(other)
|
|
@@ -115,6 +115,22 @@ module Capybara
|
|
|
115
115
|
|
|
116
116
|
private
|
|
117
117
|
|
|
118
|
+
def wait_for_stable_size(seconds=Capybara.default_max_wait_time)
|
|
119
|
+
res = yield if block_given?
|
|
120
|
+
prev_size = size
|
|
121
|
+
start_time = Capybara::Helpers.monotonic_time
|
|
122
|
+
begin
|
|
123
|
+
sleep 0.05
|
|
124
|
+
cur_size = size
|
|
125
|
+
return res if cur_size == prev_size
|
|
126
|
+
prev_size = cur_size
|
|
127
|
+
end while (Capybara::Helpers.monotonic_time - start_time) < seconds
|
|
128
|
+
#TODO raise error in 3.0
|
|
129
|
+
#raise Capybara::WindowError, "Window size not stable."
|
|
130
|
+
warn "Window size not stable in #{seconds} seconds. This will raise an exception in a future version of Capybara"
|
|
131
|
+
return res
|
|
132
|
+
end
|
|
133
|
+
|
|
118
134
|
def raise_unless_current(what)
|
|
119
135
|
unless current?
|
|
120
136
|
raise Capybara::WindowError, "#{what} not current window is not possible."
|
data/lib/capybara.rb
CHANGED
|
@@ -25,7 +25,8 @@ module Capybara
|
|
|
25
25
|
attr_accessor :server_port, :exact, :match, :exact_options, :visible_text_only, :enable_aria_label
|
|
26
26
|
attr_accessor :default_selector, :default_max_wait_time, :ignore_hidden_elements
|
|
27
27
|
attr_accessor :save_path, :wait_on_first_by_default, :automatic_label_click, :automatic_reload
|
|
28
|
-
|
|
28
|
+
attr_reader :reuse_server
|
|
29
|
+
attr_accessor :raise_server_errors, :server_errors
|
|
29
30
|
attr_writer :default_driver, :current_driver, :javascript_driver, :session_name, :server_host
|
|
30
31
|
attr_reader :save_and_open_page_path
|
|
31
32
|
attr_accessor :app
|
|
@@ -331,7 +332,7 @@ module Capybara
|
|
|
331
332
|
#
|
|
332
333
|
def reset_sessions!
|
|
333
334
|
#reset in reverse so sessions that started servers are reset last
|
|
334
|
-
session_pool.reverse_each { |
|
|
335
|
+
session_pool.reverse_each { |_mode, session| session.reset! }
|
|
335
336
|
end
|
|
336
337
|
alias_method :reset!, :reset_sessions!
|
|
337
338
|
|
|
@@ -391,12 +392,12 @@ module Capybara
|
|
|
391
392
|
end
|
|
392
393
|
|
|
393
394
|
def app_host=(url)
|
|
394
|
-
raise ArgumentError.new("Capybara.app_host should be set to a url (http://www.example.com)") unless url.nil? || (url =~ URI::
|
|
395
|
+
raise ArgumentError.new("Capybara.app_host should be set to a url (http://www.example.com)") unless url.nil? || (url =~ URI::Parser.new.make_regexp)
|
|
395
396
|
@app_host = url
|
|
396
397
|
end
|
|
397
398
|
|
|
398
399
|
def default_host=(url)
|
|
399
|
-
raise ArgumentError.new("Capybara.default_host should be set to a url (http://www.example.com)") unless url.nil? || (url =~ URI::
|
|
400
|
+
raise ArgumentError.new("Capybara.default_host should be set to a url (http://www.example.com)") unless url.nil? || (url =~ URI::Parser.new.make_regexp)
|
|
400
401
|
@default_host = url
|
|
401
402
|
end
|
|
402
403
|
|
|
@@ -469,7 +470,7 @@ module Capybara
|
|
|
469
470
|
require 'capybara/selenium/driver'
|
|
470
471
|
end
|
|
471
472
|
|
|
472
|
-
Capybara.register_server :default do |app, port,
|
|
473
|
+
Capybara.register_server :default do |app, port, _host|
|
|
473
474
|
Capybara.run_default_server(app, port)
|
|
474
475
|
end
|
|
475
476
|
|
|
@@ -479,10 +480,8 @@ Capybara.register_server :webrick do |app, port, host|
|
|
|
479
480
|
end
|
|
480
481
|
|
|
481
482
|
Capybara.register_server :puma do |app, port, host|
|
|
482
|
-
require 'puma'
|
|
483
|
-
Puma
|
|
484
|
-
s.add_tcp_listener host, port
|
|
485
|
-
end.run.join
|
|
483
|
+
require 'rack/handler/puma'
|
|
484
|
+
Rack::Handler::Puma.run(app, Host: host, Port: port, Threads: "0:4")
|
|
486
485
|
end
|
|
487
486
|
|
|
488
487
|
Capybara.configure do |config|
|
data/spec/basic_node_spec.rb
CHANGED
|
@@ -52,7 +52,7 @@ RSpec.describe Capybara do
|
|
|
52
52
|
|
|
53
53
|
it "allows using custom matchers" do
|
|
54
54
|
Capybara.add_selector :lifeform do
|
|
55
|
-
xpath { |name| "
|
|
55
|
+
xpath { |name| ".//option[contains(.,'#{name}')]" }
|
|
56
56
|
end
|
|
57
57
|
expect(string).to have_selector(:id, "page")
|
|
58
58
|
expect(string).not_to have_selector(:id, 'does-not-exist')
|
data/spec/capybara_spec.rb
CHANGED
|
@@ -46,11 +46,14 @@ RSpec.describe Capybara do
|
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
it "should add a new server" do
|
|
49
|
+
skip "JRuby fails this because of path issues to geckodriver I think. Its tested in other runs - not worth figuring out at this time" if RUBY_PLATFORM == 'java'
|
|
50
|
+
|
|
51
|
+
require 'rack/handler/webrick'
|
|
49
52
|
Capybara.register_server :blob do |app, port, host|
|
|
50
53
|
Rack::Handler::WEBrick.run(app, Host: host, Port: port, AccessLog: [], Logger: WEBrick::Log::new(nil, 0))
|
|
51
54
|
end
|
|
52
55
|
Capybara.server = :blob
|
|
53
|
-
session = Capybara::Session.new(:selenium, TestApp.
|
|
56
|
+
session = Capybara::Session.new(:selenium, TestApp.new)
|
|
54
57
|
session.visit('/')
|
|
55
58
|
expect(session.body).to include("Hello world!")
|
|
56
59
|
end
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
require 'spec_helper'
|
|
3
|
+
require 'selenium-webdriver'
|
|
3
4
|
|
|
4
5
|
RSpec.describe Capybara::Selenium::Driver do
|
|
5
6
|
it "should exit with a non-zero exit status" do
|
|
6
|
-
|
|
7
|
+
options = { browser: (ENV['SELENIUM_BROWSER'] || :firefox).to_sym }
|
|
8
|
+
options[:desired_capabilities] = Selenium::WebDriver::Remote::Capabilities.firefox(marionette: false) if ENV['LEGACY_FIREFOX']
|
|
9
|
+
browser = Capybara::Selenium::Driver.new(TestApp, options).browser
|
|
7
10
|
expect(true).to eq(false)
|
|
8
11
|
end
|
|
9
12
|
end
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
require 'spec_helper'
|
|
3
|
+
require 'selenium-webdriver'
|
|
3
4
|
|
|
4
5
|
RSpec.describe Capybara::Selenium::Driver do
|
|
5
6
|
it "should exit with a zero exit status" do
|
|
6
|
-
|
|
7
|
+
options = { browser: (ENV['SELENIUM_BROWSER'] || :firefox).to_sym }
|
|
8
|
+
options[:desired_capabilities] = Selenium::WebDriver::Remote::Capabilities.firefox(marionette: false) if ENV['LEGACY_FIREFOX']
|
|
9
|
+
browser = Capybara::Selenium::Driver.new(TestApp, options ).browser
|
|
7
10
|
expect(true).to eq(true)
|
|
8
11
|
end
|
|
9
12
|
end
|