capybara-lockstep 2.1.1 → 2.2.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: 92432e49d223c6a01c09cbe199fec3d3ad0fdc80c5eb5def77883e25f5bace80
4
- data.tar.gz: 43fcb6f560accb02c5a6081506a6d1b65c571ab149b0d470efeddf49adb853b9
3
+ metadata.gz: fa4a510d3f4745ef60812fdf3ab03f6c3e8ede0c6ea4046cb87364d6664e2a7d
4
+ data.tar.gz: 78be38bdb5aa4fcb9147394ac3adb11f3112c18539ba53a096c214931be753cb
5
5
  SHA512:
6
- metadata.gz: ef3cb7e6d8789b1108602ad7d18ba7e00bf52e93135d8ebec84d9307c556f800f05218d4b23a750d66888e99f9f2939c37f76d3fd3359cdf765b5799b2a3e182
7
- data.tar.gz: d2017577968548a815e9e60c9d1fa5838ab3c16fcbb1122acdaf9185e2c44c36766cca61a53de6c016ed691b4d558ae4fab282ed34cd18aa5348a8db64f527ad
6
+ metadata.gz: 356df47acf01a2642769be49f54c48736ea030c803a92b3c059c587e5e82bb927fa0b4e5dcf7953060162a46491cf0122c6a2d0debd1f607cbd1b09cc8608ff2
7
+ data.tar.gz: c5d1189ee309d32197f19765dad9014cc59f13a8d9f6a17287537045cbf02664b480ce9d087e933b3fad1a2c63b4460b5dc5e61e20d3e0b98d76cde9d90eaff3
@@ -3,13 +3,13 @@ name: Tests
3
3
  on:
4
4
  push:
5
5
  branches:
6
- - master
6
+ - main
7
7
  pull_request:
8
8
  branches:
9
- - master
9
+ - main
10
10
  workflow_dispatch:
11
11
  branches:
12
- - master
12
+ - main
13
13
  jobs:
14
14
  test:
15
15
  runs-on: ubuntu-20.04
data/CHANGELOG.md CHANGED
@@ -3,6 +3,13 @@ All notable changes to this project will be documented in this file.
3
3
  This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
4
4
 
5
5
 
6
+ # 2.2.0
7
+
8
+ - We now wait for `<video>` and `<audio>` elements to load their metadata. This addresses a race condition where a media element is inserted into the DOM, but another user action deletes or renames the source before the browser could load the initial metadata frames.
9
+ - We now wait for `<script type="module">`.
10
+ - We no longer wait for `<img loading="lazy">` or `<iframe loading="lazy">`. This prevents a deadlock where we would wait forever for an element that defers loading until it is scrolled into the viewport.
11
+
12
+
6
13
  # 2.1.0
7
14
 
8
15
  - We now synchronize for an additional [JavaScript task](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/) after `history.pushState()`, `history.replaceState()`, `history.forward()`, `history.back()` and `history.go()`.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- capybara-lockstep (2.1.1)
4
+ capybara-lockstep (2.2.0)
5
5
  activesupport (>= 4.2)
6
6
  capybara (>= 3.0)
7
7
  ruby2_keywords
@@ -113,4 +113,4 @@ DEPENDENCIES
113
113
  thin
114
114
 
115
115
  BUNDLED WITH
116
- 4.0.15
116
+ 2.2.32
data/README.md CHANGED
@@ -71,7 +71,8 @@ When capybara-lockstep synchronizes it will:
71
71
  - wait for client-side JavaScript to render or hydrate DOM elements.
72
72
  - wait for any pending AJAX requests to finish and their callbacks to be called.
73
73
  - wait for dynamically inserted `<script>`s to load (e.g. from [dynamic imports](https://webpack.js.org/guides/code-splitting/#dynamic-imports) or Analytics snippets).
74
- - waits for dynamically inserted `<img>` or `<iframe>` elements to load.
74
+ - waits for dynamically inserted `<img>` or `<iframe>` elements to load (ignoring [lazy-loaded](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#lazy) elements).
75
+ - waits for dynamically inserted `<audio>` and `<video>` elements to load their [metadata](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/loadedmetadata_event)
75
76
 
76
77
  In summary Capybara can no longer observe or interact with the page while HTTP requests are in flight.
77
78
  This covers most async work that causes flaky tests.
@@ -15,7 +15,7 @@ Gem::Specification.new do |spec|
15
15
  spec.metadata["source_code_uri"] = spec.homepage
16
16
 
17
17
  spec.metadata["bug_tracker_uri"] = "https://github.com/makandra/capybara-lockstep/issues"
18
- spec.metadata["changelog_uri"] = "https://github.com/makandra/capybara-lockstep/blob/master/CHANGELOG.md"
18
+ spec.metadata["changelog_uri"] = "https://github.com/makandra/capybara-lockstep/blob/main/CHANGELOG.md"
19
19
  spec.metadata["rubygems_mfa_required"] = 'true'
20
20
 
21
21
  # Specify which files should be added to the gem when it is released.
@@ -177,39 +177,47 @@ window.CapybaraLockstep = (function() {
177
177
  }
178
178
 
179
179
  function isRemoteScript(element) {
180
- if (element.tagName === 'SCRIPT') {
181
- let src = element.getAttribute('src')
182
- let type = element.getAttribute('type')
180
+ return element.matches('script[src]') && !hasDataSource(element)
181
+ }
183
182
 
184
- return src && (!type || /javascript/i.test(type))
185
- }
183
+ function isTrackableImage(element) {
184
+ return element.matches('img') &&
185
+ !element.complete &&
186
+ !hasDataSource(element) &&
187
+ element.getAttribute('loading') !== 'lazy'
186
188
  }
187
189
 
188
- function isRemoteImage(element) {
189
- if (element.tagName === 'IMG' && !element.complete) {
190
- let src = element.getAttribute('src')
191
- let srcSet = element.getAttribute('srcset')
190
+ function isTrackableIFrame(element) {
191
+ return element.matches('iframe') &&
192
+ !hasDataSource(element) &&
193
+ element.getAttribute('loading') !== 'lazy'
194
+ }
195
+
196
+ function hasDataSource(element) {
197
+ // <img> can have <img src> and <img srcset>
198
+ // <video> can have <video src> or <video><source src>
199
+ // <audio> can have <audio src> or <audio><source src>
200
+ return element.matches('[src*="data:"], [srcset*="data:"]') ||
201
+ !!element.querySelector('source [src*="data:"], source [srcset*="data:"]')
202
+ }
192
203
 
193
- let localSrcPattern = /^data:/
194
- let localSrcSetPattern = /(^|\s)data:/
204
+ function isTrackableMediaElement(element) {
205
+ return element.matches('audio, video') &&
206
+ element.readyState === 0 && // no metadata known
207
+ !hasDataSource(element) &&
208
+ element.getAttribute('preload') !== 'none'
209
+ }
195
210
 
196
- let hasLocalSrc = src && localSrcPattern.test(src)
197
- let hasLocalSrcSet = srcSet && localSrcSetPattern.test(srcSet)
211
+ function trackRemoteElement(element, condition, workTag) {
212
+ trackLoadingElement(element, condition, workTag, 'load', 'error')
198
213
 
199
- return (src && !hasLocalSrc) || (srcSet && !hasLocalSrcSet)
200
- }
201
214
  }
202
215
 
203
- function isRemoteInlineFrame(element) {
204
- if (element.tagName === 'IFRAME') {
205
- let src = element.getAttribute('src')
206
- let localSrcPattern = /^data:/
207
- let hasLocalSrc = src && localSrcPattern.test(src)
208
- return (src && !hasLocalSrc)
209
- }
216
+ function trackMediaElement(element, condition, workTag) {
217
+ trackLoadingElement(element, condition, workTag, 'loadedmetadata', 'error')
210
218
  }
211
219
 
212
- function trackRemoteElement(element, condition, workTag) {
220
+ function trackLoadingElement(element, condition, workTag, loadEvent, errorEvent) {
213
221
  if (!condition(element)) {
214
222
  return
215
223
  }
@@ -220,8 +228,8 @@ window.CapybaraLockstep = (function() {
220
228
 
221
229
  let doStop = function() {
222
230
  stopped = true
223
- element.removeEventListener('load', doStop)
224
- element.removeEventListener('error', doStop)
231
+ element.removeEventListener(loadEvent, doStop)
232
+ element.removeEventListener(errorEvent, doStop)
225
233
  stopWork(workTag)
226
234
  }
227
235
 
@@ -240,11 +248,11 @@ window.CapybaraLockstep = (function() {
240
248
  }
241
249
 
242
250
  let scheduleCheckCondition = function() {
243
- setTimeout(checkCondition, 200)
251
+ setTimeout(checkCondition, 150)
244
252
  }
245
253
 
246
- element.addEventListener('load', doStop)
247
- element.addEventListener('error', doStop)
254
+ element.addEventListener(loadEvent, doStop)
255
+ element.addEventListener(errorEvent, doStop)
248
256
 
249
257
  // We periodically check whether we still think the element will
250
258
  // produce a `load` or `error` event.
@@ -256,8 +264,9 @@ window.CapybaraLockstep = (function() {
256
264
  change.addedNodes.forEach(function(addedNode) {
257
265
  if (addedNode.nodeType === Node.ELEMENT_NODE) {
258
266
  trackRemoteElement(addedNode, isRemoteScript, 'Script')
259
- trackRemoteElement(addedNode, isRemoteImage, 'Image')
260
- trackRemoteElement(addedNode, isRemoteInlineFrame, 'Inline frame')
267
+ trackRemoteElement(addedNode, isTrackableImage, 'Image')
268
+ trackRemoteElement(addedNode, isTrackableIFrame, 'Inline frame')
269
+ trackMediaElement(addedNode, isTrackableMediaElement, 'Media element')
261
270
  }
262
271
  })
263
272
  })
@@ -1,5 +1,5 @@
1
1
  module Capybara
2
2
  module Lockstep
3
- VERSION = "2.1.1"
3
+ VERSION = "2.2.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capybara-lockstep
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henning Koch
8
+ autorequire:
8
9
  bindir: exe
9
10
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
11
+ date: 2024-02-12 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
14
  name: capybara
@@ -65,6 +66,7 @@ dependencies:
65
66
  - - ">="
66
67
  - !ruby/object:Gem::Version
67
68
  version: '0'
69
+ description:
68
70
  email:
69
71
  - henning.koch@makandra.de
70
72
  executables: []
@@ -105,8 +107,9 @@ metadata:
105
107
  homepage_uri: https://github.com/makandra/capybara-lockstep
106
108
  source_code_uri: https://github.com/makandra/capybara-lockstep
107
109
  bug_tracker_uri: https://github.com/makandra/capybara-lockstep/issues
108
- changelog_uri: https://github.com/makandra/capybara-lockstep/blob/master/CHANGELOG.md
110
+ changelog_uri: https://github.com/makandra/capybara-lockstep/blob/main/CHANGELOG.md
109
111
  rubygems_mfa_required: 'true'
112
+ post_install_message:
110
113
  rdoc_options: []
111
114
  require_paths:
112
115
  - lib
@@ -121,7 +124,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
121
124
  - !ruby/object:Gem::Version
122
125
  version: '0'
123
126
  requirements: []
124
- rubygems_version: 4.0.15
127
+ rubygems_version: 3.4.3
128
+ signing_key:
125
129
  specification_version: 4
126
130
  summary: Synchronize Capybara commands with client-side JavaScript and AJAX requests
127
131
  test_files: []