Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set timeout promise support #227

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/lolex-src.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ function withGlobal(_global) {
var addTimerReturnsObject = typeof timeoutResult === "object";
var hrtimePresent = (_global.process && typeof _global.process.hrtime === "function");
var nextTickPresent = (_global.process && typeof _global.process.nextTick === "function");
var nodeUtil = (_global.process && typeof require === "function" && require("util"));
var symbolUtilPromisifyCustom = nodeUtil && nodeUtil.promisify && nodeUtil.promisify.custom;
var performancePresent = (_global.performance && typeof _global.performance.now === "function");
var hasPerformancePrototype = (_global.Performance && (typeof _global.Performance).match(/^(function|object)$/));
var queueMicrotaskPresent = (typeof _global.queueMicrotask === "function");
Expand Down Expand Up @@ -568,6 +570,13 @@ function withGlobal(_global) {
delay: timeout
});
};
if (symbolUtilPromisifyCustom) {
clock.setTimeout[symbolUtilPromisifyCustom] = function (delay) {
return new _global.Promise(function (resolve) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you store a reference to Promise at initialization time? Would help in Jest in the cases where people mess with globals

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, can you elaborate on that?

Copy link
Member

@SimenB SimenB Mar 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

People have tests that do

global.Promise = undefined

inside of their test. It would be great to be resilient to that by grabbing a copy of the original Promise early. Use case being to test how their code behaves without promises available

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SimenB You're basically just saying that lolex should do something like this, right?

// needed not to break in case people null out the `Promise` property in user-code
var originalPromise = _global.Promise;

And then reference that when using Promises internally.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes 🙂

return clock.setTimeout(resolve, delay);
});
};
}

clock.clearTimeout = function clearTimeout(timerId) {
return clearTimer(clock, timerId, "Timeout");
Expand Down
50 changes: 38 additions & 12 deletions test/lolex-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ var GlobalDate = Date;
var NOOP = function NOOP() { return undefined; };
var nextTickPresent = (global.process && typeof global.process.nextTick === "function");
var queueMicrotaskPresent = (typeof global.queueMicrotask === "function");
var utilPromisify = (global.process && typeof require === "function" && require("util") && require("util").promisify);
var hrtimePresent = (global.process && typeof global.process.hrtime === "function");
var performanceNowPresent = (global.performance && typeof global.performance.now === "function");
var performanceMarkPresent = (global.performance && typeof global.performance.mark === "function");
Expand Down Expand Up @@ -206,13 +207,10 @@ describe("lolex", function () {

describe("setTimeout", function () {

var evalCalled;
beforeEach(function () {
this.clock = lolex.createClock();
lolex.evalCalled = false;
});

afterEach(function () {
delete lolex.evalCalled;
evalCalled = false;
});

it("throws if no arguments", function () {
Expand Down Expand Up @@ -252,24 +250,28 @@ describe("lolex", function () {
});

it("parses numeric string times", function () {
this.clock.setTimeout(function () { lolex.evalCalled = true; }, "10");
this.clock.setTimeout(function () { evalCalled = true; }, "10");
this.clock.tick(10);

assert(lolex.evalCalled);
assert(evalCalled);
});

it("parses no-numeric string times", function () {
this.clock.setTimeout(function () { lolex.evalCalled = true; }, "string");
this.clock.setTimeout(function () { evalCalled = true; }, "string");
this.clock.tick(10);

assert(lolex.evalCalled);
assert(evalCalled);
});

it("evals non-function callbacks", function () {
this.clock.setTimeout("lolex.evalCalled = true", 10);
global.evalFn = function () {
evalCalled = true;
};
this.clock.setTimeout("evalFn()", 10);
this.clock.tick(10);

assert(lolex.evalCalled);
assert(evalCalled);
delete global.evalFn;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete this before the assertion so that it's guaranteed to get called. If the assertion above fails, this won't be cleaned up.

});

it("passes setTimeout parameters", function () {
Expand Down Expand Up @@ -393,6 +395,17 @@ describe("lolex", function () {
this.clock.runAll();
assert.equals(calls, ["NaN", "Infinity", "-Infinity"]);
});
it("Handles promisification of setTimeout", function () {
if (!utilPromisify) {
this.skip();
}
var timeout = utilPromisify(this.clock.setTimeout);
return global.Promise.resolve().then(function () {
var p1 = timeout(1e6);
this.clock.tick(1e6);
return p1;
}.bind(this));
});
});

describe("setImmediate", function () {
Expand Down Expand Up @@ -1922,6 +1935,19 @@ describe("lolex", function () {
}
});

it("global fake setTimeout with util promisify should work", function () {
if (!utilPromisify) {
this.skip();
}
this.clock = lolex.install();
var delay = utilPromisify(setTimeout);
return global.Promise.resolve().then(function () {
var p = delay(1e6);
this.clock.tick(1e6);
return p;
}.bind(this));
});

it("global fake setTimeout().unref() should return timer", function () {
this.clock = lolex.install();
var stub = sinon.stub();
Expand Down Expand Up @@ -2545,7 +2571,7 @@ describe("lolex", function () {
});
it("runs with timers and before them", function () {
var last = "";
clock.runMicrotasks(function () {
clock.queueMicrotask(function () {
called = true;
last = "tick";
});
Expand Down