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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 495d3ed978e831569eb691423ab97e79b4a354e415ce7247c7fba01916bce60a
4
- data.tar.gz: bb51f4acfbd6cbe7b19f3e326d7e8d771004babe1ed415ca9f283c1301822ac9
3
+ metadata.gz: 514789431b5b017176575acd43c1a5b6558040f31cf7cb4ac119cf10e756dbee
4
+ data.tar.gz: 2945ac3b32b7f83a7bc2bd14848f67950c12e5063033d8dbe2063788dfe8c024
5
5
  SHA512:
6
- metadata.gz: aeb726459feb3f529e02bc8cc5d8c8cd5afe2377d7906ff5e78485137770ad851cfa7e9a175a3f9ff59bbf2deb4a8fc0d14a06af584928e552a8d25bba3ddc43
7
- data.tar.gz: 8f6955613d8a1073dcfeb26d003a22c0694462bdbab917ae66f31b11bbca2af36d5164394e4eafd18157b57d5684d7c9ae2afce4c0693230f91aca7c532d8528
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- capybara-lockstep (2.0.2)
4
+ capybara-lockstep (2.1.0)
5
5
  activesupport (>= 4.2)
6
6
  capybara (>= 3.0)
7
7
  ruby2_keywords
data/README.md CHANGED
@@ -349,7 +349,23 @@ ensure
349
349
  end
350
350
  ```
351
351
 
352
- In the `:manual` mode you may still force synchronization by calling `Capybara::Lockstep.synchronize` manually.
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 // default is 1
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.
@@ -58,7 +58,7 @@ module Capybara
58
58
  self.mode = temporary_mode
59
59
  block.call
60
60
  ensure
61
- self.mode = temporary_mode
61
+ self.mode = old_mode
62
62
  end
63
63
 
64
64
  def enabled=(enabled)
@@ -4,14 +4,14 @@ window.CapybaraLockstep = (function() {
4
4
  let jobCount
5
5
  let idleCallbacks
6
6
  let finishedWorkTags
7
- let waitTasks
7
+ let defaultWaitTasks
8
8
  reset()
9
9
 
10
10
  function reset() {
11
11
  jobCount = 0
12
12
  idleCallbacks = []
13
13
  finishedWorkTags = []
14
- waitTasks = 1
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
- afterWaitTasks(stopWorkNow.bind(this, tag))
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 || waitTasks > 0) {
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, tasksLeft = waitTasks) {
259
- if (tasksLeft > 0) {
260
- afterWaitTasks(fn, tasksLeft - 1)
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 trackInteraction(eventType) {
283
- document.addEventListener(eventType, function() {
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
- if (waitTasks > 0) {
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
- trackInteraction('touchstart')
301
- trackInteraction('mousedown')
302
- trackInteraction('click')
303
- trackInteraction('keydown')
304
- trackInteraction('focusin')
305
- trackInteraction('focusout')
306
- trackInteraction('input')
307
- trackInteraction('change')
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) { 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
- JS = IO.read(JS_PATH)
6
+ HELPER_JS = IO.read(JS_PATH)
7
7
 
8
- def capybara_lockstep_js
9
- JS
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
- js = capybara_lockstep_js + capybara_lockstep_config_js(options)
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
 
@@ -1,5 +1,5 @@
1
1
  module Capybara
2
2
  module Lockstep
3
- VERSION = "2.0.2"
3
+ VERSION = "2.1.0"
4
4
  end
5
5
  end
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.2
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: 2023-12-22 00:00:00.000000000 Z
11
+ date: 2024-01-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capybara