Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
81152 views
1
var mocks = require('mocks');
2
3
var timers = {};
4
// Keep a fake timestamp
5
// move on the time when runTimersToTime() is called
6
var now = 0;
7
8
// add a timer of type either 'timeout' or 'interval'
9
function _setTimer(type, callback, delay) {
10
var token = null;
11
do {
12
token = Math.floor(Math.random() * 4294967296) + 1;
13
} while (timers[token]);
14
timers[token] = {
15
type: type,
16
callback: callback,
17
// Add some random msecs to the delay to mimic code execution time.
18
time: now + delay + Math.floor(Math.random() * 5),
19
interval: (type == 'interval' ? delay : 0)
20
};
21
return token;
22
}
23
24
// clear a timer of type either 'timeout' or 'interval'
25
function _clearTimer(type, token) {
26
if (timers[token] && timers[token].type == type) {
27
delete timers[token];
28
}
29
}
30
31
function _setTimeout(callback, delay) {
32
return _setTimer('timeout', callback, delay);
33
}
34
35
function _setInterval(callback, delay) {
36
return _setTimer('interval', callback, delay);
37
}
38
39
function _clearTimeout(token) {
40
_clearTimer('timeout', token);
41
}
42
43
function _clearInterval(token) {
44
_clearTimer('interval', token);
45
}
46
47
// Run timer of given token
48
function _runTimer(token) {
49
// Skip non-existing token
50
if (timers[token]) {
51
if (timers[token].type == 'timeout') {
52
// for 'timeout', run callback and delete the timer
53
var callback = timers[token].callback;
54
delete timers[token];
55
callback();
56
} else if (timers[token].type == 'interval') {
57
// for 'interval', run callback and set the next invoke time
58
// Add some random msecs to the delay to mimic code execution time.
59
timers[token].time =
60
now + timers[token].interval + Math.floor(Math.random() * 5);
61
timers[token].callback();
62
}
63
}
64
}
65
66
function _runTimersOnce() {
67
// Invoke all timers once regardsless of the delay
68
for (var token in timers) {
69
_runTimer(token);
70
}
71
}
72
73
function _runTimersToTime(delay) {
74
var toRunToken = _getNextTimerToken();
75
if (!toRunToken) {
76
return;
77
}
78
79
var minTime = timers[toRunToken].time;
80
if (now + delay < minTime) {
81
// Termination when there's no more timers to invoke
82
now += delay;
83
} else {
84
// Recursively invoke the next to-run timer
85
delay -= (minTime - now);
86
now = minTime;
87
_runTimer(toRunToken);
88
_runTimersToTime(delay);
89
}
90
}
91
92
function _runTimersRepeatedly() {
93
// Only run a generous 1000 timers and then bail, since we may have entered
94
// a loop if we have more than that.
95
var max_timers = 1000;
96
97
var token;
98
for (var ii = 0; ii < max_timers; ii++) {
99
token = _getNextTimerToken();
100
101
if (!token) {
102
break;
103
}
104
105
_runTimer(token);
106
}
107
108
if (ii === max_timers) {
109
throw new Error("More timers still exist after " + max_timers + " timers!");
110
}
111
}
112
113
function _clearTimers() {
114
for (var token in timers) {
115
delete timers[token];
116
}
117
}
118
119
function _getNextTimerToken() {
120
var nextTimerToken = null;
121
var minTime = 31536000000; // One year
122
// Find the next to invoke timer
123
for (var token in timers) {
124
if (timers[token].time < minTime) {
125
nextTimerToken = token;
126
minTime = timers[token].time;
127
}
128
}
129
return nextTimerToken;
130
}
131
132
var mockTimers = {
133
setTimeout: _setTimeout,
134
clearTimeout: _clearTimeout,
135
setInterval: _setInterval,
136
clearInterval: _clearInterval,
137
138
/**
139
* Copyright 2013-2014, Facebook, Inc.
140
* All rights reserved.
141
*
142
* This source code is licensed under the BSD-style license found in the
143
* LICENSE file in the root directory of this source tree. An additional grant
144
* of patent rights can be found in the PATENTS file in the same directory.
145
*
146
* Iteratively run callbacks in time order during the time from now to
147
* now + delay.
148
* If one callback register another timer which should be run during now to
149
* now + delay, the new timer will also be run in the right order.
150
*
151
* @param delay
152
*/
153
runTimersToTime: _runTimersToTime,
154
155
/**
156
* Run all registered timer once. Newly registered timers will not be run.
157
*/
158
runTimersOnce: _runTimersOnce,
159
160
/**
161
* Iteratively run callbacks until there are no timers left to call. Will
162
* stop after a maximum number of iterations to avoid infinite loop.
163
*
164
* @param maximum iterations (optional)
165
*/
166
runTimersRepeatedly: _runTimersRepeatedly,
167
168
/**
169
* Clear all timers
170
*/
171
clearTimers: _clearTimers,
172
173
/**
174
* Get the number of remaining timers
175
*/
176
getTimersCount: function() {
177
return Object.keys(timers).length;
178
}
179
};
180
181
module.exports.installMockTimers = function(window) {
182
window._originalTimeouts = {
183
setTimeout: window.setTimeout,
184
clearTimeout: window.clearTimeout,
185
setInterval: window.setInterval,
186
clearInterval: window.clearInterval
187
};
188
window.setTimeout =
189
mocks.getMockFunction().mockImplementation(mockTimers.setTimeout);
190
window.clearTimeout =
191
mocks.getMockFunction().mockImplementation(mockTimers.clearTimeout);
192
window.setInterval =
193
mocks.getMockFunction().mockImplementation(mockTimers.setInterval);
194
window.clearInterval =
195
mocks.getMockFunction().mockImplementation(mockTimers.clearInterval);
196
window.mockRunTimersOnce =
197
mocks.getMockFunction().mockImplementation(mockTimers.runTimersOnce);
198
window.mockRunTimersToTime =
199
mocks.getMockFunction().mockImplementation(mockTimers.runTimersToTime);
200
window.mockRunTimersRepeatedly =
201
mocks.getMockFunction().mockImplementation(mockTimers.runTimersRepeatedly);
202
window.mockClearTimers =
203
mocks.getMockFunction().mockImplementation(mockTimers.clearTimers);
204
window.mockGetTimersCount =
205
mocks.getMockFunction().mockImplementation(mockTimers.getTimersCount);
206
};
207
208
module.exports.uninstallMockTimers = function(window) {
209
window.setTimeout = window._originalTimeouts.setTimeout;
210
window.clearTimeout = window._originalTimeouts.clearTimeout;
211
window.setInterval = window._originalTimeouts.setInterval;
212
window.clearInterval = window._originalTimeouts.clearInterval;
213
window._originalTimeouts = undefined;
214
window.mockRunTimersOnce = undefined;
215
window.mockRunTimersToTime = undefined;
216
window.mockRunTimersRepeatedly = undefined;
217
window.mockClearTimers = undefined;
218
window.mockGetTimersCount = undefined;
219
};
220
221