Mailspring/spec/n1-spec-runner/time-override.coffee
2016-10-16 20:10:19 -07:00

101 lines
2.8 KiB
CoffeeScript

_ = require 'underscore'
# Public: To make specs easier to test, we make all asynchronous behavior
# actually synchronous. We do this by overriding all global timeout and
# Promise functions.
#
# You must now manually call `advanceClock()` in order to move the "clock"
# forward.
class TimeOverride
@advanceClock = (delta=1) =>
@now += delta
callbacks = []
@timeouts ?= []
@timeouts = @timeouts.filter ([id, strikeTime, callback]) =>
if strikeTime <= @now
callbacks.push(callback)
false
else
true
callback() for callback in callbacks
@resetTime = =>
@now = 0
@timeoutCount = 0
@intervalCount = 0
@timeouts = []
@intervalTimeouts = {}
@originalPromiseScheduler = null
@enableSpies = =>
window.advanceClock = @advanceClock
window.originalSetInterval = window.setInterval
spyOn(window, "setTimeout").andCallFake @_fakeSetTimeout
spyOn(window, "clearTimeout").andCallFake @_fakeClearTimeout
spyOn(window, "setInterval").andCallFake @_fakeSetInterval
spyOn(window, "clearInterval").andCallFake @_fakeClearInterval
spyOn(_._, "now").andCallFake => @now
# spyOn(Date, "now").andCallFake => @now
# spyOn(Date.prototype, "getTime").andCallFake => @now
@_setPromiseScheduler()
@_setPromiseScheduler: =>
# Make Bluebird use setTimeout so that it hooks into our stubs, and you
# can advance promises using `advanceClock()`. To avoid breaking any
# specs that `dont` manually call advanceClock, call it automatically on
# the next tick.
@originalPromiseScheduler ?= Promise.setScheduler (fn) =>
setTimeout(fn, 0)
process.nextTick =>
@advanceClock(1)
@disableSpies = =>
window.advanceClock = null
jasmine.unspy(window, 'setTimeout')
jasmine.unspy(window, 'clearTimeout')
jasmine.unspy(window, 'setInterval')
jasmine.unspy(window, 'clearInterval')
jasmine.unspy(_._, "now")
Promise.setScheduler(@originalPromiseScheduler) if @originalPromiseScheduler
@originalPromiseScheduler = null
@resetSpyData = ->
window.setTimeout.reset?()
window.clearTimeout.reset?()
window.setInterval.reset?()
window.clearInterval.reset?()
Date.now.reset?()
Date.prototype.getTime.reset?()
@_fakeSetTimeout = (callback, ms) =>
id = ++@timeoutCount
@timeouts.push([id, @now + ms, callback])
id
@_fakeClearTimeout = (idToClear) =>
@timeouts ?= []
@timeouts = @timeouts.filter ([id]) -> id != idToClear
@_fakeSetInterval = (callback, ms) =>
id = ++@intervalCount
action = =>
callback()
@intervalTimeouts[id] = @_fakeSetTimeout(action, ms)
@intervalTimeouts[id] = @_fakeSetTimeout(action, ms)
id
@_fakeClearInterval = (idToClear) =>
@_fakeClearTimeout(@intervalTimeouts[idToClear])
module.exports = TimeOverride