kopia lustrzana https://github.com/wagtail/wagtail
Extract setOptionalInterval util from SessionController
rodzic
7b67723da9
commit
a5b42936ec
client/src
controllers
|
@ -2,6 +2,7 @@ import { Controller } from '@hotwired/stimulus';
|
|||
import { DialogController } from './DialogController';
|
||||
import { SwapController } from './SwapController';
|
||||
import { ActionController } from './ActionController';
|
||||
import { setOptionalInterval } from '../utils/interval';
|
||||
|
||||
interface PingResponse {
|
||||
session_id: string;
|
||||
|
@ -73,7 +74,7 @@ export class SessionController extends Controller<HTMLElement> {
|
|||
declare interceptValue: boolean;
|
||||
|
||||
/** The interval ID for the periodic pinging */
|
||||
declare interval: number;
|
||||
declare interval: number | null;
|
||||
/** The last action button that triggered the event */
|
||||
lastActionButton?: HTMLButtonElement;
|
||||
|
||||
|
@ -120,11 +121,7 @@ export class SessionController extends Controller<HTMLElement> {
|
|||
*/
|
||||
addInterval(): void {
|
||||
this.clearInterval();
|
||||
// Values outside this range will be ignored by window.setInterval,
|
||||
// making it fire all the time.
|
||||
if (this.intervalValue <= 0 || this.intervalValue >= 2 ** 31) return;
|
||||
|
||||
this.interval = window.setInterval(this.ping, this.intervalValue);
|
||||
this.interval = setOptionalInterval(this.ping, this.intervalValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -133,6 +130,7 @@ export class SessionController extends Controller<HTMLElement> {
|
|||
clearInterval(): void {
|
||||
if (this.interval) {
|
||||
window.clearInterval(this.interval);
|
||||
this.interval = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
import { setOptionalInterval } from './interval';
|
||||
|
||||
jest.useFakeTimers();
|
||||
jest.spyOn(global, 'setInterval');
|
||||
|
||||
describe('setOptionalInterval', () => {
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
jest.clearAllTimers();
|
||||
});
|
||||
|
||||
it('should be a pass-through for setInterval in normal cases', () => {
|
||||
const callback = jest.fn();
|
||||
const interval = setOptionalInterval(callback, 1);
|
||||
|
||||
expect(setInterval).toHaveBeenCalledWith(callback, 1);
|
||||
expect(interval).toEqual(global.setInterval.mock.results[0].value);
|
||||
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
jest.advanceTimersByTime(1);
|
||||
expect(callback).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should not set the interval if the delay is unset', () => {
|
||||
const callback = jest.fn();
|
||||
const interval = setOptionalInterval(callback);
|
||||
|
||||
expect(setInterval).not.toHaveBeenCalled();
|
||||
expect(interval).toBeNull();
|
||||
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
jest.advanceTimersByTime(100);
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not set the interval if the delay is set to 0', () => {
|
||||
const callback = jest.fn();
|
||||
const interval = setOptionalInterval(callback, 0);
|
||||
|
||||
expect(setInterval).not.toHaveBeenCalled();
|
||||
expect(interval).toBeNull();
|
||||
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
jest.advanceTimersByTime(100);
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not set the interval if the delay is set to a very large value', () => {
|
||||
const callback = jest.fn();
|
||||
const interval = setOptionalInterval(callback, 9999999999);
|
||||
|
||||
expect(setInterval).not.toHaveBeenCalled();
|
||||
expect(interval).toBeNull();
|
||||
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
jest.advanceTimersByTime(10000000000);
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* Like `setInterval`, but only sets the interval if the `delay` value is positive.
|
||||
*
|
||||
* Browsers treat non-positive `delay` values as 0, which means the interval will
|
||||
* run immediately (basically all the time). Instead of allowing this behavior,
|
||||
* this function will not set the interval instead. This allows the interval to
|
||||
* be disabled by setting the `delay` value to <= 0 (or a large enough value that
|
||||
* it overflows to negative), which is useful for user-configurable intervals.
|
||||
*
|
||||
* @param func the callback function to call
|
||||
* @param delay the interval delay in milliseconds
|
||||
* @param args the arguments to pass to the callback function
|
||||
* @returns the interval ID if the interval is valid, otherwise null
|
||||
*/
|
||||
export const setOptionalInterval = (
|
||||
func: TimerHandler,
|
||||
delay?: number,
|
||||
...args: any[]
|
||||
) => {
|
||||
// "The `delay` argument is converted to a signed 32-bit integer."
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/setInterval#return_value
|
||||
if (!delay || delay <= 0 || delay >= 2 ** 31) return null;
|
||||
return setInterval(func, delay, ...args);
|
||||
};
|
Ładowanie…
Reference in New Issue