capybara 3.4.0 → 3.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 354c57c570fb124607ab4255934f26bdb55b81716b846a2d76bb938ecae5d0c0
4
- data.tar.gz: 128b9ee025bcd0021bc7e966a57d96fc05b516bd8dcb29756f3206f8aef15d4f
3
+ metadata.gz: ccbb47ddccdce3cfd6a790bd2af929bf21f0dff5a9c284c1798fced5de3deef0
4
+ data.tar.gz: abcbaadffc9b324fcb05601b14a923a051471de760c6a290acd4c020f7f53428
5
5
  SHA512:
6
- metadata.gz: c55429aed39e48dbe84375f0822e2f0f244e4572474a797a27e8f83bdf0fa3c8062ca91d6696aba1b54c228908385351c483598a9f44718529d7ad4139b0717c
7
- data.tar.gz: 8c61a46eb89183e28c4e0e7be76118ccecceb3383a6c7c37b2f9d7d0aa5efe5971146a97374146df09881a2fe0da94f58a89822cdb9e6d53b95f502782eb9106
6
+ metadata.gz: dee7228b9108ed669bf8796cfe024a49594b8820f5b0899118d49a90ecd8616453ec42b5467b0a833156ae0f10ff57df3e627f2b2e164ad4edc68fcef7cc0e6e
7
+ data.tar.gz: 7de8b0aa5ab6b9565b17732a61e6e693b431806c33cb2d64098f3f2d6d0440383af96f2930cff0197b11e92059e48878210a4254309320eeaf73f0cf470b256f
data/History.md CHANGED
@@ -1,3 +1,28 @@
1
+ # Version 3.5.0
2
+ Release date: 2018-08-01
3
+
4
+ ### Added
5
+
6
+ * text predicates and matchers (`has_text?`, `has_content?`, `assert_text`, etc) now support a `normalize_ws` option
7
+
8
+ ### Fixed
9
+
10
+ * `attach_file` with Selenium and local Firefox 62+ now correctly generates only one change event when attaching multiple files
11
+
12
+ # Version 3.4.2
13
+ Release date: 2018-07-24
14
+
15
+ ### Fixed
16
+
17
+ * `match_xxx` selectors and `matches_xxx?` predicates work correctly with elements found using a sibling selector - Issue #2073
18
+
19
+ # Version 3.4.1
20
+ Release date: 2018-07-20
21
+
22
+ ### Fixed
23
+
24
+ * `Session#evaluate_script` now strips the script in `Session` rather than only in the Selenium driver
25
+
1
26
  # Version 3.4.0
2
27
  Release date: 2018-07-19
3
28
 
data/README.md CHANGED
@@ -76,7 +76,7 @@ GitHub): http://groups.google.com/group/ruby-capybara
76
76
 
77
77
  ## <a name="setup"></a>Setup
78
78
 
79
- Capybara requires Ruby 2.2.2 or later. To install, add this line to your
79
+ Capybara requires Ruby 2.3.0 or later. To install, add this line to your
80
80
  `Gemfile` and run `bundle install`:
81
81
 
82
82
  ```ruby
@@ -344,7 +344,9 @@ module Capybara
344
344
  ##
345
345
  #
346
346
  # Trigger any event on the current element, for example mouseover or focus
347
- # events. Does not work in Selenium.
347
+ # events. Not supported with the Selenium driver, and SHOULDN'T BE USED IN TESTING unless you
348
+ # fully understand why you're using it, that it can allow actions a user could never
349
+ # perform, and that it may completely invalidate your test.
348
350
  #
349
351
  # @param [String] event The name of the event to trigger
350
352
  #
@@ -203,7 +203,6 @@ module Capybara
203
203
  end
204
204
  end
205
205
  end
206
- alias_method :refute_selector, :assert_no_selector
207
206
 
208
207
  ##
209
208
  #
@@ -529,7 +528,24 @@ module Capybara
529
528
  raise Capybara::ExpectationNotMet, 'Item matched the provided selector' if result.include? self
530
529
  end
531
530
  end
532
- alias_method :refute_matches_selector, :assert_not_matches_selector
531
+
532
+ # Deprecated
533
+ # TODO: remove
534
+ def refute_selector(*args, &optional_filter_block)
535
+ warn '`refute_selector` was never meant to be in this scope unless ' \
536
+ 'using minitest. Either replace with `assert_no_selector` ' \
537
+ "or require 'capybara/minitest'."
538
+ assert_no_selector(*args, &optional_filter_block)
539
+ end
540
+
541
+ # Deprecated
542
+ # TODO: remove
543
+ def refute_matches_elector(*args, &optional_filter_block)
544
+ warn '`refute_matches_selector` was never meant to be in this scope unless ' \
545
+ 'using minitest. Either replace with `assert_not_matches_selector` ' \
546
+ "or require 'capybara/minitest'."
547
+ assert_not_matches_selector(*args, &optional_filter_block)
548
+ end
533
549
 
534
550
  ##
535
551
  #
@@ -616,6 +632,7 @@ module Capybara
616
632
  # @option options [Range] :between (nil) Range of times that is expected to contain number of times text occurs
617
633
  # @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum time that Capybara will wait for text to eq/match given string/regexp argument
618
634
  # @option options [Boolean] :exact (Capybara.exact_text) Whether text must be an exact match or just substring
635
+ # @option options [Boolean] :nomalize_ws (false) When true replace all whitespace with standard spaces and collapse consecutive whitespace to a single space
619
636
  # @overload $0(text, **options)
620
637
  # @param [String, Regexp] text The string/regexp to check for. If it's a string, text is expected to include it. If it's a regexp, text is expected to match it.
621
638
  # @option options [Integer] :count (nil) Number of times the text is expected to occur
@@ -624,6 +641,7 @@ module Capybara
624
641
  # @option options [Range] :between (nil) Range of times that is expected to contain number of times text occurs
625
642
  # @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum time that Capybara will wait for text to eq/match given string/regexp argument
626
643
  # @option options [Boolean] :exact (Capybara.exact_text) Whether text must be an exact match or just substring
644
+ # @option options [Boolean] :normalize_ws (false) When true replace all whitespace with standard spaces and collapse consecutive whitespace to a single space
627
645
  # @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
628
646
  # @return [true]
629
647
  #
@@ -709,7 +727,7 @@ module Capybara
709
727
  query_args = _set_query_session_options(*query_args)
710
728
  query = Capybara::Queries::MatchQuery.new(*query_args, &optional_filter_block)
711
729
  synchronize(query.wait) do
712
- yield query.resolve_for(query_scope)
730
+ yield query.resolve_for(first(:xpath, './parent::*', minimum: 0) || query_scope)
713
731
  end
714
732
  true
715
733
  end
@@ -24,6 +24,7 @@ module Capybara
24
24
  def resolve_for(node)
25
25
  @node = node
26
26
  @actual_text = text(node, @type)
27
+ @actual_text.gsub!(/[[:space:]]+/, ' ').strip! if options[:normalize_ws]
27
28
  @count = @actual_text.scan(@search_regexp).size
28
29
  end
29
30
 
@@ -83,7 +84,7 @@ module Capybara
83
84
  end
84
85
 
85
86
  def valid_keys
86
- COUNT_KEYS + %i[wait exact]
87
+ COUNT_KEYS + %i[wait exact normalize_ws]
87
88
  end
88
89
 
89
90
  def check_visible_text?
@@ -9,6 +9,11 @@ module Capybara
9
9
 
10
10
  attr_reader :failure_message, :failure_message_when_negated
11
11
 
12
+ def initialize(*args, &filter_block)
13
+ @args = args.dup
14
+ @filter_block = filter_block
15
+ end
16
+
12
17
  def wrap(actual)
13
18
  actual = actual.to_capybara_node if actual.respond_to?(:to_capybara_node)
14
19
  @context_el = if actual.respond_to?(:has_selector?)
@@ -56,11 +61,6 @@ module Capybara
56
61
  end
57
62
 
58
63
  class HaveSelector < Matcher
59
- def initialize(*args, &filter_block)
60
- @args = args
61
- @filter_block = filter_block
62
- end
63
-
64
64
  def matches?(actual)
65
65
  wrap_matches?(actual) { |el| el.assert_selector(*@args, &@filter_block) }
66
66
  end
@@ -79,11 +79,6 @@ module Capybara
79
79
  end
80
80
 
81
81
  class HaveAllSelectors < Matcher
82
- def initialize(*args, &filter_block)
83
- @args = args
84
- @filter_block = filter_block
85
- end
86
-
87
82
  def matches?(actual)
88
83
  wrap_matches?(actual) { |el| el.assert_all_of_selectors(*@args, &@filter_block) }
89
84
  end
@@ -98,11 +93,6 @@ module Capybara
98
93
  end
99
94
 
100
95
  class HaveNoSelectors < Matcher
101
- def initialize(*args, &filter_block)
102
- @args = args
103
- @filter_block = filter_block
104
- end
105
-
106
96
  def matches?(actual)
107
97
  wrap_matches?(actual) { |el| el.assert_none_of_selectors(*@args, &@filter_block) }
108
98
  end
@@ -135,11 +125,6 @@ module Capybara
135
125
  end
136
126
 
137
127
  class HaveText < Matcher
138
- def initialize(*args)
139
- @args = args.dup
140
- @content = args[0].is_a?(Symbol) ? args[1] : args[0]
141
- end
142
-
143
128
  def matches?(actual)
144
129
  wrap_matches?(actual) { |el| el.assert_text(*@args) }
145
130
  end
@@ -149,22 +134,21 @@ module Capybara
149
134
  end
150
135
 
151
136
  def description
152
- "text #{format(@content)}"
137
+ "text #{format(text)}"
153
138
  end
154
139
 
155
140
  def format(content)
156
141
  content.inspect
157
142
  end
158
- end
159
143
 
160
- class HaveTitle < Matcher
161
- def initialize(*args)
162
- @args = args
144
+ private
163
145
 
164
- # are set just for backwards compatability
165
- @title = args.first
146
+ def text
147
+ @args[0].is_a?(Symbol) ? @args[1] : @args[0]
166
148
  end
149
+ end
167
150
 
151
+ class HaveTitle < Matcher
168
152
  def matches?(actual)
169
153
  wrap_matches?(actual) { |el| el.assert_title(*@args) }
170
154
  end
@@ -174,16 +158,17 @@ module Capybara
174
158
  end
175
159
 
176
160
  def description
177
- "have title #{@title.inspect}"
161
+ "have title #{title.inspect}"
178
162
  end
179
- end
180
163
 
181
- class HaveCurrentPath < Matcher
182
- def initialize(*args)
183
- @args = args
184
- @current_path = args.first
164
+ private
165
+
166
+ def title
167
+ @args.first
185
168
  end
169
+ end
186
170
 
171
+ class HaveCurrentPath < Matcher
187
172
  def matches?(actual)
188
173
  wrap_matches?(actual) { |el| el.assert_current_path(*@args) }
189
174
  end
@@ -193,7 +178,13 @@ module Capybara
193
178
  end
194
179
 
195
180
  def description
196
- "have current path #{@current_path.inspect}"
181
+ "have current path #{current_path.inspect}"
182
+ end
183
+
184
+ private
185
+
186
+ def current_path
187
+ @args.first
197
188
  end
198
189
  end
199
190
 
@@ -201,6 +192,7 @@ module Capybara
201
192
  include ::Capybara::RSpecMatchers::Compound if defined?(::Capybara::RSpecMatchers::Compound)
202
193
 
203
194
  def initialize(matcher)
195
+ super()
204
196
  @matcher = matcher
205
197
  end
206
198
 
@@ -226,10 +218,6 @@ module Capybara
226
218
  end
227
219
 
228
220
  class HaveStyle < Matcher
229
- def initialize(*args)
230
- @args = args
231
- end
232
-
233
221
  def matches?(actual)
234
222
  wrap_matches?(actual) { |el| el.assert_style(*@args) }
235
223
  end
@@ -99,7 +99,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
99
99
  end
100
100
 
101
101
  def evaluate_script(script, *args)
102
- result = execute_script("return #{script.strip}", *args)
102
+ result = execute_script("return #{script}", *args)
103
103
  unwrap_script_result(result)
104
104
  end
105
105
 
@@ -312,7 +312,7 @@ private
312
312
  end
313
313
 
314
314
  def ie?
315
- browser_name == :ie
315
+ %i[internet_explorer ie].include?(browser_name)
316
316
  end
317
317
 
318
318
  def browser_name
@@ -176,7 +176,14 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
176
176
 
177
177
  if parent
178
178
  siblings = parent.find_xpath(selector)
179
- selector += "[#{siblings.index(node) + 1}]" unless siblings.size == 1
179
+ selector += case siblings.size
180
+ when 0
181
+ '[ERROR]' # IE doesn't support full XPath (namespace-uri, etc)
182
+ when 1
183
+ '' # index not necessary when only one matching element
184
+ else
185
+ "[#{siblings.index(node) + 1}]"
186
+ end
180
187
  end
181
188
  result.push selector
182
189
  end
@@ -5,7 +5,7 @@ class Capybara::Selenium::ChromeNode < Capybara::Selenium::Node
5
5
  super(value)
6
6
  rescue ::Selenium::WebDriver::Error::ExpectedError => e
7
7
  if e.message =~ /File not found : .+\n.+/m
8
- raise ArgumentError, "Selenium with remote Chrome doesn't currently support multiple file upload"
8
+ raise ArgumentError, "Selenium < 3.14 with remote Chrome doesn't support multiple file upload"
9
9
  end
10
10
  raise
11
11
  end
@@ -26,8 +26,11 @@ class Capybara::Selenium::MarionetteNode < Capybara::Selenium::Node
26
26
  end
27
27
 
28
28
  def set_file(value) # rubocop:disable Naming/AccessorMethodName
29
+ native.clear # By default files are appended so we have to clear here
30
+ return super if driver.browser.capabilities[:browser_version].to_f >= 62.0
31
+
32
+ # Workaround lack of support for multiple upload by uploading one at a time
29
33
  path_names = value.to_s.empty? ? [] : value
30
- native.clear
31
34
  Array(path_names).each do |path|
32
35
  unless driver.browser.respond_to?(:upload)
33
36
  if (fd = bridge.file_detector)
@@ -47,7 +50,7 @@ private
47
50
 
48
51
  def upload(local_file)
49
52
  unless File.file?(local_file)
50
- raise Error::WebDriverError, "you may only upload files: #{local_file.inspect}"
53
+ raise ArgumentError, "You may only upload files: #{local_file.inspect}"
51
54
  end
52
55
 
53
56
  result = bridge.http.call(:post, "session/#{bridge.session_id}/file", file: Selenium::WebDriver::Zipper.zip_file(local_file))
@@ -580,7 +580,7 @@ module Capybara
580
580
  #
581
581
  def evaluate_script(script, *args)
582
582
  @touched = true
583
- result = driver.evaluate_script(script, *driver_args(args))
583
+ result = driver.evaluate_script(script.strip, *driver_args(args))
584
584
  element_script_result(result)
585
585
  end
586
586