capybara 3.26.0 → 3.27.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +18 -0
  3. data/README.md +1 -2
  4. data/lib/capybara/minitest.rb +29 -29
  5. data/lib/capybara/node/element.rb +2 -1
  6. data/lib/capybara/node/matchers.rb +6 -6
  7. data/lib/capybara/node/simple.rb +2 -1
  8. data/lib/capybara/queries/ancestor_query.rb +5 -9
  9. data/lib/capybara/queries/selector_query.rb +2 -2
  10. data/lib/capybara/queries/sibling_query.rb +4 -10
  11. data/lib/capybara/registrations/servers.rb +4 -1
  12. data/lib/capybara/selector/regexp_disassembler.rb +7 -0
  13. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -1
  14. data/lib/capybara/selenium/atoms/src/isDisplayed.js +9 -9
  15. data/lib/capybara/selenium/driver.rb +2 -1
  16. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +9 -4
  17. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +8 -6
  18. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +9 -0
  19. data/lib/capybara/selenium/nodes/chrome_node.rb +41 -5
  20. data/lib/capybara/selenium/nodes/firefox_node.rb +16 -0
  21. data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
  22. data/lib/capybara/spec/session/node_spec.rb +40 -3
  23. data/lib/capybara/spec/views/with_html.erb +10 -0
  24. data/lib/capybara/version.rb +1 -1
  25. data/spec/basic_node_spec.rb +6 -6
  26. data/spec/capybara_spec.rb +28 -28
  27. data/spec/filter_set_spec.rb +5 -5
  28. data/spec/fixtures/selenium_driver_rspec_failure.rb +1 -1
  29. data/spec/fixtures/selenium_driver_rspec_success.rb +1 -1
  30. data/spec/rack_test_spec.rb +9 -9
  31. data/spec/regexp_dissassembler_spec.rb +12 -2
  32. data/spec/rspec/shared_spec_matchers.rb +2 -2
  33. data/spec/rspec_spec.rb +1 -1
  34. data/spec/selector_spec.rb +15 -15
  35. data/spec/selenium_spec_chrome.rb +38 -0
  36. data/spec/selenium_spec_firefox.rb +1 -1
  37. data/spec/server_spec.rb +18 -18
  38. data/spec/session_spec.rb +4 -4
  39. data/spec/shared_selenium_node.rb +36 -0
  40. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 799d14b5b1f64c06a58d962e7187f439332772f95d9d946d7452cf04d1710669
4
- data.tar.gz: 79d2dc83febaaae726776d509c01e591558a7a174c2e8b58733082981610c57c
3
+ metadata.gz: d2fb2005b8e78a2ee5cd0cf72bdfe2143988cce46abf19422f00bc78ac6336fa
4
+ data.tar.gz: 17f7b3eba5799d74ba90bddd6bacec90f1318e3c731097a4cb362f211272652b
5
5
  SHA512:
6
- metadata.gz: ccb7b53977549aaa7597577b74a5bde4ebcaee1fa9137b7aad1c7317f73b980cfb27552921386af12601febffc2326c481915d96ac6c56f87f594a9c726ea855
7
- data.tar.gz: 87c6490f0f8132750d30391aadb007ae9376d03d093c12f783ed32a3a373b33541c0ef66f7b0f7c8c069b982203542e92b33e294a80611b52dbc79e7d20021dc
6
+ metadata.gz: 28e92147279b5b2ee953853fd93071e143719ec099fb68187ea4fa666fbe3593606876968861c9104967e7b7bbd2033b2105ce9720bb00b4de94cd98c8473553
7
+ data.tar.gz: 25aee95fc26cc88c27e5229f73665a1cf6b2a8658ece2b8503809a520a45afe5622b28825206cff599ad7a2e749dbc168941dcc298995bc43fd61545b6a306a1
data/History.md CHANGED
@@ -1,3 +1,21 @@
1
+ # Version 3.27.0
2
+ Release date: 2019-07-28
3
+
4
+ ### Added
5
+
6
+ * Allow to use chromedriver/geckodriver native `is_element_displayed` endpoint via Selenium
7
+ driver `native_displayed` option for performance reasons. Disabled by default due to endpoints
8
+ currently not handling <details> element descendants visibility correctly.
9
+
10
+ ### Fixed
11
+
12
+ * Ignore negative lookahead/lookbehind regex when performing initial XPath text matching
13
+ * Reloading of elements found via `ancestor` and `sibling`
14
+ * Only default puma settings to `queue_requests: false` when using SSL
15
+ * Visibility of descendants of <details> elements is correctly determined when using rack_test
16
+ and the selenium driver with Capybara optimized atoms
17
+ * local/session storage clearance in Chrome when clearing only one of them - Issue #2233
18
+
1
19
  # Version 3.26.0
2
20
  Release date: 2019-07-15
3
21
 
data/README.md CHANGED
@@ -7,8 +7,7 @@
7
7
  [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/jnicklas/capybara?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
8
8
  [![SemVer](https://api.dependabot.com/badges/compatibility_score?dependency-name=capybara&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=capybara&package-manager=bundler&version-scheme=semver)
9
9
 
10
- **Note** You are viewing the README for the 3.26.x version of Capybara.
11
-
10
+ **Note** You are viewing the README for the 3.27.x version of Capybara
12
11
 
13
12
  Capybara helps you test web applications by simulating how a real user would
14
13
  interact with your app. It is agnostic about the driver running your tests and
@@ -9,38 +9,38 @@ module Capybara
9
9
  ## Assert text exists
10
10
  #
11
11
  # @!method assert_text
12
- # see {Capybara::Node::Matchers#assert_text}
12
+ # @see Capybara::Node::Matchers#assert_text
13
13
 
14
14
  ## Assert text does not exist
15
15
  #
16
16
  # @!method assert_no_text
17
- # see {Capybara::Node::Matchers#assert_no_text}
17
+ # @see Capybara::Node::Matchers#assert_no_text
18
18
 
19
19
  ##
20
20
  # Assertion that page title does match
21
21
  #
22
22
  # @!method assert_title
23
- # see {Capybara::Node::DocumentMatchers#assert_title}
23
+ # @see Capybara::Node::DocumentMatchers#assert_title
24
24
 
25
25
  ##
26
26
  # Assertion that page title does not match
27
27
  #
28
28
  # @!method refute_title
29
29
  # @!method assert_no_title
30
- # see {Capybara::Node::DocumentMatchers#assert_no_title}
30
+ # @see Capybara::Node::DocumentMatchers#assert_no_title
31
31
 
32
32
  ##
33
33
  # Assertion that current path matches
34
34
  #
35
35
  # @!method assert_current_path
36
- # see {Capybara::SessionMatchers#assert_current_path}
36
+ # @see Capybara::SessionMatchers#assert_current_path
37
37
 
38
38
  ##
39
39
  # Assertion that current page does not match
40
40
  #
41
41
  # @!method refute_current_path
42
42
  # @!method assert_no_current_path
43
- # see {Capybara::SessionMatchers#assert_no_current_path}
43
+ # @see Capybara::SessionMatchers#assert_no_current_path
44
44
 
45
45
  %w[text no_text title no_title current_path no_current_path].each do |assertion_name|
46
46
  class_eval <<-ASSERTION, __FILE__, __LINE__ + 1
@@ -64,37 +64,37 @@ module Capybara
64
64
  ## Assert selector exists on page
65
65
  #
66
66
  # @!method assert_selector
67
- # see {Capybara::Node::Matchers#assert_selector}
67
+ # @see Capybara::Node::Matchers#assert_selector
68
68
 
69
69
  ## Assert selector does not exist on page
70
70
  #
71
71
  # @!method assert_no_selector
72
- # see {Capybara::Node::Matchers#assert_no_selector}
72
+ # @see Capybara::Node::Matchers#assert_no_selector
73
73
 
74
74
  ## Assert element matches selector
75
75
  #
76
76
  # @!method assert_matches_selector
77
- # see {Capybara::Node::Matchers#assert_matches_selector}
77
+ # @see Capybara::Node::Matchers#assert_matches_selector
78
78
 
79
79
  ## Assert element does not match selector
80
80
  #
81
81
  # @!method assert_xpath
82
- # see {Capybara::Node::Matchers#assert_not_matches_selector}
82
+ # @see Capybara::Node::Matchers#assert_not_matches_selector
83
83
 
84
84
  ## Assert element has the provided CSS styles
85
85
  #
86
86
  # @!method assert_matches_style
87
- # see {Capybara::Node::Matchers#assert_matches_style}
87
+ # @see Capybara::Node::Matchers#assert_matches_style
88
88
 
89
89
  ## Assert element has a matching sibling
90
90
  #
91
91
  # @!method assert_sibling
92
- # see {Capybara::Node::Matchers#assert_sibling}
92
+ # @see Capybara::Node::Matchers#assert_sibling
93
93
 
94
94
  ## Assert element has a matching ancestor
95
95
  #
96
96
  # @!method assert_ancestor
97
- # see {Capybara::Node::Matchers#assert_ancestor}
97
+ # @see Capybara::Node::Matchers#assert_ancestor
98
98
 
99
99
  %w[selector no_selector matches_style
100
100
  all_of_selectors none_of_selectors any_of_selectors
@@ -163,72 +163,72 @@ module Capybara
163
163
  # Assertion that there is xpath
164
164
  #
165
165
  # @!method assert_xpath
166
- # see {Capybara::Node::Matchers#has_xpath?}
166
+ # @see Capybara::Node::Matchers#has_xpath?
167
167
 
168
168
  ##
169
169
  # Assertion that there is no xpath
170
170
  #
171
171
  # @!method refute_xpath
172
172
  # @!method assert_no_xpath
173
- # see {Capybara::Node::Matchers#has_no_xpath?}
173
+ # @see Capybara::Node::Matchers#has_no_xpath?
174
174
 
175
175
  ##
176
176
  # Assertion that there is css
177
177
  #
178
178
  # @!method assert_css
179
- # see {Capybara::Node::Matchers#has_css?}
179
+ # @see Capybara::Node::Matchers#has_css?
180
180
 
181
181
  ##
182
182
  # Assertion that there is no css
183
183
  #
184
184
  # @!method refute_css
185
185
  # @!method assert_no_css
186
- # see {Capybara::Node::Matchers#has_no_css?}
186
+ # @see Capybara::Node::Matchers#has_no_css?
187
187
 
188
188
  ##
189
189
  # Assertion that there is link
190
190
  #
191
191
  # @!method assert_link
192
- # see {Capybara::Node::Matchers#has_link?}
192
+ # @see Capybara::Node::Matchers#has_link?
193
193
 
194
194
  ##
195
195
  # Assertion that there is no link
196
196
  #
197
197
  # @!method assert_no_link
198
198
  # @!method refute_link
199
- # see {Capybara::Node::Matchers#has_no_link?}
199
+ # @see Capybara::Node::Matchers#has_no_link?
200
200
 
201
201
  ##
202
202
  # Assertion that there is button
203
203
  #
204
204
  # @!method assert_button
205
- # see {Capybara::Node::Matchers#has_button?}
205
+ # @see Capybara::Node::Matchers#has_button?
206
206
 
207
207
  ##
208
208
  # Assertion that there is no button
209
209
  #
210
210
  # @!method refute_button
211
211
  # @!method assert_no_button
212
- # see {Capybara::Node::Matchers#has_no_button?}
212
+ # @see Capybara::Node::Matchers#has_no_button?
213
213
 
214
214
  ##
215
215
  # Assertion that there is field
216
216
  #
217
217
  # @!method assert_field
218
- # see {Capybara::Node::Matchers#has_field?}
218
+ # @see Capybara::Node::Matchers#has_field?
219
219
 
220
220
  ##
221
221
  # Assertion that there is no field
222
222
  #
223
223
  # @!method refute_field
224
224
  # @!method assert_no_field
225
- # see {Capybara::Node::Matchers#has_no_field?}
225
+ # @see Capybara::Node::Matchers#has_no_field?
226
226
 
227
227
  ##
228
228
  # Assertion that there is checked_field
229
229
  #
230
230
  # @!method assert_checked_field
231
- # see {Capybara::Node::Matchers#has_checked_field?}
231
+ # @see Capybara::Node::Matchers#has_checked_field?
232
232
 
233
233
  ##
234
234
  # Assertion that there is no checked_field
@@ -240,7 +240,7 @@ module Capybara
240
240
  # Assertion that there is unchecked_field
241
241
  #
242
242
  # @!method assert_unchecked_field
243
- # see {Capybara::Node::Matchers#has_unchecked_field?}
243
+ # @see Capybara::Node::Matchers#has_unchecked_field?
244
244
 
245
245
  ##
246
246
  # Assertion that there is no unchecked_field
@@ -252,27 +252,27 @@ module Capybara
252
252
  # Assertion that there is select
253
253
  #
254
254
  # @!method assert_select
255
- # see {Capybara::Node::Matchers#has_select?}
255
+ # @see Capybara::Node::Matchers#has_select?
256
256
 
257
257
  ##
258
258
  # Assertion that there is no select
259
259
  #
260
260
  # @!method refute_select
261
261
  # @!method assert_no_select
262
- # see {Capybara::Node::Matchers#has_no_select?}
262
+ # @see Capybara::Node::Matchers#has_no_select?
263
263
 
264
264
  ##
265
265
  # Assertion that there is table
266
266
  #
267
267
  # @!method assert_table
268
- # see {Capybara::Node::Matchers#has_table?}
268
+ # @see Capybara::Node::Matchers#has_table?
269
269
 
270
270
  ##
271
271
  # Assertion that there is no table
272
272
  #
273
273
  # @!method refute_table
274
274
  # @!method assert_no_table
275
- # see {Capybara::Node::Matchers#has_no_table?}
275
+ # @see Capybara::Node::Matchers#has_no_table?
276
276
 
277
277
  private
278
278
 
@@ -514,7 +514,8 @@ module Capybara
514
514
  def reload
515
515
  if @allow_reload
516
516
  begin
517
- reloaded = query_scope.reload.first(@query.name, @query.locator, @query.options)
517
+ reloaded = @query.resolve_for(query_scope.reload)&.first
518
+
518
519
  @base = reloaded.base if reloaded
519
520
  rescue StandardError => e
520
521
  raise e unless catch_error?(e)
@@ -141,8 +141,8 @@ module Capybara
141
141
  # or descendants of the current node. If options are provided, the assertion
142
142
  # will check that each locator is present with those options as well (other than `:wait`).
143
143
  #
144
- # page.assert_all_of_selectors(:custom, 'Tom', 'Joe', visible: all)
145
- # page.assert_all_of_selectors(:css, '#my_div', 'a.not_clicked')
144
+ # page.assert_all_of_selectors(:custom, 'Tom', 'Joe', visible: all)
145
+ # page.assert_all_of_selectors(:css, '#my_div', 'a.not_clicked')
146
146
  #
147
147
  # It accepts all options that {Capybara::Node::Finders#all} accepts,
148
148
  # such as `:text` and `:visible`.
@@ -162,8 +162,8 @@ module Capybara
162
162
  # or descendants of the current node. If options are provided, the assertion
163
163
  # will check that each locator is not present with those options as well (other than `:wait`).
164
164
  #
165
- # page.assert_none_of_selectors(:custom, 'Tom', 'Joe', visible: all)
166
- # page.assert_none_of_selectors(:css, '#my_div', 'a.not_clicked')
165
+ # page.assert_none_of_selectors(:custom, 'Tom', 'Joe', visible: all)
166
+ # page.assert_none_of_selectors(:css, '#my_div', 'a.not_clicked')
167
167
  #
168
168
  # It accepts all options that {Capybara::Node::Finders#all} accepts,
169
169
  # such as `:text` and `:visible`.
@@ -183,8 +183,8 @@ module Capybara
183
183
  # or descendants of the current node. If options are provided, the assertion
184
184
  # will check that each locator is present with those options as well (other than `:wait`).
185
185
  #
186
- # page.assert_any_of_selectors(:custom, 'Tom', 'Joe', visible: all)
187
- # page.assert_any_of_selectors(:css, '#my_div', 'a.not_clicked')
186
+ # page.assert_any_of_selectors(:custom, 'Tom', 'Joe', visible: all)
187
+ # page.assert_any_of_selectors(:css, '#my_div', 'a.not_clicked')
188
188
  #
189
189
  # It accepts all options that {Capybara::Node::Finders#all} accepts,
190
190
  # such as `:text` and `:visible`.
@@ -197,7 +197,8 @@ module Capybara
197
197
  x.ancestor_or_self[
198
198
  x.attr(:style)[x.contains('display:none') | x.contains('display: none')] |
199
199
  x.attr(:hidden) |
200
- x.qname.one_of('script', 'head')
200
+ x.qname.one_of('script', 'head') |
201
+ (~x.self(:summary) & XPath.parent(:details))
201
202
  ].boolean
202
203
  end.to_s.freeze
203
204
  end
@@ -3,20 +3,16 @@
3
3
  module Capybara
4
4
  module Queries
5
5
  class AncestorQuery < Capybara::Queries::SelectorQuery
6
- def initialize(*args)
7
- super
8
- @count_options = {}
9
- COUNT_KEYS.each do |key|
10
- @count_options[key] = @options.delete(key) if @options.key?(key)
11
- end
12
- end
13
-
14
6
  # @api private
15
7
  def resolve_for(node, exact = nil)
16
8
  @child_node = node
9
+
17
10
  node.synchronize do
18
11
  match_results = super(node.session.current_scope, exact)
19
- node.all(:xpath, XPath.ancestor, **@count_options) { |el| match_results.include?(el) }
12
+ ancestors = node.find_xpath(XPath.ancestor.to_s)
13
+ .map(&method(:to_element))
14
+ .select { |el| match_results.include?(el) }
15
+ Capybara::Result.new(ancestors, self)
20
16
  end
21
17
  end
22
18
 
@@ -451,9 +451,9 @@ module Capybara
451
451
  return (visible != :hidden) && (node.initial_cache[:visible] != false) && !node.obscured? if obscured == false
452
452
 
453
453
  vis = case visible
454
- when :visible then
454
+ when :visible
455
455
  node.initial_cache[:visible] || (node.initial_cache[:visible].nil? && node.visible?)
456
- when :hidden then
456
+ when :hidden
457
457
  (node.initial_cache[:visible] == false) || (node.initial_cache[:visbile].nil? && !node.visible?)
458
458
  else
459
459
  true
@@ -3,21 +3,15 @@
3
3
  module Capybara
4
4
  module Queries
5
5
  class SiblingQuery < SelectorQuery
6
- def initialize(*args)
7
- super
8
- @count_options = {}
9
- COUNT_KEYS.each do |key|
10
- @count_options[key] = @options.delete(key) if @options.key?(key)
11
- end
12
- end
13
-
14
6
  # @api private
15
7
  def resolve_for(node, exact = nil)
16
8
  @sibling_node = node
17
9
  node.synchronize do
18
10
  match_results = super(node.session.current_scope, exact)
19
- xpath = XPath.preceding_sibling + XPath.following_sibling
20
- node.all(:xpath, xpath, **@count_options) { |el| match_results.include?(el) }
11
+ siblings = node.find_xpath((XPath.preceding_sibling + XPath.following_sibling).to_s)
12
+ .map(&method(:to_element))
13
+ .select { |el| match_results.include?(el) }
14
+ Capybara::Result.new(siblings, self)
21
15
  end
22
16
  end
23
17
 
@@ -23,7 +23,10 @@ Capybara.register_server :puma do |app, port, host, **options|
23
23
  # If we just run the Puma Rack handler it installs signal handlers which prevent us from being able to interrupt tests.
24
24
  # Therefore construct and run the Server instance ourselves.
25
25
  # Rack::Handler::Puma.run(app, { Host: host, Port: port, Threads: "0:4", workers: 0, daemon: false }.merge(options))
26
- options = { Host: host, Port: port, Threads: '0:4', workers: 0, daemon: false, queue_requests: false }.merge(options)
26
+ default_options = { Host: host, Port: port, Threads: '0:4', workers: 0, daemon: false, queue_requests: false }
27
+ default_options[:queue_requests] = false if options[:Host]&.start_with?('ssl://')
28
+ options = default_options.merge(options)
29
+
27
30
  conf = Rack::Handler::Puma.config(app, options)
28
31
  events = conf.options[:Silent] ? ::Puma::Events.strings : ::Puma::Events.stdio
29
32
 
@@ -100,6 +100,8 @@ module Capybara
100
100
  def extract_strings(process_alternatives)
101
101
  strings = []
102
102
  each do |exp|
103
+ next if exp.ignore?
104
+
103
105
  next strings.push(nil) if exp.optional? && !process_alternatives
104
106
 
105
107
  next strings.push(exp.alternative_strings) if exp.alternation? && process_alternatives
@@ -159,6 +161,11 @@ module Capybara
159
161
  alts.all?(&:any?) ? Set.new(alts) : nil
160
162
  end
161
163
 
164
+ def ignore?
165
+ [Regexp::Expression::Assertion::NegativeLookahead,
166
+ Regexp::Expression::Assertion::NegativeLookbehind].any? { |klass| @exp.is_a? klass }
167
+ end
168
+
162
169
  private
163
170
 
164
171
  def indeterminate?
@@ -1 +1 @@
1
- (function(){function f(t,e,n){function r(t){var e=x(t);if(0<e.height&&0<e.width)return!0;if("PATH"==t.tagName.toUpperCase()&&(0<e.height||0<e.width)){var n=window.getComputedStyle(t)["stroke-width"];return!!n&&0<parseInt(n,10)}return"hidden"!=window.getComputedStyle(t).overflow&&Array.prototype.slice.call(t.childNodes).some(function(t){return t.nodeType==Node.TEXT_NODE||t.nodeType==Node.ELEMENT_NODE&&r(t)})}function i(t){return C(t)==T.HIDDEN&&Array.prototype.slice.call(t.childNodes).every(function(t){return t.nodeType!=Node.ELEMENT_NODE||i(t)||!r(t)})}var o=t.tagName.toUpperCase();if("BODY"==o)return!0;var a=D(t);if(a&&a.tagName&&"DETAILS"==a.tagName.toUpperCase()&&!a.open&&"SUMMARY"!=o)return!1;if("OPTION"==o||"OPTGROUP"==o){var u=v(t,function(t){return"SELECT"==t.tagName.toUpperCase()});return!!u&&f(u,!0,n)}var l=c(t);if(l)return!!l.image&&0<l.rect.width&&0<l.rect.height&&f(l.image,e,n);if("INPUT"==o&&"hidden"==t.type.toLowerCase())return!1;if("NOSCRIPT"==o)return!1;var d=window.getComputedStyle(t).visibility;return"collapse"!=d&&"hidden"!=d&&(!!n(t)&&(!(!e&&0==h(t))&&(!!r(t)&&!i(t))))}function E(t){var e=x(t);return{left:e.left,right:e.left+e.width,top:e.top,bottom:e.top+e.height}}function D(t){return t.parentElement}function C(t){function e(t){function e(t){if(t==u)return!0;var e=window.getComputedStyle(t),n=e.display;return 0!=n.indexOf("inline")&&"contents"!=n&&("absolute"!=r||"static"!=e.position)}var r=window.getComputedStyle(t).position;if("fixed"==r)return i=!0,t==u?null:u;for(var n=D(t);n&&!e(n);)n=D(n);return n}function n(t){var e=t;if("visible"==d)if(t==u&&l)e=l;else if(t==l)return{x:"visible",y:"visible"};var n=window.getComputedStyle(e),r={x:n["overflow-x"],y:n["overflow-y"]};return t==u&&(r.x="visible"==r.x?"auto":r.x,r.y="visible"==r.y?"auto":r.y),r}function r(t){return t==u?{x:window.scrollX,y:window.scrollY}:{x:t.scrollLeft,y:t.scrollTop}}for(var i,o=E(t),a=t.ownerDocument,u=a.documentElement,l=a.body,d=window.getComputedStyle(u).overflow,f=e(t);f;f=e(f)){var h=n(f);if("visible"!=h.x||"visible"!=h.y){var s=x(f);if(0==s.width||0==s.height)return T.HIDDEN;var p=o.right<s.left,c=o.bottom<s.top;if(p&&"hidden"==h.x||c&&"hidden"==h.y)return T.HIDDEN;if(p&&"visible"!=h.x||c&&"visible"!=h.y){var v=r(f),g=o.right<s.left-v.x,w=o.bottom<s.top-v.y;return g&&"visible"!=h.x||w&&"visible"!=h.x?T.HIDDEN:C(f)==T.HIDDEN?T.HIDDEN:T.SCROLL}var N=o.left>=s.left+s.width,m=o.top>=s.top+s.height;if(N&&"hidden"==h.x||m&&"hidden"==h.y)return T.HIDDEN;if(N&&"visible"!=h.x||m&&"visible"!=h.y){if(i){var y=r(f);if(o.left>=u.scrollWidth-y.x||o.right>=u.scrollHeight-y.y)return T.HIDDEN}return C(f)==T.HIDDEN?T.HIDDEN:T.SCROLL}}}return T.NONE}function o(t){var e=t.document.documentElement;return{width:e.clientWidth,height:e.clientHeight}}function p(t,e,n,r){return{left:t,top:e,width:n,height:r}}function x(t){var e,n=c(t);if(n)return n.rect;if("HTML"==t.tagName.toUpperCase()){t.ownerDocument;var r=o(window);return p(0,0,r.width,r.height)}try{e=t.getBoundingClientRect()}catch(i){return p(0,0,0,0)}return p(e.left,e.top,e.right-e.left,e.bottom-e.top)}function h(t){var e=1,n=window.getComputedStyle(t).opacity;n&&(e=Number(n));var r=D(t);return r&&r.nodeType==Node.ELEMENT_NODE&&(e*=h(r)),e}function s(t){var e=t.shape.toLowerCase(),n=t.coords.split(",");if("rect"==e&&4==n.length){var r=n[0],i=n[1];return p(r,i,n[2]-r,n[3]-i)}if("circle"==e&&3==n.length){var o=n[0],a=n[1],u=n[2];return p(o-u,a-u,2*u,2*u)}if("poly"==e&&2<n.length){for(var l=n[0],d=n[1],f=l,h=d,s=2;s+1<n.length;s+=2)l=Math.min(l,n[s]),f=Math.max(f,n[s]),d=Math.min(d,n[s+1]),h=Math.max(h,n[s+1]);return p(l,d,f-l,h-d)}return p(0,0,0,0)}function c(t){var e=t.tagName.toUpperCase(),n="MAP"==e;if(!n&&"AREA"!=e)return null;var r=n?t:"MAP"==D(t).tagName.toUpperCase()?D(t):null,i=null,o=null;if(r&&r.name&&((i=r.ownerDocument.querySelector("*[usemap='#"+r.name+"']"))&&(o=x(i),!n&&"default"!=t.shape.toLowerCase()))){var a=s(t),u=Math.min(Math.max(a.left,0),o.width),l=Math.min(Math.max(a.top,0),o.height),d=Math.min(a.width,o.width-u),f=Math.min(a.height,o.height-l);o=p(u+o.left,l+o.top,d,f)}return{image:i,rect:o||p(0,0,0,0)}}function v(t,e){for(t&&(t=D(t));t;){if(e(t))return t;t=D(t)}return null}function r(t){var e=t.parentNode;if(e&&e.shadowRoot&&t.assignedSlot!==undefined)return t.assignedSlot?t.assignedSlot.parentNode:null;if(t.getDestinationInsertionPoints){var n=t.getDestinationInsertionPoints();if(0<n.length)return n[n.length-1]}return e}var T={NONE:"none",HIDDEN:"hidden",SCROLL:"scroll"};return function i(t,e){function n(t){if("none"==window.getComputedStyle(t).display)return!1;var e=r(t);if("function"==typeof ShadowRoot&&e instanceof ShadowRoot){if(e.host.shadowRoot!==e)return!1;e=e.host}return!(!e||e.nodeType!=Node.DOCUMENT_NODE&&e.nodeType!=Node.DOCUMENT_FRAGMENT_NODE)||e&&n(e)}return f(t,!!e,n)}})()
1
+ (function(){function d(t,e,n){function r(t){var e=x(t);if(0<e.height&&0<e.width)return!0;if("PATH"==t.tagName.toUpperCase()&&(0<e.height||0<e.width)){var n=window.getComputedStyle(t)["stroke-width"];return!!n&&0<parseInt(n,10)}return"hidden"!=window.getComputedStyle(t).overflow&&Array.prototype.slice.call(t.childNodes).some(function(t){return t.nodeType==Node.TEXT_NODE||t.nodeType==Node.ELEMENT_NODE&&r(t)})}function i(t){return C(t)==T.HIDDEN&&Array.prototype.slice.call(t.childNodes).every(function(t){return t.nodeType!=Node.ELEMENT_NODE||i(t)||!r(t)})}var o=t.tagName.toUpperCase();if("BODY"==o)return!0;if("OPTION"==o||"OPTGROUP"==o){var a=c(t,function(t){return"SELECT"==t.tagName.toUpperCase()});return!!a&&d(a,!0,n)}var u=s(t);if(u)return!!u.image&&0<u.rect.width&&0<u.rect.height&&d(u.image,e,n);if("INPUT"==o&&"hidden"==t.type.toLowerCase())return!1;if("NOSCRIPT"==o)return!1;var l=window.getComputedStyle(t).visibility;return"collapse"!=l&&"hidden"!=l&&(!!n(t)&&(!(!e&&0==f(t))&&(!!r(t)&&!i(t))))}function E(t){var e=x(t);return{left:e.left,right:e.left+e.width,top:e.top,bottom:e.top+e.height}}function D(t){return t.parentElement}function C(t){function e(t){function e(t){if(t==u)return!0;var e=window.getComputedStyle(t),n=e.display;return 0!=n.indexOf("inline")&&"contents"!=n&&("absolute"!=r||"static"!=e.position)}var r=window.getComputedStyle(t).position;if("fixed"==r)return i=!0,t==u?null:u;for(var n=D(t);n&&!e(n);)n=D(n);return n}function n(t){var e=t;if("visible"==d)if(t==u&&l)e=l;else if(t==l)return{x:"visible",y:"visible"};var n=window.getComputedStyle(e),r={x:n["overflow-x"],y:n["overflow-y"]};return t==u&&(r.x="visible"==r.x?"auto":r.x,r.y="visible"==r.y?"auto":r.y),r}function r(t){return t==u?{x:window.scrollX,y:window.scrollY}:{x:t.scrollLeft,y:t.scrollTop}}for(var i,o=E(t),a=t.ownerDocument,u=a.documentElement,l=a.body,d=window.getComputedStyle(u).overflow,f=e(t);f;f=e(f)){var h=n(f);if("visible"!=h.x||"visible"!=h.y){var s=x(f);if(0==s.width||0==s.height)return T.HIDDEN;var p=o.right<s.left,c=o.bottom<s.top;if(p&&"hidden"==h.x||c&&"hidden"==h.y)return T.HIDDEN;if(p&&"visible"!=h.x||c&&"visible"!=h.y){var v=r(f),g=o.right<s.left-v.x,w=o.bottom<s.top-v.y;return g&&"visible"!=h.x||w&&"visible"!=h.x?T.HIDDEN:C(f)==T.HIDDEN?T.HIDDEN:T.SCROLL}var N=o.left>=s.left+s.width,m=o.top>=s.top+s.height;if(N&&"hidden"==h.x||m&&"hidden"==h.y)return T.HIDDEN;if(N&&"visible"!=h.x||m&&"visible"!=h.y){if(i){var y=r(f);if(o.left>=u.scrollWidth-y.x||o.right>=u.scrollHeight-y.y)return T.HIDDEN}return C(f)==T.HIDDEN?T.HIDDEN:T.SCROLL}}}return T.NONE}function o(t){var e=t.document.documentElement;return{width:e.clientWidth,height:e.clientHeight}}function p(t,e,n,r){return{left:t,top:e,width:n,height:r}}function x(t){var e,n=s(t);if(n)return n.rect;if("HTML"==t.tagName.toUpperCase()){t.ownerDocument;var r=o(window);return p(0,0,r.width,r.height)}try{e=t.getBoundingClientRect()}catch(i){return p(0,0,0,0)}return p(e.left,e.top,e.right-e.left,e.bottom-e.top)}function f(t){var e=1,n=window.getComputedStyle(t).opacity;n&&(e=Number(n));var r=D(t);return r&&r.nodeType==Node.ELEMENT_NODE&&(e*=f(r)),e}function h(t){var e=t.shape.toLowerCase(),n=t.coords.split(",");if("rect"==e&&4==n.length){var r=n[0],i=n[1];return p(r,i,n[2]-r,n[3]-i)}if("circle"==e&&3==n.length){var o=n[0],a=n[1],u=n[2];return p(o-u,a-u,2*u,2*u)}if("poly"==e&&2<n.length){for(var l=n[0],d=n[1],f=l,h=d,s=2;s+1<n.length;s+=2)l=Math.min(l,n[s]),f=Math.max(f,n[s]),d=Math.min(d,n[s+1]),h=Math.max(h,n[s+1]);return p(l,d,f-l,h-d)}return p(0,0,0,0)}function s(t){var e=t.tagName.toUpperCase(),n="MAP"==e;if(!n&&"AREA"!=e)return null;var r=n?t:"MAP"==D(t).tagName.toUpperCase()?D(t):null,i=null,o=null;if(r&&r.name&&((i=r.ownerDocument.querySelector("*[usemap='#"+r.name+"']"))&&(o=x(i),!n&&"default"!=t.shape.toLowerCase()))){var a=h(t),u=Math.min(Math.max(a.left,0),o.width),l=Math.min(Math.max(a.top,0),o.height),d=Math.min(a.width,o.width-u),f=Math.min(a.height,o.height-l);o=p(u+o.left,l+o.top,d,f)}return{image:i,rect:o||p(0,0,0,0)}}function c(t,e){for(t&&(t=D(t));t;){if(e(t))return t;t=D(t)}return null}function r(t){var e=t.parentNode;if(e&&e.shadowRoot&&t.assignedSlot!==undefined)return t.assignedSlot?t.assignedSlot.parentNode:null;if(t.getDestinationInsertionPoints){var n=t.getDestinationInsertionPoints();if(0<n.length)return n[n.length-1]}return e}var T={NONE:"none",HIDDEN:"hidden",SCROLL:"scroll"};return function i(t,e){function n(t){if("none"==window.getComputedStyle(t).display)return!1;var e=r(t);if("function"==typeof ShadowRoot&&e instanceof ShadowRoot){if(e.host.shadowRoot!==e)return!1;e=e.host}return!(!e||e.nodeType!=Node.DOCUMENT_NODE&&e.nodeType!=Node.DOCUMENT_FRAGMENT_NODE)||!(e&&e.tagName&&"DETAILS"==e.tagName.toUpperCase()&&!e.open&&"SUMMARY"!=t.tagName)&&(e&&n(e))}return d(t,!!e,n)}})()
@@ -14,15 +14,6 @@
14
14
  return true;
15
15
  }
16
16
 
17
- // Child of DETAILS element is not shown unless the DETAILS element is open
18
- // or the child is a SUMMARY element.
19
-
20
- var parent = getParentElement(elem);
21
- if (parent && parent.tagName && (parent.tagName.toUpperCase() == "DETAILS") &&
22
- !parent.open && !(elemTagName == "SUMMARY")) {
23
- return false;
24
- }
25
-
26
17
  // Option or optgroup is shown if enclosing select is shown (ignoring the
27
18
  // select's opacity).
28
19
  if ((elemTagName == "OPTION") ||
@@ -73,12 +64,14 @@
73
64
  if (rect.height > 0 && rect.width > 0) {
74
65
  return true;
75
66
  }
67
+
76
68
  // A vertical or horizontal SVG Path element will report zero width or
77
69
  // height but is "shown" if it has a positive stroke-width.
78
70
  if ((e.tagName.toUpperCase() == "PATH") && (rect.height > 0 || rect.width > 0)) {
79
71
  var strokeWidth = window.getComputedStyle(e)["stroke-width"];
80
72
  return !!strokeWidth && (parseInt(strokeWidth, 10) > 0);
81
73
  }
74
+
82
75
  // Zero-sized elements should still be considered to have positive size
83
76
  // if they have a child element or text node with positive size, unless
84
77
  // the element has an 'overflow' style of "hidden".
@@ -446,6 +439,13 @@
446
439
  return true;
447
440
  }
448
441
 
442
+ // Child of DETAILS element is not shown unless the DETAILS element is open
443
+ // or the child is a SUMMARY element.
444
+ if (parent && parent.tagName && (parent.tagName.toUpperCase() == "DETAILS") &&
445
+ !parent.open && !(e.tagName == "SUMMARY")) {
446
+ return false;
447
+ }
448
+
449
449
  return parent && displayed(parent);
450
450
  }
451
451