capybara-lockstep 2.0.2 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/Gemfile.lock +1 -1
- data/README.md +20 -2
- data/lib/capybara-lockstep/configuration.rb +1 -1
- data/lib/capybara-lockstep/helper.js +50 -21
- data/lib/capybara-lockstep/helper.rb +6 -5
- data/lib/capybara-lockstep/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 514789431b5b017176575acd43c1a5b6558040f31cf7cb4ac119cf10e756dbee
|
4
|
+
data.tar.gz: 2945ac3b32b7f83a7bc2bd14848f67950c12e5063033d8dbe2063788dfe8c024
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b2dac0508c3caaa13fd28fe285c9c3b7d2b796dfba6c2bf788578ffee90135b6504a2e9b731d8bf4496806723d26c28bf5ccb536e5de21c2b5661b354a9e2de1
|
7
|
+
data.tar.gz: 4e80b685b588dfded10cb0783cbe62aceb00517199ef5527ce76fb76a234c96eb913ec0e7d08df2e22a7dd5a2b2d475bed0d4318add6ddee9fd27403afc2e0fe
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,21 @@ 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.1.0
|
7
|
+
|
8
|
+
- 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()`.
|
9
|
+
- We now synchronize for an additional JavaScript task after `popstate` and `hashchange` events.
|
10
|
+
- We now synchronize for an additional JavaScript task when the window is resized.
|
11
|
+
- You can now disable automatic synchronization for the duration of a block: `Capybara::Lockstep.with_mode(:manual) { ... }`.
|
12
|
+
|
13
|
+
|
14
|
+
# 2.0.3
|
15
|
+
|
16
|
+
- Fix a bug where we wouldn't wait for an additional [JavaScript task](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/) after a tracked event or async job.
|
17
|
+
- Fix a bug where the `Capybara::Lockstep.wait_tasks` configuration would be ignored.
|
18
|
+
- Fix a bug where the `capybara_lockstep_js` helper (for use without Rails) would not include the current configuration.
|
19
|
+
|
20
|
+
|
6
21
|
# 2.0.2
|
7
22
|
|
8
23
|
- Fix a bug where setting a logger object with `Capybara::Lockstep.debug = logger` would crash (by @dorianmarie).
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -349,7 +349,23 @@ ensure
|
|
349
349
|
end
|
350
350
|
```
|
351
351
|
|
352
|
-
|
352
|
+
You can also disable automatic synchronization for the duration of a block:
|
353
|
+
|
354
|
+
```ruby
|
355
|
+
Capybara::Lockstep.with_mode(:manual) do
|
356
|
+
do_unsynchronized_work
|
357
|
+
end
|
358
|
+
```
|
359
|
+
|
360
|
+
In the `:manual` mode you may still force synchronization by calling `Capybara::Lockstep.synchronize` manually:
|
361
|
+
|
362
|
+
```ruby
|
363
|
+
Capybara::Lockstep.with_mode(:manual) do
|
364
|
+
do_some_work
|
365
|
+
Capybara::Lockstep.synchronize
|
366
|
+
do_other_work
|
367
|
+
end
|
368
|
+
```
|
353
369
|
|
354
370
|
To completely disable synchronization, even when `Capybara::Lockstep.synchronize` is called:
|
355
371
|
|
@@ -360,6 +376,8 @@ Capybara::Lockstep.synchronize # will not synchronize
|
|
360
376
|
|
361
377
|
|
362
378
|
|
379
|
+
|
380
|
+
|
363
381
|
## Handling legacy promises
|
364
382
|
|
365
383
|
Legacy promise implementations (like jQuery's `$.Deferred` and AngularJS' `$q`) work using [tasks instead of microtasks](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/). Their AJAX implementations (like `$.ajax()` and `$http`) use task-based promises to signal that a request is done.
|
@@ -377,7 +395,7 @@ It is theoretically possible that your test will observe the browser in that win
|
|
377
395
|
Any issues caused by this will usually be mitigated by Capybara's retry logic. **If** you think that this is an issue for your test suite, you can configure capybara-headless to wait additional tasks before it considers the browser to be idle:
|
378
396
|
|
379
397
|
```ruby
|
380
|
-
Capybara::Lockstep.wait_tasks = 2
|
398
|
+
Capybara::Lockstep.wait_tasks = 2 # default is 1
|
381
399
|
```
|
382
400
|
|
383
401
|
If you see longer chains of `then()` or nested `setTimeout()` calls in your code, you may need to configure a higher number of tasks to wait.
|
@@ -4,14 +4,14 @@ window.CapybaraLockstep = (function() {
|
|
4
4
|
let jobCount
|
5
5
|
let idleCallbacks
|
6
6
|
let finishedWorkTags
|
7
|
-
let
|
7
|
+
let defaultWaitTasks
|
8
8
|
reset()
|
9
9
|
|
10
10
|
function reset() {
|
11
11
|
jobCount = 0
|
12
12
|
idleCallbacks = []
|
13
13
|
finishedWorkTags = []
|
14
|
-
|
14
|
+
defaultWaitTasks = 1
|
15
15
|
debug = false
|
16
16
|
}
|
17
17
|
|
@@ -57,8 +57,9 @@ window.CapybaraLockstep = (function() {
|
|
57
57
|
promise.then(taggedStopWork, taggedStopWork)
|
58
58
|
}
|
59
59
|
|
60
|
-
function stopWork(tag) {
|
61
|
-
|
60
|
+
function stopWork(tag, waitAdditionalTasks = 0) {
|
61
|
+
let effectiveWaitTasks = defaultWaitTasks + waitAdditionalTasks
|
62
|
+
afterWaitTasks(stopWorkNow.bind(this, tag), effectiveWaitTasks)
|
62
63
|
}
|
63
64
|
|
64
65
|
function stopWorkNow(tag) {
|
@@ -92,6 +93,27 @@ window.CapybaraLockstep = (function() {
|
|
92
93
|
}
|
93
94
|
}
|
94
95
|
|
96
|
+
function trackHistory() {
|
97
|
+
// Wait an additional task because some browsers seem to require additional
|
98
|
+
// time before the URL changes.
|
99
|
+
trackEvent(document, 'popstate', 1)
|
100
|
+
trackEvent(document, 'hashchange', 1)
|
101
|
+
|
102
|
+
// API: https://developer.mozilla.org/en-US/docs/Web/API/History
|
103
|
+
for (let method of ['pushState', 'popState', 'forward', 'back', 'go']) {
|
104
|
+
let workTag = `history.${method}()`
|
105
|
+
let nativeImpl = history[method]
|
106
|
+
history[method] = function(...args) {
|
107
|
+
try {
|
108
|
+
startWork(workTag)
|
109
|
+
return nativeImpl.apply(history, args)
|
110
|
+
} finally {
|
111
|
+
stopWork(workTag, 1)
|
112
|
+
}
|
113
|
+
}
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
95
117
|
function trackXHR() {
|
96
118
|
let oldOpen = XMLHttpRequest.prototype.open
|
97
119
|
let oldSend = XMLHttpRequest.prototype.send
|
@@ -135,7 +157,7 @@ window.CapybaraLockstep = (function() {
|
|
135
157
|
// CapybaraLockstep.track() is called as the first script in the head.
|
136
158
|
// jQuery will be loaded after us, so we wait until DOMContentReady.
|
137
159
|
whenReady(function() {
|
138
|
-
if (!window.jQuery ||
|
160
|
+
if (!window.jQuery || defaultWaitTasks > 0) {
|
139
161
|
return
|
140
162
|
}
|
141
163
|
|
@@ -255,9 +277,12 @@ window.CapybaraLockstep = (function() {
|
|
255
277
|
}
|
256
278
|
}
|
257
279
|
|
258
|
-
function afterWaitTasks(fn,
|
259
|
-
if (
|
260
|
-
|
280
|
+
function afterWaitTasks(fn, waitTasks = defaultWaitTasks) {
|
281
|
+
if (waitTasks > 0) {
|
282
|
+
// Wait 1 task and recurse
|
283
|
+
setTimeout(function() {
|
284
|
+
afterWaitTasks(fn, waitTasks - 1)
|
285
|
+
})
|
261
286
|
} else {
|
262
287
|
fn()
|
263
288
|
}
|
@@ -279,14 +304,16 @@ window.CapybaraLockstep = (function() {
|
|
279
304
|
})
|
280
305
|
}
|
281
306
|
|
282
|
-
function
|
283
|
-
|
307
|
+
function trackEvent(eventTarget, eventType, waitAdditionalTasks = 0) {
|
308
|
+
eventTarget.addEventListener(eventType, function() {
|
284
309
|
// Only litter the log with interaction events if we're actually going
|
285
310
|
// to be busy for at least 1 task.
|
286
|
-
|
311
|
+
let effectiveWaitTasks = defaultWaitTasks + waitAdditionalTasks
|
312
|
+
|
313
|
+
if (effectiveWaitTasks > 0) {
|
287
314
|
let tag = eventType
|
288
315
|
startWork(tag)
|
289
|
-
stopWork(tag)
|
316
|
+
stopWork(tag, waitAdditionalTasks)
|
290
317
|
}
|
291
318
|
})
|
292
319
|
}
|
@@ -294,17 +321,19 @@ window.CapybaraLockstep = (function() {
|
|
294
321
|
function track() {
|
295
322
|
trackOldUnpoly()
|
296
323
|
trackFetch()
|
324
|
+
trackHistory()
|
297
325
|
trackXHR()
|
298
326
|
trackRemoteElements()
|
299
327
|
trackJQuery()
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
328
|
+
trackEvent(document, 'touchstart')
|
329
|
+
trackEvent(document, 'mousedown')
|
330
|
+
trackEvent(document, 'click')
|
331
|
+
trackEvent(document, 'keydown')
|
332
|
+
trackEvent(document, 'focusin')
|
333
|
+
trackEvent(document, 'focusout')
|
334
|
+
trackEvent(document, 'input')
|
335
|
+
trackEvent(document, 'change')
|
336
|
+
trackEvent(window, 'resize', 1)
|
308
337
|
}
|
309
338
|
|
310
339
|
function synchronize(callback) {
|
@@ -324,7 +353,7 @@ window.CapybaraLockstep = (function() {
|
|
324
353
|
synchronize: synchronize,
|
325
354
|
reset: reset,
|
326
355
|
set debug(value) { debug = value },
|
327
|
-
set waitTasks(value) {
|
356
|
+
set waitTasks(value) { defaultWaitTasks = value }
|
328
357
|
}
|
329
358
|
})()
|
330
359
|
|
@@ -3,10 +3,10 @@ module Capybara
|
|
3
3
|
module Helper
|
4
4
|
|
5
5
|
JS_PATH = File.expand_path('../helper.js', __FILE__)
|
6
|
-
|
6
|
+
HELPER_JS = IO.read(JS_PATH)
|
7
7
|
|
8
|
-
def capybara_lockstep_js
|
9
|
-
|
8
|
+
def capybara_lockstep_js(options = {})
|
9
|
+
HELPER_JS + capybara_lockstep_config_js(options)
|
10
10
|
end
|
11
11
|
|
12
12
|
def capybara_lockstep(options = {})
|
@@ -17,10 +17,11 @@ module Capybara
|
|
17
17
|
tag_options[:nonce] = options.fetch(:nonce, true)
|
18
18
|
end
|
19
19
|
|
20
|
-
|
21
|
-
javascript_tag(js, tag_options)
|
20
|
+
javascript_tag(capybara_lockstep_js(options), tag_options)
|
22
21
|
end
|
23
22
|
|
23
|
+
private
|
24
|
+
|
24
25
|
def capybara_lockstep_config_js(options = {})
|
25
26
|
js = ''
|
26
27
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capybara-lockstep
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Henning Koch
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: capybara
|