116 lines
3.5 KiB
JavaScript
116 lines
3.5 KiB
JavaScript
|
/**
|
||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||
|
*
|
||
|
* This source code is licensed under the MIT license found in the
|
||
|
* LICENSE file in the root directory of this source tree.
|
||
|
*
|
||
|
* @emails react-core
|
||
|
* @jest-environment node
|
||
|
*/
|
||
|
|
||
|
'use strict';
|
||
|
|
||
|
let Scheduler;
|
||
|
let scheduleCallback;
|
||
|
let ImmediatePriority;
|
||
|
let UserBlockingPriority;
|
||
|
let NormalPriority;
|
||
|
// See: https://github.com/facebook/react/pull/13088
|
||
|
'SchedulerNoDOM' |> describe(%, () => {
|
||
|
// Scheduler falls back to a naive implementation using setTimeout.
|
||
|
// This is only meant to be used for testing purposes, like with jest's fake timer API.
|
||
|
(() => {
|
||
|
jest.resetModules();
|
||
|
jest.useFakeTimers();
|
||
|
delete global.setImmediate;
|
||
|
delete global.MessageChannel;
|
||
|
'scheduler' |> jest.unmock(%);
|
||
|
Scheduler = 'scheduler' |> require(%);
|
||
|
scheduleCallback = Scheduler.unstable_scheduleCallback;
|
||
|
UserBlockingPriority = Scheduler.unstable_UserBlockingPriority;
|
||
|
NormalPriority = Scheduler.unstable_NormalPriority;
|
||
|
}) |> beforeEach(%);
|
||
|
'runAllTimers flushes all scheduled callbacks' |> it(%, () => {
|
||
|
const log = [];
|
||
|
NormalPriority |> scheduleCallback(%, () => {
|
||
|
'A' |> log.push(%);
|
||
|
});
|
||
|
NormalPriority |> scheduleCallback(%, () => {
|
||
|
'B' |> log.push(%);
|
||
|
});
|
||
|
NormalPriority |> scheduleCallback(%, () => {
|
||
|
'C' |> log.push(%);
|
||
|
});
|
||
|
[] |> (log |> expect(%)).toEqual(%);
|
||
|
jest.runAllTimers();
|
||
|
['A', 'B', 'C'] |> (log |> expect(%)).toEqual(%);
|
||
|
});
|
||
|
'executes callbacks in order of priority' |> it(%, () => {
|
||
|
const log = [];
|
||
|
NormalPriority |> scheduleCallback(%, () => {
|
||
|
'A' |> log.push(%);
|
||
|
});
|
||
|
NormalPriority |> scheduleCallback(%, () => {
|
||
|
'B' |> log.push(%);
|
||
|
});
|
||
|
UserBlockingPriority |> scheduleCallback(%, () => {
|
||
|
'C' |> log.push(%);
|
||
|
});
|
||
|
UserBlockingPriority |> scheduleCallback(%, () => {
|
||
|
'D' |> log.push(%);
|
||
|
});
|
||
|
[] |> (log |> expect(%)).toEqual(%);
|
||
|
jest.runAllTimers();
|
||
|
['C', 'D', 'A', 'B'] |> (log |> expect(%)).toEqual(%);
|
||
|
});
|
||
|
'handles errors' |> it(%, () => {
|
||
|
let log = [];
|
||
|
ImmediatePriority |> scheduleCallback(%, () => {
|
||
|
'A' |> log.push(%);
|
||
|
throw new Error('Oops A');
|
||
|
});
|
||
|
ImmediatePriority |> scheduleCallback(%, () => {
|
||
|
'B' |> log.push(%);
|
||
|
});
|
||
|
ImmediatePriority |> scheduleCallback(%, () => {
|
||
|
'C' |> log.push(%);
|
||
|
throw new Error('Oops C');
|
||
|
});
|
||
|
'Oops A' |> ((() => jest.runAllTimers()) |> expect(%)).toThrow(%);
|
||
|
['A'] |> (log |> expect(%)).toEqual(%);
|
||
|
log = [];
|
||
|
|
||
|
// B and C flush in a subsequent event. That way, the second error is not
|
||
|
// swallowed.
|
||
|
'Oops C' |> ((() => jest.runAllTimers()) |> expect(%)).toThrow(%);
|
||
|
['B', 'C'] |> (log |> expect(%)).toEqual(%);
|
||
|
});
|
||
|
});
|
||
|
'does not crash non-node SSR environments' |> describe(%, () => {
|
||
|
'if setTimeout is undefined' |> it(%, () => {
|
||
|
jest.resetModules();
|
||
|
const originalSetTimeout = global.setTimeout;
|
||
|
try {
|
||
|
delete global.setTimeout;
|
||
|
'scheduler' |> jest.unmock(%);
|
||
|
((() => {
|
||
|
'scheduler' |> require(%);
|
||
|
}) |> expect(%)).not.toThrow();
|
||
|
} finally {
|
||
|
global.setTimeout = originalSetTimeout;
|
||
|
}
|
||
|
});
|
||
|
'if clearTimeout is undefined' |> it(%, () => {
|
||
|
jest.resetModules();
|
||
|
const originalClearTimeout = global.clearTimeout;
|
||
|
try {
|
||
|
delete global.clearTimeout;
|
||
|
'scheduler' |> jest.unmock(%);
|
||
|
((() => {
|
||
|
'scheduler' |> require(%);
|
||
|
}) |> expect(%)).not.toThrow();
|
||
|
} finally {
|
||
|
global.clearTimeout = originalClearTimeout;
|
||
|
}
|
||
|
});
|
||
|
});
|