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
|
@@ -90,14 +90,11 @@ module Capybara
|
|
|
90
90
|
# @raise [Capybara::ExpectationNotMet] If the selector does not exist
|
|
91
91
|
#
|
|
92
92
|
def assert_selector(*args, &optional_filter_block)
|
|
93
|
-
|
|
94
|
-
synchronize(query.wait) do
|
|
95
|
-
result = query.resolve_for(self)
|
|
93
|
+
_verify_selector_result(args, optional_filter_block) do |result, query|
|
|
96
94
|
unless result.matches_count? && ((!result.empty?) || query.expects_none?)
|
|
97
95
|
raise Capybara::ExpectationNotMet, result.failure_message
|
|
98
96
|
end
|
|
99
97
|
end
|
|
100
|
-
return true
|
|
101
98
|
end
|
|
102
99
|
|
|
103
100
|
##
|
|
@@ -117,14 +114,11 @@ module Capybara
|
|
|
117
114
|
# @raise [Capybara::ExpectationNotMet] If the selector exists
|
|
118
115
|
#
|
|
119
116
|
def assert_no_selector(*args, &optional_filter_block)
|
|
120
|
-
|
|
121
|
-
synchronize(query.wait) do
|
|
122
|
-
result = query.resolve_for(self)
|
|
117
|
+
_verify_selector_result(args, optional_filter_block) do |result, query|
|
|
123
118
|
if result.matches_count? && ((!result.empty?) || query.expects_none?)
|
|
124
119
|
raise Capybara::ExpectationNotMet, result.negative_failure_message
|
|
125
120
|
end
|
|
126
121
|
end
|
|
127
|
-
return true
|
|
128
122
|
end
|
|
129
123
|
alias_method :refute_selector, :assert_no_selector
|
|
130
124
|
|
|
@@ -333,7 +327,7 @@ module Capybara
|
|
|
333
327
|
#
|
|
334
328
|
def has_no_checked_field?(locator=nil, options={}, &optional_filter_block)
|
|
335
329
|
locator, options = nil, locator if locator.is_a? Hash
|
|
336
|
-
has_no_selector?(:field, locator, options.merge(checked: true))
|
|
330
|
+
has_no_selector?(:field, locator, options.merge(checked: true), &optional_filter_block)
|
|
337
331
|
end
|
|
338
332
|
|
|
339
333
|
##
|
|
@@ -455,25 +449,15 @@ module Capybara
|
|
|
455
449
|
# @raise [Capybara::ExpectationNotMet] If the selector does not match
|
|
456
450
|
#
|
|
457
451
|
def assert_matches_selector(*args, &optional_filter_block)
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
result = query.resolve_for(self.query_scope)
|
|
461
|
-
unless result.include? self
|
|
462
|
-
raise Capybara::ExpectationNotMet, "Item does not match the provided selector"
|
|
463
|
-
end
|
|
452
|
+
_verify_match_result(args, optional_filter_block) do |result|
|
|
453
|
+
raise Capybara::ExpectationNotMet, "Item does not match the provided selector" unless result.include? self
|
|
464
454
|
end
|
|
465
|
-
return true
|
|
466
455
|
end
|
|
467
456
|
|
|
468
457
|
def assert_not_matches_selector(*args, &optional_filter_block)
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
result = query.resolve_for(self.query_scope)
|
|
472
|
-
if result.include? self
|
|
473
|
-
raise Capybara::ExpectationNotMet, 'Item matched the provided selector'
|
|
474
|
-
end
|
|
458
|
+
_verify_match_result(args, optional_filter_block) do |result|
|
|
459
|
+
raise Capybara::ExpectationNotMet, 'Item matched the provided selector' if result.include? self
|
|
475
460
|
end
|
|
476
|
-
return true
|
|
477
461
|
end
|
|
478
462
|
alias_method :refute_matches_selector, :assert_not_matches_selector
|
|
479
463
|
|
|
@@ -573,14 +557,11 @@ module Capybara
|
|
|
573
557
|
# @return [true]
|
|
574
558
|
#
|
|
575
559
|
def assert_text(*args)
|
|
576
|
-
|
|
577
|
-
synchronize(query.wait) do
|
|
578
|
-
count = query.resolve_for(self)
|
|
560
|
+
_verify_text(args) do |count, query|
|
|
579
561
|
unless query.matches_count?(count) && ((count > 0) || query.expects_none?)
|
|
580
562
|
raise Capybara::ExpectationNotMet, query.failure_message
|
|
581
563
|
end
|
|
582
564
|
end
|
|
583
|
-
return true
|
|
584
565
|
end
|
|
585
566
|
|
|
586
567
|
##
|
|
@@ -592,14 +573,11 @@ module Capybara
|
|
|
592
573
|
# @return [true]
|
|
593
574
|
#
|
|
594
575
|
def assert_no_text(*args)
|
|
595
|
-
|
|
596
|
-
synchronize(query.wait) do
|
|
597
|
-
count = query.resolve_for(self)
|
|
576
|
+
_verify_text(args) do |count, query|
|
|
598
577
|
if query.matches_count?(count) && ((count > 0) || query.expects_none?)
|
|
599
578
|
raise Capybara::ExpectationNotMet, query.negative_failure_message
|
|
600
579
|
end
|
|
601
580
|
end
|
|
602
|
-
return true
|
|
603
581
|
end
|
|
604
582
|
|
|
605
583
|
##
|
|
@@ -645,6 +623,35 @@ module Capybara
|
|
|
645
623
|
self.eql?(other) || (other.respond_to?(:base) && base == other.base)
|
|
646
624
|
end
|
|
647
625
|
|
|
626
|
+
private
|
|
627
|
+
|
|
628
|
+
def _verify_selector_result(query_args, optional_filter_block, &result_block)
|
|
629
|
+
query = Capybara::Queries::SelectorQuery.new(*query_args, &optional_filter_block)
|
|
630
|
+
synchronize(query.wait) do
|
|
631
|
+
result = query.resolve_for(self)
|
|
632
|
+
result_block.call(result, query)
|
|
633
|
+
end
|
|
634
|
+
return true
|
|
635
|
+
end
|
|
636
|
+
|
|
637
|
+
def _verify_match_result(query_args, optional_filter_block, &result_block)
|
|
638
|
+
query = Capybara::Queries::MatchQuery.new(*query_args, &optional_filter_block)
|
|
639
|
+
synchronize(query.wait) do
|
|
640
|
+
result = query.resolve_for(self.query_scope)
|
|
641
|
+
result_block.call(result)
|
|
642
|
+
end
|
|
643
|
+
return true
|
|
644
|
+
end
|
|
645
|
+
|
|
646
|
+
def _verify_text(query_args)
|
|
647
|
+
query = Capybara::Queries::TextQuery.new(*query_args)
|
|
648
|
+
synchronize(query.wait) do
|
|
649
|
+
count = query.resolve_for(self)
|
|
650
|
+
yield(count, query)
|
|
651
|
+
end
|
|
652
|
+
return true
|
|
653
|
+
end
|
|
654
|
+
|
|
648
655
|
end
|
|
649
656
|
end
|
|
650
657
|
end
|
data/lib/capybara/node/simple.rb
CHANGED
|
@@ -53,7 +53,9 @@ module Capybara
|
|
|
53
53
|
def matches_filters?(node)
|
|
54
54
|
if options[:text]
|
|
55
55
|
regexp = options[:text].is_a?(Regexp) ? options[:text] : Regexp.escape(options[:text].to_s)
|
|
56
|
-
|
|
56
|
+
text_visible = visible
|
|
57
|
+
text_visible = :all if text_visible == :hidden
|
|
58
|
+
return false if not node.text(text_visible).match(regexp)
|
|
57
59
|
end
|
|
58
60
|
|
|
59
61
|
case visible
|
|
@@ -71,7 +73,7 @@ module Capybara
|
|
|
71
73
|
end
|
|
72
74
|
end
|
|
73
75
|
|
|
74
|
-
res &&= @filter_block.call(node) unless @filter_block.nil?
|
|
76
|
+
res &&= Capybara.using_wait_time(0){ @filter_block.call(node)} unless @filter_block.nil?
|
|
75
77
|
res
|
|
76
78
|
end
|
|
77
79
|
|
|
@@ -152,7 +152,7 @@ private
|
|
|
152
152
|
end
|
|
153
153
|
end
|
|
154
154
|
|
|
155
|
-
def set_radio(
|
|
155
|
+
def set_radio(_value)
|
|
156
156
|
other_radios_xpath = XPath.generate { |x| x.anywhere(:input)[x.attr(:name).equals(self[:name])] }.to_s
|
|
157
157
|
driver.dom.xpath(other_radios_xpath).each { |node| node.remove_attribute("checked") }
|
|
158
158
|
native['checked'] = 'checked'
|
data/lib/capybara/result.rb
CHANGED
|
@@ -40,6 +40,8 @@ module Capybara
|
|
|
40
40
|
alias :index :find_index
|
|
41
41
|
|
|
42
42
|
def each(&block)
|
|
43
|
+
return enum_for(:each) unless block_given?
|
|
44
|
+
|
|
43
45
|
@result_cache.each(&block)
|
|
44
46
|
loop do
|
|
45
47
|
next_result = @results_enum.next
|
|
@@ -137,7 +139,7 @@ module Capybara
|
|
|
137
139
|
|
|
138
140
|
def lazy_select_elements(&block)
|
|
139
141
|
if @elements.respond_to? :lazy #Ruby 2.0+
|
|
140
|
-
@elements.lazy.select
|
|
142
|
+
@elements.lazy.select(&block)
|
|
141
143
|
else
|
|
142
144
|
Enumerator.new do |yielder|
|
|
143
145
|
@elements.each do |val|
|
|
@@ -4,6 +4,8 @@ module Capybara
|
|
|
4
4
|
class Matcher
|
|
5
5
|
include ::RSpec::Matchers::Composable if defined?(::RSpec::Expectations::Version) && (Gem::Version.new(RSpec::Expectations::Version::STRING) >= Gem::Version.new('3.0'))
|
|
6
6
|
|
|
7
|
+
attr_reader :failure_message, :failure_message_when_negated
|
|
8
|
+
|
|
7
9
|
def wrap(actual)
|
|
8
10
|
if actual.respond_to?("has_selector?")
|
|
9
11
|
actual
|
|
@@ -11,10 +13,29 @@ module Capybara
|
|
|
11
13
|
Capybara.string(actual.to_s)
|
|
12
14
|
end
|
|
13
15
|
end
|
|
16
|
+
|
|
17
|
+
# RSpec 2 compatibility:
|
|
18
|
+
def failure_message_for_should; failure_message end
|
|
19
|
+
def failure_message_for_should_not; failure_message_when_negated end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def wrap_matches?(actual)
|
|
24
|
+
yield(wrap(actual))
|
|
25
|
+
rescue Capybara::ExpectationNotMet => e
|
|
26
|
+
@failure_message = e.message
|
|
27
|
+
return false
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def wrap_does_not_match?(actual)
|
|
31
|
+
yield(wrap(actual))
|
|
32
|
+
rescue Capybara::ExpectationNotMet => e
|
|
33
|
+
@failure_message_when_negated = e.message
|
|
34
|
+
return false
|
|
35
|
+
end
|
|
14
36
|
end
|
|
15
37
|
|
|
16
38
|
class HaveSelector < Matcher
|
|
17
|
-
attr_reader :failure_message, :failure_message_when_negated
|
|
18
39
|
|
|
19
40
|
def initialize(*args, &filter_block)
|
|
20
41
|
@args = args
|
|
@@ -22,17 +43,11 @@ module Capybara
|
|
|
22
43
|
end
|
|
23
44
|
|
|
24
45
|
def matches?(actual)
|
|
25
|
-
|
|
26
|
-
rescue Capybara::ExpectationNotMet => e
|
|
27
|
-
@failure_message = e.message
|
|
28
|
-
return false
|
|
46
|
+
wrap_matches?(actual){ |el| el.assert_selector(*@args, &@filter_block) }
|
|
29
47
|
end
|
|
30
48
|
|
|
31
49
|
def does_not_match?(actual)
|
|
32
|
-
|
|
33
|
-
rescue Capybara::ExpectationNotMet => e
|
|
34
|
-
@failure_message_when_negated = e.message
|
|
35
|
-
return false
|
|
50
|
+
wrap_does_not_match?(actual){ |el| el.assert_no_selector(*@args, &@filter_block) }
|
|
36
51
|
end
|
|
37
52
|
|
|
38
53
|
def description
|
|
@@ -42,17 +57,29 @@ module Capybara
|
|
|
42
57
|
def query
|
|
43
58
|
@query ||= Capybara::Queries::SelectorQuery.new(*@args, &@filter_block)
|
|
44
59
|
end
|
|
60
|
+
end
|
|
45
61
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
62
|
+
class MatchSelector < HaveSelector
|
|
63
|
+
def matches?(actual)
|
|
64
|
+
wrap_matches?(actual) { |el| el.assert_matches_selector(*@args, &@filter_block) }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def does_not_match?(actual)
|
|
68
|
+
wrap_does_not_match?(actual) { |el| el.assert_not_matches_selector(*@args, &@filter_block) }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def description
|
|
72
|
+
"match #{query.description}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def query
|
|
76
|
+
@query ||= Capybara::Queries::MatchQuery.new(*@args)
|
|
77
|
+
end
|
|
49
78
|
end
|
|
50
79
|
|
|
51
80
|
class HaveText < Matcher
|
|
52
81
|
attr_reader :type, :content, :options
|
|
53
82
|
|
|
54
|
-
attr_reader :failure_message, :failure_message_when_negated
|
|
55
|
-
|
|
56
83
|
def initialize(*args)
|
|
57
84
|
@args = args.dup
|
|
58
85
|
|
|
@@ -63,17 +90,11 @@ module Capybara
|
|
|
63
90
|
end
|
|
64
91
|
|
|
65
92
|
def matches?(actual)
|
|
66
|
-
|
|
67
|
-
rescue Capybara::ExpectationNotMet => e
|
|
68
|
-
@failure_message = e.message
|
|
69
|
-
return false
|
|
93
|
+
wrap_matches?(actual) { |el| el.assert_text(*@args) }
|
|
70
94
|
end
|
|
71
95
|
|
|
72
96
|
def does_not_match?(actual)
|
|
73
|
-
|
|
74
|
-
rescue Capybara::ExpectationNotMet => e
|
|
75
|
-
@failure_message_when_negated = e.message
|
|
76
|
-
return false
|
|
97
|
+
wrap_does_not_match?(actual) { |el| el.assert_no_text(*@args) }
|
|
77
98
|
end
|
|
78
99
|
|
|
79
100
|
def description
|
|
@@ -84,17 +105,11 @@ module Capybara
|
|
|
84
105
|
content = Capybara::Helpers.normalize_whitespace(content) unless content.is_a? Regexp
|
|
85
106
|
content.inspect
|
|
86
107
|
end
|
|
87
|
-
|
|
88
|
-
# RSpec 2 compatibility:
|
|
89
|
-
alias_method :failure_message_for_should, :failure_message
|
|
90
|
-
alias_method :failure_message_for_should_not, :failure_message_when_negated
|
|
91
108
|
end
|
|
92
109
|
|
|
93
110
|
class HaveTitle < Matcher
|
|
94
111
|
attr_reader :title
|
|
95
112
|
|
|
96
|
-
attr_reader :failure_message, :failure_message_when_negated
|
|
97
|
-
|
|
98
113
|
def initialize(*args)
|
|
99
114
|
@args = args
|
|
100
115
|
|
|
@@ -103,33 +118,21 @@ module Capybara
|
|
|
103
118
|
end
|
|
104
119
|
|
|
105
120
|
def matches?(actual)
|
|
106
|
-
|
|
107
|
-
rescue Capybara::ExpectationNotMet => e
|
|
108
|
-
@failure_message = e.message
|
|
109
|
-
return false
|
|
121
|
+
wrap_matches?(actual) { |el| el.assert_title(*@args) }
|
|
110
122
|
end
|
|
111
123
|
|
|
112
124
|
def does_not_match?(actual)
|
|
113
|
-
|
|
114
|
-
rescue Capybara::ExpectationNotMet => e
|
|
115
|
-
@failure_message_when_negated = e.message
|
|
116
|
-
return false
|
|
125
|
+
wrap_does_not_match?(actual) { |el| el.assert_no_title(*@args) }
|
|
117
126
|
end
|
|
118
127
|
|
|
119
128
|
def description
|
|
120
129
|
"have title #{title.inspect}"
|
|
121
130
|
end
|
|
122
|
-
|
|
123
|
-
# RSpec 2 compatibility:
|
|
124
|
-
alias_method :failure_message_for_should, :failure_message
|
|
125
|
-
alias_method :failure_message_for_should_not, :failure_message_when_negated
|
|
126
131
|
end
|
|
127
132
|
|
|
128
133
|
class HaveCurrentPath < Matcher
|
|
129
134
|
attr_reader :current_path
|
|
130
135
|
|
|
131
|
-
attr_reader :failure_message, :failure_message_when_negated
|
|
132
|
-
|
|
133
136
|
def initialize(*args)
|
|
134
137
|
@args = args
|
|
135
138
|
|
|
@@ -138,26 +141,16 @@ module Capybara
|
|
|
138
141
|
end
|
|
139
142
|
|
|
140
143
|
def matches?(actual)
|
|
141
|
-
|
|
142
|
-
rescue Capybara::ExpectationNotMet => e
|
|
143
|
-
@failure_message = e.message
|
|
144
|
-
return false
|
|
144
|
+
wrap_matches?(actual) { |el| el.assert_current_path(*@args) }
|
|
145
145
|
end
|
|
146
146
|
|
|
147
147
|
def does_not_match?(actual)
|
|
148
|
-
|
|
149
|
-
rescue Capybara::ExpectationNotMet => e
|
|
150
|
-
@failure_message_when_negated = e.message
|
|
151
|
-
return false
|
|
148
|
+
wrap_does_not_match?(actual) { |el| el.assert_no_current_path(*@args) }
|
|
152
149
|
end
|
|
153
150
|
|
|
154
151
|
def description
|
|
155
152
|
"have current path #{current_path.inspect}"
|
|
156
153
|
end
|
|
157
|
-
|
|
158
|
-
# RSpec 2 compatibility:
|
|
159
|
-
alias_method :failure_message_for_should, :failure_message
|
|
160
|
-
alias_method :failure_message_for_should_not, :failure_message_when_negated
|
|
161
154
|
end
|
|
162
155
|
|
|
163
156
|
class BecomeClosed
|
|
@@ -188,46 +181,12 @@ module Capybara
|
|
|
188
181
|
alias_method :failure_message_for_should_not, :failure_message_when_negated
|
|
189
182
|
end
|
|
190
183
|
|
|
191
|
-
class MatchSelector < Matcher
|
|
192
|
-
attr_reader :failure_message, :failure_message_when_negated
|
|
193
|
-
|
|
194
|
-
def initialize(*args)
|
|
195
|
-
@args = args
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
def matches?(actual)
|
|
199
|
-
actual.assert_matches_selector(*@args)
|
|
200
|
-
rescue Capybara::ExpectationNotMet => e
|
|
201
|
-
@failure_message = e.message
|
|
202
|
-
return false
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
def does_not_match?(actual)
|
|
206
|
-
actual.assert_not_matches_selector(*@args)
|
|
207
|
-
rescue Capybara::ExpectationNotMet => e
|
|
208
|
-
@failure_message_when_negated = e.message
|
|
209
|
-
return false
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
def description
|
|
213
|
-
"match #{query.description}"
|
|
214
|
-
end
|
|
215
|
-
|
|
216
|
-
def query
|
|
217
|
-
@query ||= Capybara::Queries::MatchQuery.new(*@args)
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
# RSpec 2 compatibility:
|
|
221
|
-
alias_method :failure_message_for_should, :failure_message
|
|
222
|
-
alias_method :failure_message_for_should_not, :failure_message_when_negated
|
|
223
|
-
end
|
|
224
|
-
|
|
225
184
|
def have_selector(*args, &optional_filter_block)
|
|
226
185
|
HaveSelector.new(*args, &optional_filter_block)
|
|
227
186
|
end
|
|
228
187
|
|
|
229
|
-
def match_selector(*args)
|
|
230
|
-
MatchSelector.new(*args)
|
|
188
|
+
def match_selector(*args, &optional_filter_block)
|
|
189
|
+
MatchSelector.new(*args, &optional_filter_block)
|
|
231
190
|
end
|
|
232
191
|
# defined_negated_matcher was added in RSpec 3.1 - it's syntactic sugar only since a user can do
|
|
233
192
|
# expect(page).not_to match_selector, so not sure we really need to support not_match_selector for prior to RSpec 3.1
|
|
@@ -238,16 +197,16 @@ module Capybara
|
|
|
238
197
|
HaveSelector.new(:xpath, xpath, options, &optional_filter_block)
|
|
239
198
|
end
|
|
240
199
|
|
|
241
|
-
def match_xpath(xpath, options={})
|
|
242
|
-
MatchSelector.new(:xpath, xpath, options)
|
|
200
|
+
def match_xpath(xpath, options={}, &optional_filter_block)
|
|
201
|
+
MatchSelector.new(:xpath, xpath, options, &optional_filter_block)
|
|
243
202
|
end
|
|
244
203
|
|
|
245
204
|
def have_css(css, options={}, &optional_filter_block)
|
|
246
205
|
HaveSelector.new(:css, css, options, &optional_filter_block)
|
|
247
206
|
end
|
|
248
207
|
|
|
249
|
-
def match_css(css, options={})
|
|
250
|
-
MatchSelector.new(:css, css, options)
|
|
208
|
+
def match_css(css, options={}, &optional_filter_block)
|
|
209
|
+
MatchSelector.new(:css, css, options, &optional_filter_block)
|
|
251
210
|
end
|
|
252
211
|
|
|
253
212
|
def have_text(*args)
|
|
@@ -307,6 +266,5 @@ module Capybara
|
|
|
307
266
|
def become_closed(options = {})
|
|
308
267
|
BecomeClosed.new(options)
|
|
309
268
|
end
|
|
310
|
-
|
|
311
269
|
end
|
|
312
270
|
end
|
|
@@ -6,6 +6,7 @@ require 'xpath'
|
|
|
6
6
|
#Patch XPath to allow a nil condition in where
|
|
7
7
|
module XPath
|
|
8
8
|
class Renderer
|
|
9
|
+
undef :where if method_defined?(:where)
|
|
9
10
|
def where(on, condition)
|
|
10
11
|
condition = condition.to_s
|
|
11
12
|
if !condition.empty?
|
|
@@ -177,14 +178,14 @@ module Capybara
|
|
|
177
178
|
|
|
178
179
|
def filter_set(name, filters_to_use = nil)
|
|
179
180
|
f_set = FilterSet.all[name]
|
|
180
|
-
f_set.filters.each do |
|
|
181
|
-
custom_filters[
|
|
181
|
+
f_set.filters.each do |n, filter|
|
|
182
|
+
custom_filters[n] = filter if filters_to_use.nil? || filters_to_use.include?(n)
|
|
182
183
|
end
|
|
183
|
-
f_set.descriptions.each { |desc| @filter_set.describe
|
|
184
|
+
f_set.descriptions.each { |desc| @filter_set.describe(&desc) }
|
|
184
185
|
end
|
|
185
186
|
|
|
186
187
|
def describe &block
|
|
187
|
-
@filter_set.describe
|
|
188
|
+
@filter_set.describe(&block)
|
|
188
189
|
end
|
|
189
190
|
|
|
190
191
|
##
|
|
@@ -228,8 +229,12 @@ module Capybara
|
|
|
228
229
|
locate_xpath
|
|
229
230
|
end
|
|
230
231
|
|
|
232
|
+
def describe_all_expression_filters(opts={})
|
|
233
|
+
expression_filters.map { |ef| " with #{ef} #{opts[ef]}" if opts.has_key?(ef) }.join
|
|
234
|
+
end
|
|
235
|
+
|
|
231
236
|
def find_by_attr(attribute, value)
|
|
232
|
-
finder_name = "find_by_#{attribute
|
|
237
|
+
finder_name = "find_by_#{attribute}_attr"
|
|
233
238
|
if respond_to?(finder_name, true)
|
|
234
239
|
send(finder_name, value)
|
|
235
240
|
else
|
data/lib/capybara/selector.rb
CHANGED
|
@@ -87,7 +87,7 @@ Capybara.add_selector(:field) do
|
|
|
87
87
|
end
|
|
88
88
|
describe do |options|
|
|
89
89
|
desc = String.new
|
|
90
|
-
(expression_filters - [:type]).each { |ef| desc << " with #{ef
|
|
90
|
+
(expression_filters - [:type]).each { |ef| desc << " with #{ef} #{options[ef]}" if options.has_key?(ef) }
|
|
91
91
|
desc << " of type #{options[:type].inspect}" if options[:type]
|
|
92
92
|
desc << " with value #{options[:with].to_s.inspect}" if options.has_key?(:with)
|
|
93
93
|
desc
|
|
@@ -196,7 +196,7 @@ Capybara.add_selector(:button) do
|
|
|
196
196
|
describe do |options|
|
|
197
197
|
desc = String.new
|
|
198
198
|
desc << " that is disabled" if options[:disabled] == true
|
|
199
|
-
|
|
199
|
+
desc << describe_all_expression_filters(options)
|
|
200
200
|
desc
|
|
201
201
|
end
|
|
202
202
|
end
|
|
@@ -244,7 +244,7 @@ Capybara.add_selector(:fillable_field) do
|
|
|
244
244
|
|
|
245
245
|
describe do |options|
|
|
246
246
|
desc = String.new
|
|
247
|
-
|
|
247
|
+
desc << describe_all_expression_filters(options)
|
|
248
248
|
desc << " with value #{options[:with].to_s.inspect}" if options.has_key?(:with)
|
|
249
249
|
desc
|
|
250
250
|
end
|
|
@@ -277,7 +277,7 @@ Capybara.add_selector(:radio_button) do
|
|
|
277
277
|
describe do |options|
|
|
278
278
|
desc = String.new
|
|
279
279
|
desc << " with value #{options[:option].inspect}" if options[:option]
|
|
280
|
-
|
|
280
|
+
desc << describe_all_expression_filters(options)
|
|
281
281
|
desc
|
|
282
282
|
end
|
|
283
283
|
end
|
|
@@ -308,7 +308,7 @@ Capybara.add_selector(:checkbox) do
|
|
|
308
308
|
describe do |options|
|
|
309
309
|
desc = String.new
|
|
310
310
|
desc << " with value #{options[:option].inspect}" if options[:option]
|
|
311
|
-
|
|
311
|
+
desc << describe_all_expression_filters(options)
|
|
312
312
|
desc
|
|
313
313
|
end
|
|
314
314
|
end
|
|
@@ -364,7 +364,7 @@ Capybara.add_selector(:select) do
|
|
|
364
364
|
desc << " with options #{options[:options].inspect}" if options[:options]
|
|
365
365
|
desc << " with at least options #{options[:with_options].inspect}" if options[:with_options]
|
|
366
366
|
desc << " with #{options[:selected].inspect} selected" if options[:selected]
|
|
367
|
-
|
|
367
|
+
desc << describe_all_expression_filters(options)
|
|
368
368
|
desc
|
|
369
369
|
end
|
|
370
370
|
end
|
|
@@ -417,7 +417,7 @@ Capybara.add_selector(:file_field) do
|
|
|
417
417
|
|
|
418
418
|
describe do |options|
|
|
419
419
|
desc = String.new
|
|
420
|
-
|
|
420
|
+
desc << describe_all_expression_filters(options)
|
|
421
421
|
desc
|
|
422
422
|
end
|
|
423
423
|
end
|
|
@@ -4,9 +4,11 @@ require "uri"
|
|
|
4
4
|
class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
5
5
|
|
|
6
6
|
DEFAULT_OPTIONS = {
|
|
7
|
-
:browser => :firefox
|
|
7
|
+
:browser => :firefox,
|
|
8
|
+
clear_local_storage: false,
|
|
9
|
+
clear_session_storage: false
|
|
8
10
|
}
|
|
9
|
-
SPECIAL_OPTIONS = [:browser]
|
|
11
|
+
SPECIAL_OPTIONS = [:browser, :clear_local_storage, :clear_session_storage]
|
|
10
12
|
|
|
11
13
|
attr_reader :app, :options
|
|
12
14
|
|
|
@@ -17,7 +19,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
|
17
19
|
options[:desired_capabilities].merge!({ unexpectedAlertBehaviour: "ignore" })
|
|
18
20
|
end
|
|
19
21
|
|
|
20
|
-
@browser = Selenium::WebDriver.for(options[:browser], options.reject { |key,
|
|
22
|
+
@browser = Selenium::WebDriver.for(options[:browser], options.reject { |key,_val| SPECIAL_OPTIONS.include?(key) })
|
|
21
23
|
|
|
22
24
|
main = Process.pid
|
|
23
25
|
at_exit do
|
|
@@ -92,7 +94,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
|
92
94
|
browser.execute_script "return #{script}"
|
|
93
95
|
end
|
|
94
96
|
|
|
95
|
-
def save_screenshot(path,
|
|
97
|
+
def save_screenshot(path, _options={})
|
|
96
98
|
browser.save_screenshot(path)
|
|
97
99
|
end
|
|
98
100
|
|
|
@@ -107,6 +109,20 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
|
107
109
|
# can trigger an endless series of unload modals
|
|
108
110
|
begin
|
|
109
111
|
@browser.manage.delete_all_cookies
|
|
112
|
+
if options[:clear_session_storage]
|
|
113
|
+
if @browser.respond_to? :session_storage
|
|
114
|
+
@browser.session_storage.clear
|
|
115
|
+
else
|
|
116
|
+
warn "sessionStorage clear requested but is not available for this driver"
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
if options[:clear_local_storage]
|
|
120
|
+
if @browser.respond_to? :local_storage
|
|
121
|
+
@browser.local_storage.clear
|
|
122
|
+
else
|
|
123
|
+
warn "localStorage clear requested but is not available for this driver"
|
|
124
|
+
end
|
|
125
|
+
end
|
|
110
126
|
rescue Selenium::WebDriver::Error::UnhandledError
|
|
111
127
|
# delete_all_cookies fails when we've previously gone
|
|
112
128
|
# to about:blank, so we rescue this error and do nothing
|
|
@@ -220,8 +236,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
|
220
236
|
browser.switch_to.window(handle) { yield }
|
|
221
237
|
end
|
|
222
238
|
|
|
223
|
-
def accept_modal(
|
|
224
|
-
options = options.dup
|
|
239
|
+
def accept_modal(_type, options={})
|
|
225
240
|
yield if block_given?
|
|
226
241
|
modal = find_modal(options)
|
|
227
242
|
modal.send_keys options[:with] if options[:with]
|
|
@@ -230,7 +245,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
|
230
245
|
message
|
|
231
246
|
end
|
|
232
247
|
|
|
233
|
-
def dismiss_modal(
|
|
248
|
+
def dismiss_modal(_type, options={})
|
|
234
249
|
yield if block_given?
|
|
235
250
|
modal = find_modal(options)
|
|
236
251
|
message = modal.text
|
|
@@ -242,6 +257,11 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
|
242
257
|
@browser.quit if @browser
|
|
243
258
|
rescue Errno::ECONNREFUSED
|
|
244
259
|
# Browser must have already gone
|
|
260
|
+
rescue Selenium::WebDriver::Error::UnknownError => e
|
|
261
|
+
unless silenced_unknown_error_message?(e.message) # Most likely already gone
|
|
262
|
+
# probably already gone but not sure - so warn
|
|
263
|
+
warn "Ignoring Selenium UnknownError during driver quit: #{e.message}"
|
|
264
|
+
end
|
|
245
265
|
ensure
|
|
246
266
|
@browser = nil
|
|
247
267
|
end
|
|
@@ -293,4 +313,11 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
|
293
313
|
end
|
|
294
314
|
end
|
|
295
315
|
|
|
316
|
+
def silenced_unknown_error_message?(msg)
|
|
317
|
+
silenced_unknown_error_messages.any? { |r| msg =~ r }
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
def silenced_unknown_error_messages
|
|
321
|
+
[ /Error communicating with the remote browser/ ]
|
|
322
|
+
end
|
|
296
323
|
end
|
|
@@ -47,7 +47,11 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
|
|
47
47
|
click if value ^ native.attribute('checked').to_s.eql?("true")
|
|
48
48
|
elsif tag_name == 'input' and type == 'file'
|
|
49
49
|
path_names = value.to_s.empty? ? [] : value
|
|
50
|
-
|
|
50
|
+
if driver.options[:browser].to_s == "chrome"
|
|
51
|
+
native.send_keys(Array(path_names).join("\n"))
|
|
52
|
+
else
|
|
53
|
+
native.send_keys(*path_names)
|
|
54
|
+
end
|
|
51
55
|
elsif tag_name == 'textarea' or tag_name == 'input'
|
|
52
56
|
if readonly?
|
|
53
57
|
warn "Attempt to set readonly element with value: #{value} \n *This will raise an exception in a future version of Capybara"
|