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 +4 -4
- data/.github/workflows/test.yml +3 -3
- data/CHANGELOG.md +7 -0
- data/Gemfile.lock +2 -2
- data/README.md +2 -1
- data/capybara-lockstep.gemspec +1 -1
- data/lib/capybara-lockstep/helper.js +39 -30
- data/lib/capybara-lockstep/version.rb +1 -1
- metadata +8 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fa4a510d3f4745ef60812fdf3ab03f6c3e8ede0c6ea4046cb87364d6664e2a7d
|
|
4
|
+
data.tar.gz: 78be38bdb5aa4fcb9147394ac3adb11f3112c18539ba53a096c214931be753cb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 356df47acf01a2642769be49f54c48736ea030c803a92b3c059c587e5e82bb927fa0b4e5dcf7953060162a46491cf0122c6a2d0debd1f607cbd1b09cc8608ff2
|
|
7
|
+
data.tar.gz: c5d1189ee309d32197f19765dad9014cc59f13a8d9f6a17287537045cbf02664b480ce9d087e933b3fad1a2c63b4460b5dc5e61e20d3e0b98d76cde9d90eaff3
|
data/.github/workflows/test.yml
CHANGED
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
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.
|
data/capybara-lockstep.gemspec
CHANGED
|
@@ -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/
|
|
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
|
-
|
|
181
|
-
|
|
182
|
-
let type = element.getAttribute('type')
|
|
180
|
+
return element.matches('script[src]') && !hasDataSource(element)
|
|
181
|
+
}
|
|
183
182
|
|
|
184
|
-
|
|
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
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
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
|
-
|
|
194
|
-
|
|
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
|
-
|
|
197
|
-
|
|
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
|
|
204
|
-
|
|
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
|
|
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(
|
|
224
|
-
element.removeEventListener(
|
|
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,
|
|
251
|
+
setTimeout(checkCondition, 150)
|
|
244
252
|
}
|
|
245
253
|
|
|
246
|
-
element.addEventListener(
|
|
247
|
-
element.addEventListener(
|
|
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,
|
|
260
|
-
trackRemoteElement(addedNode,
|
|
267
|
+
trackRemoteElement(addedNode, isTrackableImage, 'Image')
|
|
268
|
+
trackRemoteElement(addedNode, isTrackableIFrame, 'Inline frame')
|
|
269
|
+
trackMediaElement(addedNode, isTrackableMediaElement, 'Media element')
|
|
261
270
|
}
|
|
262
271
|
})
|
|
263
272
|
})
|
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.
|
|
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:
|
|
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/
|
|
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.
|
|
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: []
|