123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635 |
- goog.setTestOnly('goog.testing.MockClock');
- goog.provide('goog.testing.MockClock');
- goog.require('goog.Disposable');
- goog.require('goog.Promise');
- goog.require('goog.Thenable');
- goog.require('goog.async.run');
- goog.require('goog.testing.PropertyReplacer');
- goog.require('goog.testing.events');
- goog.require('goog.testing.events.Event');
- goog.testing.MockClock = function(opt_autoInstall) {
- goog.Disposable.call(this);
-
- this.queue_ = [];
-
- this.deletedKeys_ = {};
- if (opt_autoInstall) {
- this.install();
- }
- };
- goog.inherits(goog.testing.MockClock, goog.Disposable);
- goog.testing.MockClock.REQUEST_ANIMATION_FRAME_TIMEOUT = 20;
- goog.testing.MockClock.nextId = Math.round(Math.random() * 10000);
- goog.testing.MockClock.prototype.timeoutsMade_ = 0;
- goog.testing.MockClock.prototype.callbacksTriggered_ = 0;
- goog.testing.MockClock.prototype.replacer_ = null;
- goog.testing.MockClock.prototype.nowMillis_ = 0;
- goog.testing.MockClock.prototype.timeoutDelay_ = 0;
- goog.testing.MockClock.REAL_SETTIMEOUT_ = goog.global.setTimeout;
- goog.testing.MockClock.prototype.install = function() {
- if (!this.replacer_) {
- if (goog.testing.MockClock.REAL_SETTIMEOUT_ !== goog.global.setTimeout) {
- if (typeof console !== 'undefined' && console.warn) {
- console.warn(
- 'Non default setTimeout detected. ' +
- 'Use of multiple MockClock instances or other clock mocking ' +
- 'should be avoided due to unspecified behavior and ' +
- 'the resulting fragility.');
- }
- }
- var r = this.replacer_ = new goog.testing.PropertyReplacer();
- r.set(goog.global, 'setTimeout', goog.bind(this.setTimeout_, this));
- r.set(goog.global, 'setInterval', goog.bind(this.setInterval_, this));
- r.set(goog.global, 'setImmediate', goog.bind(this.setImmediate_, this));
- r.set(goog.global, 'clearTimeout', goog.bind(this.clearTimeout_, this));
- r.set(goog.global, 'clearInterval', goog.bind(this.clearInterval_, this));
-
-
-
-
-
-
- goog.async.run.forceNextTick &&
- goog.async.run.forceNextTick(goog.testing.MockClock.REAL_SETTIMEOUT_);
-
- this.replaceRequestAnimationFrame_();
-
- this.oldGoogNow_ = goog.now;
- goog.now = goog.bind(this.getCurrentTime, this);
- }
- };
- goog.testing.MockClock.prototype.replaceRequestAnimationFrame_ = function() {
- var r = this.replacer_;
- var requestFuncs = [
- 'requestAnimationFrame', 'webkitRequestAnimationFrame',
- 'mozRequestAnimationFrame', 'oRequestAnimationFrame',
- 'msRequestAnimationFrame'
- ];
- var cancelFuncs = [
- 'cancelAnimationFrame', 'cancelRequestAnimationFrame',
- 'webkitCancelRequestAnimationFrame', 'mozCancelRequestAnimationFrame',
- 'oCancelRequestAnimationFrame', 'msCancelRequestAnimationFrame'
- ];
- for (var i = 0; i < requestFuncs.length; ++i) {
- if (goog.global && goog.global[requestFuncs[i]]) {
- r.set(
- goog.global, requestFuncs[i],
- goog.bind(this.requestAnimationFrame_, this));
- }
- }
- for (var i = 0; i < cancelFuncs.length; ++i) {
- if (goog.global && goog.global[cancelFuncs[i]]) {
- r.set(
- goog.global, cancelFuncs[i],
- goog.bind(this.cancelRequestAnimationFrame_, this));
- }
- }
- };
- goog.testing.MockClock.prototype.uninstall = function() {
- if (this.replacer_) {
- this.replacer_.reset();
- this.replacer_ = null;
- goog.now = this.oldGoogNow_;
- }
- this.resetAsyncQueue_();
- };
- goog.testing.MockClock.prototype.disposeInternal = function() {
- this.uninstall();
- this.queue_ = null;
- this.deletedKeys_ = null;
- goog.testing.MockClock.superClass_.disposeInternal.call(this);
- };
- goog.testing.MockClock.prototype.reset = function() {
- this.queue_ = [];
- this.deletedKeys_ = {};
- this.nowMillis_ = 0;
- this.timeoutsMade_ = 0;
- this.callbacksTriggered_ = 0;
- this.timeoutDelay_ = 0;
- this.resetAsyncQueue_();
- };
- goog.testing.MockClock.prototype.resetAsyncQueue_ = function() {
- goog.async.run.resetQueue();
- };
- goog.testing.MockClock.prototype.setTimeoutDelay = function(delay) {
- this.timeoutDelay_ = delay;
- };
- goog.testing.MockClock.prototype.getTimeoutDelay = function() {
- return this.timeoutDelay_;
- };
- goog.testing.MockClock.prototype.tick = function(opt_millis) {
- if (typeof opt_millis != 'number') {
- opt_millis = 1;
- }
- var endTime = this.nowMillis_ + opt_millis;
- this.runFunctionsWithinRange_(endTime);
- this.nowMillis_ = endTime;
- return endTime;
- };
- goog.testing.MockClock.prototype.tickPromise = function(promise, opt_millis) {
- var value;
- var error;
- var resolved = false;
- promise.then(
- function(v) {
- value = v;
- resolved = true;
- },
- function(e) {
- error = e;
- resolved = true;
- });
- this.tick(opt_millis);
- if (!resolved) {
- throw new Error(
- 'Promise was expected to be resolved after mock clock tick.');
- }
- if (error) {
- throw error;
- }
- return value;
- };
- goog.testing.MockClock.prototype.getTimeoutsMade = function() {
- return this.timeoutsMade_;
- };
- goog.testing.MockClock.prototype.getCallbacksTriggered = function() {
- return this.callbacksTriggered_;
- };
- goog.testing.MockClock.prototype.getCurrentTime = function() {
- return this.nowMillis_;
- };
- goog.testing.MockClock.prototype.isTimeoutSet = function(timeoutKey) {
- return timeoutKey < goog.testing.MockClock.nextId &&
- timeoutKey >= goog.testing.MockClock.nextId - this.timeoutsMade_ &&
- !this.deletedKeys_[timeoutKey];
- };
- goog.testing.MockClock.prototype.runFunctionsWithinRange_ = function(endTime) {
- var adjustedEndTime = endTime - this.timeoutDelay_;
-
- while (this.queue_ && this.queue_.length &&
- this.queue_[this.queue_.length - 1].runAtMillis <= adjustedEndTime) {
- var timeout = this.queue_.pop();
- if (!(timeout.timeoutKey in this.deletedKeys_)) {
-
- this.nowMillis_ =
- Math.max(this.nowMillis_, timeout.runAtMillis + this.timeoutDelay_);
-
- this.callbacksTriggered_++;
- timeout.funcToCall.call(goog.global, timeout.timeoutKey);
-
- if (timeout.recurring) {
- this.scheduleFunction_(
- timeout.timeoutKey, timeout.funcToCall, timeout.millis, true);
- }
- }
- }
- };
- goog.testing.MockClock.prototype.scheduleFunction_ = function(
- timeoutKey, funcToCall, millis, recurring) {
- if (!goog.isFunction(funcToCall)) {
-
- throw new TypeError(
- 'The provided callback must be a function, not a ' + typeof funcToCall);
- }
- var timeout = {
- runAtMillis: this.nowMillis_ + millis,
- funcToCall: funcToCall,
- recurring: recurring,
- timeoutKey: timeoutKey,
- millis: millis
- };
- goog.testing.MockClock.insert_(timeout, this.queue_);
- };
- goog.testing.MockClock.insert_ = function(timeout, queue) {
-
-
-
-
-
-
-
- for (var i = queue.length; i != 0; i--) {
- if (queue[i - 1].runAtMillis > timeout.runAtMillis) {
- break;
- }
- queue[i] = queue[i - 1];
- }
- queue[i] = timeout;
- };
- goog.testing.MockClock.MAX_INT_ = 2147483647;
- goog.testing.MockClock.prototype.setTimeout_ = function(
- funcToCall, opt_millis) {
- var millis = opt_millis || 0;
- if (millis > goog.testing.MockClock.MAX_INT_) {
- throw Error(
- 'Bad timeout value: ' + millis + '. Timeouts over MAX_INT ' +
- '(24.8 days) cause timeouts to be fired ' +
- 'immediately in most browsers, except for IE.');
- }
- this.timeoutsMade_++;
- this.scheduleFunction_(
- goog.testing.MockClock.nextId, funcToCall, millis, false);
- return goog.testing.MockClock.nextId++;
- };
- goog.testing.MockClock.prototype.setInterval_ = function(
- funcToCall, opt_millis) {
- var millis = opt_millis || 0;
- this.timeoutsMade_++;
- this.scheduleFunction_(
- goog.testing.MockClock.nextId, funcToCall, millis, true);
- return goog.testing.MockClock.nextId++;
- };
- goog.testing.MockClock.prototype.requestAnimationFrame_ = function(funcToCall) {
- return this.setTimeout_(goog.bind(function() {
- if (funcToCall) {
- funcToCall(this.getCurrentTime());
- } else if (goog.global.mozRequestAnimationFrame) {
- var event = new goog.testing.events.Event('MozBeforePaint', goog.global);
- event['timeStamp'] = this.getCurrentTime();
- goog.testing.events.fireBrowserEvent(event);
- }
- }, this), goog.testing.MockClock.REQUEST_ANIMATION_FRAME_TIMEOUT);
- };
- goog.testing.MockClock.prototype.setImmediate_ = function(funcToCall) {
- return this.setTimeout_(funcToCall, 0);
- };
- goog.testing.MockClock.prototype.clearTimeout_ = function(timeoutKey) {
-
-
-
-
-
-
-
-
-
-
-
- if (this.isTimeoutSet(timeoutKey)) {
- this.deletedKeys_[timeoutKey] = true;
- }
- };
- goog.testing.MockClock.prototype.clearInterval_ = function(timeoutKey) {
- this.clearTimeout_(timeoutKey);
- };
- goog.testing.MockClock.prototype.cancelRequestAnimationFrame_ = function(
- timeoutKey) {
- this.clearTimeout_(timeoutKey);
- };
|