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

chore(tests): don't rely on jest fake timers scheduling real timers #14003

Merged
merged 2 commits into from
Nov 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,8 @@ describe('ReactDOMSuspensePlaceholder', () => {
}
jest.advanceTimersByTime(ms);
// Wait until the end of the current tick
return new Promise(resolve => {
setImmediate(resolve);
});
// We cannot use a timer since we're faking them
return Promise.resolve().then(() => {});
}

function Text(props) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}
jest.advanceTimersByTime(ms);
// Wait until the end of the current tick
return new Promise(resolve => {
setImmediate(resolve);
});
// We cannot use a timer since we're faking them
return Promise.resolve().then(() => {});
}

function Text(props) {
Expand Down
5 changes: 2 additions & 3 deletions packages/react/src/__tests__/ReactProfiler-test.internal.js
Original file line number Diff line number Diff line change
Expand Up @@ -2194,9 +2194,8 @@ describe('Profiler', () => {
function awaitableAdvanceTimers(ms) {
jest.advanceTimersByTime(ms);
// Wait until the end of the current tick
return new Promise(resolve => {
setImmediate(resolve);
});
// We cannot use a timer since we're faking them
return Promise.resolve().then(() => {});
}

it('traces both the temporary placeholder and the finished render for an interaction', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,7 @@ let ReactCache;
function initEnvForAsyncTesting() {
// Boilerplate copied from ReactDOMRoot-test
// TODO pull this into helper method, reduce repetition.
const originalDateNow = Date.now;
global.Date.now = function() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Lolex will fake this.

The test also passed when removing it when using Jest 23, not sure what it was supposed to do?

Copy link
Contributor

Choose a reason for hiding this comment

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

This is curious! I'm not sure what this was for. I'm guessing that this was just an artifact copy/pasting a snippet from ReactDOMRoot-test. It's quite a bit more sophisticated:

container = document.createElement('div');
// TODO pull this into helper method, reduce repetition.
// mock the browser APIs which are used in schedule:
// - requestAnimationFrame should pass the DOMHighResTimeStamp argument
// - calling 'window.postMessage' should actually fire postmessage handlers
// - must allow artificially changing time returned by Date.now
// Performance.now is not supported in the test environment
const originalDateNow = Date.now;
let advancedTime = null;
global.Date.now = function() {
if (advancedTime) {
return originalDateNow() + advancedTime;
}
return originalDateNow();
};
advanceCurrentTime = function(amount) {
advancedTime = amount;
};
global.requestAnimationFrame = function(cb) {
return setTimeout(() => {
cb(Date.now());
});
};

I think this is safe to remove.

return originalDateNow();
};
// TODO remove `requestAnimationFrame` when upgrading to Jest 24 with Lolex
Copy link
Contributor Author

@SimenB SimenB Oct 27, 2018

Choose a reason for hiding this comment

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

Using Jest 24, the test passes without faking global.requestAnimationFrame. So whenever the upgrade lands, just remove the implementation here

global.requestAnimationFrame = function(cb) {
return setTimeout(() => {
cb(Date.now());
Expand Down Expand Up @@ -140,7 +137,7 @@ describe('ProfilerDOM', () => {

// Evaluate in an unwrapped callback,
// Because trace/wrap won't decrement the count within the wrapped callback.
setImmediate(() => {
Promise.resolve().then(() => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I kind of wish this could be re-used, but it's unclear where something like that could go. .

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could do an await, then you're guaranteed a tick even if promises are faked

Copy link
Contributor

Choose a reason for hiding this comment

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

Naw, I think this is fine.

expect(onInteractionTraced).toHaveBeenCalledTimes(1);
expect(
onInteractionScheduledWorkCompleted,
Expand Down