mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-06-16 15:20:37 +03:00
add initialization and environment unit tests
This commit is contained in:
@@ -1,14 +1,19 @@
|
|||||||
import { isFunction, isHTMLElement, isNull, isUndefined } from 'support';
|
import { isFunction, isHTMLElement, isNull, isUndefined } from 'support';
|
||||||
import { getEnvironment } from 'environment';
|
import { getEnvironment } from 'environment';
|
||||||
import { DeepPartial } from 'typings';
|
import type { DeepPartial } from 'typings';
|
||||||
import { StructureSetupElementsObj } from 'setups/structureSetup/structureSetup.elements';
|
|
||||||
|
|
||||||
type StaticInitialization = HTMLElement | false | null;
|
type StaticInitialization = HTMLElement | false | null;
|
||||||
type DynamicInitialization = HTMLElement | boolean | null;
|
type DynamicInitialization = HTMLElement | boolean | null;
|
||||||
|
type FallbackStaticInitializtationElement<Args extends any[]> = Extract<
|
||||||
type FallbackInitializtationElement<
|
StaticInitializationElement<Args>,
|
||||||
InitElm extends StaticInitializationElement<any> | DynamicInitializationElement<any>
|
(...args: Args) => any
|
||||||
> = Extract<InitElm, (...args: any[]) => any> extends (...args: infer P) => any
|
> extends (...args: infer P) => any
|
||||||
|
? (...args: P) => HTMLElement
|
||||||
|
: never;
|
||||||
|
type FallbackDynamicInitializtationElement<Args extends any[]> = Extract<
|
||||||
|
DynamicInitializationElement<Args>,
|
||||||
|
(...args: Args) => any
|
||||||
|
> extends (...args: infer P) => any
|
||||||
? (...args: P) => HTMLElement
|
? (...args: P) => HTMLElement
|
||||||
: never;
|
: never;
|
||||||
|
|
||||||
@@ -59,30 +64,30 @@ export type InitializationTarget = InitializationTargetElement | InitializationT
|
|||||||
const resolveInitialization = <T>(value: any, args: any): T =>
|
const resolveInitialization = <T>(value: any, args: any): T =>
|
||||||
isFunction(value) ? value.apply(0, args) : value;
|
isFunction(value) ? value.apply(0, args) : value;
|
||||||
|
|
||||||
export const staticInitializationElement = <T extends StaticInitializationElement<any>>(
|
export const staticInitializationElement = <Args extends any[]>(
|
||||||
args: Parameters<Extract<T, (...initializationFnArgs: any[]) => any>>,
|
args: Args,
|
||||||
fallbackStaticInitializationElement: FallbackInitializtationElement<T>,
|
fallbackStaticInitializationElement: FallbackStaticInitializtationElement<Args>,
|
||||||
defaultStaticInitializationElementStrategy: T,
|
defaultStaticInitializationElement: StaticInitializationElement<Args>,
|
||||||
staticInitializationElementValue?: T
|
staticInitializationElementValue?: StaticInitializationElement<Args>
|
||||||
): HTMLElement => {
|
): HTMLElement => {
|
||||||
const staticInitialization = isUndefined(staticInitializationElementValue)
|
const staticInitialization = isUndefined(staticInitializationElementValue)
|
||||||
? defaultStaticInitializationElementStrategy
|
? defaultStaticInitializationElement
|
||||||
: staticInitializationElementValue;
|
: staticInitializationElementValue;
|
||||||
const resolvedInitialization = resolveInitialization<StaticInitialization>(
|
const resolvedInitialization = resolveInitialization<StaticInitialization>(
|
||||||
staticInitialization,
|
staticInitialization,
|
||||||
args
|
args
|
||||||
);
|
);
|
||||||
return resolvedInitialization || fallbackStaticInitializationElement();
|
return resolvedInitialization || fallbackStaticInitializationElement.apply(0, args);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const dynamicInitializationElement = <T extends DynamicInitializationElement<any>>(
|
export const dynamicInitializationElement = <Args extends any[]>(
|
||||||
args: Parameters<Extract<T, (...initializationFnArgs: any[]) => any>>,
|
args: Args,
|
||||||
fallbackDynamicInitializationElement: FallbackInitializtationElement<T>,
|
fallbackDynamicInitializationElement: FallbackDynamicInitializtationElement<Args>,
|
||||||
defaultDynamicInitializationElementStrategy: T,
|
defaultDynamicInitializationElement: DynamicInitializationElement<Args>,
|
||||||
dynamicInitializationElementValue?: T
|
dynamicInitializationElementValue?: DynamicInitializationElement<Args>
|
||||||
): HTMLElement | false => {
|
): HTMLElement | false => {
|
||||||
const dynamicInitialization = isUndefined(dynamicInitializationElementValue)
|
const dynamicInitialization = isUndefined(dynamicInitializationElementValue)
|
||||||
? defaultDynamicInitializationElementStrategy
|
? defaultDynamicInitializationElement
|
||||||
: dynamicInitializationElementValue;
|
: dynamicInitializationElementValue;
|
||||||
const resolvedInitialization = resolveInitialization<DynamicInitialization>(
|
const resolvedInitialization = resolveInitialization<DynamicInitialization>(
|
||||||
dynamicInitialization,
|
dynamicInitialization,
|
||||||
@@ -92,20 +97,19 @@ export const dynamicInitializationElement = <T extends DynamicInitializationElem
|
|||||||
!!resolvedInitialization &&
|
!!resolvedInitialization &&
|
||||||
(isHTMLElement(resolvedInitialization)
|
(isHTMLElement(resolvedInitialization)
|
||||||
? resolvedInitialization
|
? resolvedInitialization
|
||||||
: fallbackDynamicInitializationElement())
|
: fallbackDynamicInitializationElement.apply(0, args))
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const cancelInitialization = (
|
export const cancelInitialization = (
|
||||||
cancelInitializationValue: DeepPartial<Initialization['cancel']> | false | null | undefined,
|
isBody: boolean,
|
||||||
structureSetupElements: StructureSetupElementsObj
|
defaultCancelInitialization: Initialization['cancel'],
|
||||||
|
cancelInitializationValue?: DeepPartial<Initialization['cancel']> | false | null | undefined
|
||||||
): boolean => {
|
): boolean => {
|
||||||
const { nativeScrollbarsOverlaid, body } = cancelInitializationValue || {};
|
const { nativeScrollbarsOverlaid, body } = cancelInitializationValue || {};
|
||||||
const { _isBody } = structureSetupElements;
|
const { _nativeScrollbarsOverlaid, _nativeScrollbarsHiding } = getEnvironment();
|
||||||
const { _getDefaultInitialization, _nativeScrollbarsOverlaid, _nativeScrollbarsHiding } =
|
|
||||||
getEnvironment();
|
|
||||||
const { nativeScrollbarsOverlaid: defaultNativeScrollbarsOverlaid, body: defaultbody } =
|
const { nativeScrollbarsOverlaid: defaultNativeScrollbarsOverlaid, body: defaultbody } =
|
||||||
_getDefaultInitialization().cancel;
|
defaultCancelInitialization;
|
||||||
|
|
||||||
const resolvedNativeScrollbarsOverlaid =
|
const resolvedNativeScrollbarsOverlaid =
|
||||||
nativeScrollbarsOverlaid ?? defaultNativeScrollbarsOverlaid;
|
nativeScrollbarsOverlaid ?? defaultNativeScrollbarsOverlaid;
|
||||||
@@ -115,7 +119,7 @@ export const cancelInitialization = (
|
|||||||
(_nativeScrollbarsOverlaid.x || _nativeScrollbarsOverlaid.y) &&
|
(_nativeScrollbarsOverlaid.x || _nativeScrollbarsOverlaid.y) &&
|
||||||
resolvedNativeScrollbarsOverlaid;
|
resolvedNativeScrollbarsOverlaid;
|
||||||
const finalDocumentScrollingElement =
|
const finalDocumentScrollingElement =
|
||||||
_isBody &&
|
isBody &&
|
||||||
(isNull(resolvedDocumentScrollingElement)
|
(isNull(resolvedDocumentScrollingElement)
|
||||||
? !_nativeScrollbarsHiding
|
? !_nativeScrollbarsHiding
|
||||||
: resolvedDocumentScrollingElement);
|
: resolvedDocumentScrollingElement);
|
||||||
|
|||||||
@@ -115,7 +115,11 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
|
|||||||
options?: DeepPartial<Options>,
|
options?: DeepPartial<Options>,
|
||||||
eventListeners?: InitialEventListeners
|
eventListeners?: InitialEventListeners
|
||||||
) => {
|
) => {
|
||||||
const { _getDefaultOptions, _addListener: addEnvListener } = getEnvironment();
|
const {
|
||||||
|
_getDefaultOptions,
|
||||||
|
_getDefaultInitialization,
|
||||||
|
_addListener: addEnvListener,
|
||||||
|
} = getEnvironment();
|
||||||
const plugins = getPlugins();
|
const plugins = getPlugins();
|
||||||
const targetIsElement = isHTMLElement(target);
|
const targetIsElement = isHTMLElement(target);
|
||||||
const instanceTarget = targetIsElement ? target : target.target;
|
const instanceTarget = targetIsElement ? target : target.target;
|
||||||
@@ -271,7 +275,13 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (cancelInitialization(!targetIsElement && target.cancel, structureState._elements)) {
|
if (
|
||||||
|
cancelInitialization(
|
||||||
|
structureState._elements._isBody,
|
||||||
|
_getDefaultInitialization().cancel,
|
||||||
|
!targetIsElement && target.cancel
|
||||||
|
)
|
||||||
|
) {
|
||||||
destroy(true);
|
destroy(true);
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,14 +28,14 @@ import {
|
|||||||
getScrollbarHandleOffsetRatio,
|
getScrollbarHandleOffsetRatio,
|
||||||
} from 'setups/scrollbarsSetup/scrollbarsSetup.calculations';
|
} from 'setups/scrollbarsSetup/scrollbarsSetup.calculations';
|
||||||
import type {
|
import type {
|
||||||
Initialization,
|
|
||||||
InitializationTarget,
|
InitializationTarget,
|
||||||
|
InitializationTargetElement,
|
||||||
InitializationTargetObject,
|
InitializationTargetObject,
|
||||||
} from 'initialization';
|
} from 'initialization';
|
||||||
import type { StructureSetupElementsObj } from 'setups/structureSetup/structureSetup.elements';
|
import type { StructureSetupElementsObj } from 'setups/structureSetup/structureSetup.elements';
|
||||||
import type { ScrollbarsSetupEvents } from 'setups/scrollbarsSetup/scrollbarsSetup.events';
|
import type { ScrollbarsSetupEvents } from 'setups/scrollbarsSetup/scrollbarsSetup.events';
|
||||||
import type { StyleObject } from 'typings';
|
import type { StyleObject } from 'typings';
|
||||||
import { StructureSetupState } from 'setups';
|
import type { StructureSetupState } from 'setups';
|
||||||
|
|
||||||
export interface ScrollbarStructure {
|
export interface ScrollbarStructure {
|
||||||
_scrollbar: HTMLElement;
|
_scrollbar: HTMLElement;
|
||||||
@@ -84,7 +84,7 @@ export const createScrollbarsSetupElements = (
|
|||||||
const { scrollbars: scrollbarsInit } = (_targetIsElm ? {} : target) as InitializationTargetObject;
|
const { scrollbars: scrollbarsInit } = (_targetIsElm ? {} : target) as InitializationTargetObject;
|
||||||
const { slot: initScrollbarsSlot } = scrollbarsInit || {};
|
const { slot: initScrollbarsSlot } = scrollbarsInit || {};
|
||||||
const evaluatedScrollbarSlot = generalDynamicInitializationElement<
|
const evaluatedScrollbarSlot = generalDynamicInitializationElement<
|
||||||
Initialization['scrollbars']['slot']
|
[InitializationTargetElement, HTMLElement, HTMLElement]
|
||||||
>([_target, _host, _viewport], () => _host, defaultInitScrollbarsSlot, initScrollbarsSlot);
|
>([_target, _host, _viewport], () => _host, defaultInitScrollbarsSlot, initScrollbarsSlot);
|
||||||
const scrollbarStructureAddRemoveClass = (
|
const scrollbarStructureAddRemoveClass = (
|
||||||
scrollbarStructures: ScrollbarStructure[],
|
scrollbarStructures: ScrollbarStructure[],
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
runEachAndClear,
|
runEachAndClear,
|
||||||
stopPropagation,
|
stopPropagation,
|
||||||
XY,
|
XY,
|
||||||
selfCancelTimeout,
|
selfClearTimeout,
|
||||||
parent,
|
parent,
|
||||||
closest,
|
closest,
|
||||||
rAF,
|
rAF,
|
||||||
@@ -223,7 +223,7 @@ export const createScrollbarsSetupEvents =
|
|||||||
isHorizontal
|
isHorizontal
|
||||||
) => {
|
) => {
|
||||||
const { _scrollbar } = scrollbarStructure;
|
const { _scrollbar } = scrollbarStructure;
|
||||||
const [wheelTimeout, clearScrollTimeout] = selfCancelTimeout(333);
|
const [wheelTimeout, clearScrollTimeout] = selfClearTimeout(333);
|
||||||
const scrollByFn = !!scrollOffsetElm.scrollBy;
|
const scrollByFn = !!scrollOffsetElm.scrollBy;
|
||||||
let wheelScrollBy = true;
|
let wheelScrollBy = true;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { on, runEachAndClear, parent, scrollLeft, scrollTop, selfCancelTimeout } from 'support';
|
import { on, runEachAndClear, parent, scrollLeft, scrollTop, selfClearTimeout } from 'support';
|
||||||
import { createState, createOptionCheck } from 'setups/setups';
|
import { createState, createOptionCheck } from 'setups/setups';
|
||||||
import { createScrollbarsSetupEvents } from 'setups/scrollbarsSetup/scrollbarsSetup.events';
|
import { createScrollbarsSetupEvents } from 'setups/scrollbarsSetup/scrollbarsSetup.events';
|
||||||
import {
|
import {
|
||||||
@@ -51,11 +51,11 @@ export const createScrollbarsSetup = (
|
|||||||
|
|
||||||
const state = createState({});
|
const state = createState({});
|
||||||
const [getState] = state;
|
const [getState] = state;
|
||||||
const [requestMouseMoveAnimationFrame, cancelMouseMoveAnimationFrame] = selfCancelTimeout();
|
const [requestMouseMoveAnimationFrame, cancelMouseMoveAnimationFrame] = selfClearTimeout();
|
||||||
const [requestScrollAnimationFrame, cancelScrollAnimationFrame] = selfCancelTimeout();
|
const [requestScrollAnimationFrame, cancelScrollAnimationFrame] = selfClearTimeout();
|
||||||
const [scrollTimeout, clearScrollTimeout] = selfCancelTimeout(100);
|
const [scrollTimeout, clearScrollTimeout] = selfClearTimeout(100);
|
||||||
const [auotHideMoveTimeout, clearAutoHideTimeout] = selfCancelTimeout(100);
|
const [auotHideMoveTimeout, clearAutoHideTimeout] = selfClearTimeout(100);
|
||||||
const [auotHideTimeout, clearAutoTimeout] = selfCancelTimeout(() => globalAutoHideDelay);
|
const [auotHideTimeout, clearAutoTimeout] = selfClearTimeout(() => globalAutoHideDelay);
|
||||||
const [elements, appendElements, destroyElements] = createScrollbarsSetupElements(
|
const [elements, appendElements, destroyElements] = createScrollbarsSetupElements(
|
||||||
target,
|
target,
|
||||||
structureSetupState._elements,
|
structureSetupState._elements,
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ import {
|
|||||||
dynamicInitializationElement as generalDynamicInitializationElement,
|
dynamicInitializationElement as generalDynamicInitializationElement,
|
||||||
} from 'initialization';
|
} from 'initialization';
|
||||||
import type {
|
import type {
|
||||||
Initialization,
|
|
||||||
InitializationTarget,
|
InitializationTarget,
|
||||||
InitializationTargetElement,
|
InitializationTargetElement,
|
||||||
InitializationTargetObject,
|
InitializationTargetObject,
|
||||||
@@ -117,10 +116,10 @@ export const createStructureSetupElements = (
|
|||||||
const isBody = targetElement === ownerDocument.body;
|
const isBody = targetElement === ownerDocument.body;
|
||||||
const wnd = ownerDocument.defaultView as Window;
|
const wnd = ownerDocument.defaultView as Window;
|
||||||
const staticInitializationElement = generalStaticInitializationElement<
|
const staticInitializationElement = generalStaticInitializationElement<
|
||||||
Initialization['elements']['viewport']
|
[InitializationTargetElement]
|
||||||
>.bind(0, [targetElement]);
|
>.bind(0, [targetElement]);
|
||||||
const dynamicInitializationElement = generalDynamicInitializationElement<
|
const dynamicInitializationElement = generalDynamicInitializationElement<
|
||||||
Initialization['elements']['content']
|
[InitializationTargetElement]
|
||||||
>.bind(0, [targetElement]);
|
>.bind(0, [targetElement]);
|
||||||
const viewportElement = staticInitializationElement(
|
const viewportElement = staticInitializationElement(
|
||||||
createNewDiv,
|
createNewDiv,
|
||||||
|
|||||||
@@ -30,7 +30,12 @@ export interface Debounced<FunctionToDebounce extends (...args: any) => any> {
|
|||||||
|
|
||||||
export const noop = () => {}; // eslint-disable-line
|
export const noop = () => {}; // eslint-disable-line
|
||||||
|
|
||||||
export const selfCancelTimeout = (timeout?: number | (() => number)) => {
|
/**
|
||||||
|
* Creates a timeout and cleartimeout tuple. The timeout function always clears the previously created timeout before it runs.
|
||||||
|
* @param timeout The timeout in ms. If no timeout (or 0) is passed requestAnimationFrame is used instead of setTimeout.
|
||||||
|
* @returns A tuple with the timeout function as the first value and the clearTimeout function as the second value.
|
||||||
|
*/
|
||||||
|
export const selfClearTimeout = (timeout?: number | (() => number)) => {
|
||||||
let id: number;
|
let id: number;
|
||||||
const setTFn = timeout ? setT : rAF!;
|
const setTFn = timeout ? setT : rAF!;
|
||||||
const clearTFn = timeout ? clearT : cAF!;
|
const clearTFn = timeout ? clearT : cAF!;
|
||||||
|
|||||||
@@ -0,0 +1,186 @@
|
|||||||
|
import { DeepPartial } from 'typings';
|
||||||
|
import { defaultOptions, Options } from 'options';
|
||||||
|
import { Initialization } from 'initialization';
|
||||||
|
import { getEnvironment } from 'environment';
|
||||||
|
import { scrollbarsHidingPlugin, scrollbarsHidingPluginName } from 'plugins';
|
||||||
|
|
||||||
|
const defaultInitialization = {
|
||||||
|
elements: {
|
||||||
|
host: null,
|
||||||
|
padding: true,
|
||||||
|
viewport: expect.any(Function),
|
||||||
|
content: false,
|
||||||
|
},
|
||||||
|
scrollbars: {
|
||||||
|
slot: true,
|
||||||
|
},
|
||||||
|
cancel: {
|
||||||
|
nativeScrollbarsOverlaid: false,
|
||||||
|
body: null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let getEnv = getEnvironment;
|
||||||
|
|
||||||
|
describe('environment', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
jest.resetModules();
|
||||||
|
jest.doMock('support', () => {
|
||||||
|
const originalModule = jest.requireActual('support');
|
||||||
|
let i = 0;
|
||||||
|
return {
|
||||||
|
...originalModule,
|
||||||
|
offsetSize: jest.fn().mockImplementation(() => {
|
||||||
|
i += 1;
|
||||||
|
return { w: 100 + i, h: 100 + i };
|
||||||
|
}),
|
||||||
|
clientSize: jest.fn().mockImplementation(() => ({ w: 90, h: 90 })),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
jest.doMock('plugins', () => {
|
||||||
|
const originalModule = jest.requireActual('plugins');
|
||||||
|
return {
|
||||||
|
...originalModule,
|
||||||
|
getPlugins: jest.fn(() => originalModule.getPlugins()),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
({ getEnvironment: getEnv } = await import('environment'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('singleton behavior', () => {
|
||||||
|
const env = getEnv();
|
||||||
|
expect(env).toBe(getEnv());
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('statics', () => {
|
||||||
|
test('defaultOptions', () => {
|
||||||
|
const { _staticDefaultOptions, _getDefaultOptions } = getEnv();
|
||||||
|
expect(_staticDefaultOptions).not.toBe(defaultOptions);
|
||||||
|
expect(_staticDefaultOptions).toEqual(defaultOptions);
|
||||||
|
expect(_staticDefaultOptions).not.toBe(_getDefaultOptions());
|
||||||
|
expect(_staticDefaultOptions).toEqual(_getDefaultOptions());
|
||||||
|
});
|
||||||
|
|
||||||
|
test('defaultInitialization', () => {
|
||||||
|
const { _staticDefaultInitialization, _getDefaultInitialization } = getEnv();
|
||||||
|
expect(_staticDefaultInitialization).not.toBe(defaultInitialization);
|
||||||
|
expect(_staticDefaultInitialization).toEqual(defaultInitialization);
|
||||||
|
expect(_staticDefaultInitialization).not.toBe(_getDefaultInitialization());
|
||||||
|
expect(_staticDefaultInitialization).toEqual(_getDefaultInitialization());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('defaultOptions', () => {
|
||||||
|
test('get', () => {
|
||||||
|
const { _getDefaultOptions } = getEnv();
|
||||||
|
expect(_getDefaultOptions()).not.toBe(defaultOptions);
|
||||||
|
expect(_getDefaultOptions()).toEqual(defaultOptions);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('set', () => {
|
||||||
|
const newDefaultOptions: DeepPartial<Options> = {
|
||||||
|
paddingAbsolute: true,
|
||||||
|
overflow: {
|
||||||
|
x: 'hidden',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const { _getDefaultOptions, _setDefaultOptions } = getEnv();
|
||||||
|
expect(_getDefaultOptions()).not.toBe(defaultOptions);
|
||||||
|
expect(_getDefaultOptions()).toEqual(defaultOptions);
|
||||||
|
|
||||||
|
_setDefaultOptions(newDefaultOptions);
|
||||||
|
|
||||||
|
expect(_getDefaultOptions()).toEqual({
|
||||||
|
...defaultOptions,
|
||||||
|
...newDefaultOptions,
|
||||||
|
overflow: {
|
||||||
|
...defaultOptions.overflow,
|
||||||
|
...newDefaultOptions.overflow,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('defaultInitialization', () => {
|
||||||
|
test('get', () => {
|
||||||
|
const { _getDefaultInitialization } = getEnv();
|
||||||
|
expect(_getDefaultInitialization()).not.toBe(defaultInitialization);
|
||||||
|
expect(_getDefaultInitialization()).toEqual(defaultInitialization);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('set', () => {
|
||||||
|
const newDefaultInitialization: DeepPartial<Initialization> = {
|
||||||
|
elements: {
|
||||||
|
viewport: false,
|
||||||
|
padding: false,
|
||||||
|
},
|
||||||
|
cancel: {
|
||||||
|
body: true,
|
||||||
|
nativeScrollbarsOverlaid: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const { _getDefaultInitialization, _setDefaultInitialization } = getEnv();
|
||||||
|
expect(_getDefaultInitialization()).not.toBe(defaultInitialization);
|
||||||
|
expect(_getDefaultInitialization()).toEqual(defaultInitialization);
|
||||||
|
|
||||||
|
_setDefaultInitialization(newDefaultInitialization);
|
||||||
|
|
||||||
|
expect(_getDefaultInitialization()).toEqual({
|
||||||
|
...defaultInitialization,
|
||||||
|
...newDefaultInitialization,
|
||||||
|
elements: {
|
||||||
|
...defaultInitialization.elements,
|
||||||
|
...newDefaultInitialization.elements,
|
||||||
|
},
|
||||||
|
cancel: {
|
||||||
|
...defaultInitialization.cancel,
|
||||||
|
...newDefaultInitialization.cancel,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('addListener', () => {
|
||||||
|
test('with scrollbarsHidingPlugin registered before environment was created', async () => {
|
||||||
|
const { getPlugins } = await import('plugins');
|
||||||
|
(getPlugins as jest.Mock).mockImplementation(() => ({
|
||||||
|
[scrollbarsHidingPluginName]: scrollbarsHidingPlugin[scrollbarsHidingPluginName],
|
||||||
|
}));
|
||||||
|
|
||||||
|
const { _addListener } = getEnv();
|
||||||
|
const listener = jest.fn();
|
||||||
|
|
||||||
|
_addListener(listener);
|
||||||
|
window.dispatchEvent(new Event('resize'));
|
||||||
|
|
||||||
|
expect(listener).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('with scrollbarsHidingPlugin registered after environment was created', async () => {
|
||||||
|
const { _addListener } = getEnv();
|
||||||
|
const listener = jest.fn();
|
||||||
|
|
||||||
|
_addListener(listener);
|
||||||
|
|
||||||
|
const { getPlugins } = await import('plugins');
|
||||||
|
(getPlugins as jest.Mock).mockImplementation(() => ({
|
||||||
|
[scrollbarsHidingPluginName]: scrollbarsHidingPlugin[scrollbarsHidingPluginName],
|
||||||
|
}));
|
||||||
|
|
||||||
|
window.dispatchEvent(new Event('resize'));
|
||||||
|
|
||||||
|
expect(listener).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('without scrollbarsHidingPlugin', () => {
|
||||||
|
const { _addListener } = getEnv();
|
||||||
|
const listener = jest.fn();
|
||||||
|
|
||||||
|
_addListener(listener);
|
||||||
|
window.dispatchEvent(new Event('resize'));
|
||||||
|
|
||||||
|
expect(listener).toHaveBeenCalledTimes(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,587 @@
|
|||||||
|
import {
|
||||||
|
staticInitializationElement,
|
||||||
|
dynamicInitializationElement,
|
||||||
|
cancelInitialization,
|
||||||
|
Initialization,
|
||||||
|
} from 'initialization';
|
||||||
|
import { getEnvironment } from 'environment';
|
||||||
|
|
||||||
|
jest.mock('environment', () => ({
|
||||||
|
getEnvironment: jest.fn(() => jest.requireActual('environment').getEnvironment()),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const createDiv = () => document.createElement('div');
|
||||||
|
|
||||||
|
describe('initialization', () => {
|
||||||
|
describe('staticInitializationElement', () => {
|
||||||
|
test('defined', () => {
|
||||||
|
const args: [a: boolean, b: string] = [true, ''];
|
||||||
|
const fallbackElm = createDiv();
|
||||||
|
const defaultElm = createDiv();
|
||||||
|
const elm = createDiv();
|
||||||
|
const fallbackElmFn = jest.fn(() => fallbackElm);
|
||||||
|
const elmFn = jest.fn(() => elm);
|
||||||
|
const nullFn = jest.fn(() => null);
|
||||||
|
const falseFn = jest.fn<false, any[]>(() => false);
|
||||||
|
|
||||||
|
const values = {
|
||||||
|
elm: [
|
||||||
|
staticInitializationElement<[a: boolean, b: string]>(
|
||||||
|
args,
|
||||||
|
fallbackElmFn,
|
||||||
|
defaultElm,
|
||||||
|
elm
|
||||||
|
),
|
||||||
|
(result: HTMLElement) => expect(result).toBe(elm),
|
||||||
|
],
|
||||||
|
null: [
|
||||||
|
staticInitializationElement<[a: boolean, b: string]>(
|
||||||
|
args,
|
||||||
|
fallbackElmFn,
|
||||||
|
defaultElm,
|
||||||
|
null
|
||||||
|
),
|
||||||
|
(result: HTMLElement) => expect(result).toBe(fallbackElm),
|
||||||
|
],
|
||||||
|
false: [
|
||||||
|
staticInitializationElement<[a: boolean, b: string]>(
|
||||||
|
args,
|
||||||
|
fallbackElmFn,
|
||||||
|
defaultElm,
|
||||||
|
false
|
||||||
|
),
|
||||||
|
(result: HTMLElement) => expect(result).toBe(fallbackElm),
|
||||||
|
],
|
||||||
|
undefined: [
|
||||||
|
staticInitializationElement<[a: boolean, b: string]>(
|
||||||
|
args,
|
||||||
|
fallbackElmFn,
|
||||||
|
defaultElm,
|
||||||
|
undefined
|
||||||
|
),
|
||||||
|
(result: HTMLElement) => expect(result).toBe(defaultElm),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const fns = {
|
||||||
|
elm: [
|
||||||
|
staticInitializationElement<[a: boolean, b: string]>(
|
||||||
|
args,
|
||||||
|
fallbackElmFn,
|
||||||
|
defaultElm,
|
||||||
|
elmFn
|
||||||
|
),
|
||||||
|
(result: HTMLElement) => {
|
||||||
|
expect(result).toBe(elm);
|
||||||
|
expect(elmFn).toHaveBeenCalledTimes(1);
|
||||||
|
expect(elmFn).toHaveBeenLastCalledWith(...args);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
null: [
|
||||||
|
staticInitializationElement<[a: boolean, b: string]>(
|
||||||
|
args,
|
||||||
|
fallbackElmFn,
|
||||||
|
defaultElm,
|
||||||
|
nullFn
|
||||||
|
),
|
||||||
|
(result: HTMLElement) => {
|
||||||
|
expect(result).toBe(fallbackElm);
|
||||||
|
expect(nullFn).toHaveBeenCalledTimes(1);
|
||||||
|
expect(nullFn).toHaveBeenLastCalledWith(...args);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
false: [
|
||||||
|
staticInitializationElement<[a: boolean, b: string]>(
|
||||||
|
args,
|
||||||
|
fallbackElmFn,
|
||||||
|
defaultElm,
|
||||||
|
falseFn
|
||||||
|
),
|
||||||
|
(result: HTMLElement) => {
|
||||||
|
expect(result).toBe(fallbackElm);
|
||||||
|
expect(falseFn).toHaveBeenCalledTimes(1);
|
||||||
|
expect(falseFn).toHaveBeenLastCalledWith(...args);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.keys(values).forEach((key) => {
|
||||||
|
const [result, assertion] = values[key];
|
||||||
|
assertion(result);
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.keys(fns).forEach((key) => {
|
||||||
|
const [result, assertion] = fns[key];
|
||||||
|
assertion(result);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('default', () => {
|
||||||
|
const args: [a: boolean, b: string] = [true, ''];
|
||||||
|
const fallbackElm = createDiv();
|
||||||
|
const elm = createDiv();
|
||||||
|
const fallbackElmFn = jest.fn(() => fallbackElm);
|
||||||
|
const elmFn = jest.fn(() => elm);
|
||||||
|
const nullFn = jest.fn(() => null);
|
||||||
|
const falseFn = jest.fn<false, any[]>(() => false);
|
||||||
|
|
||||||
|
const values = {
|
||||||
|
elm: [
|
||||||
|
staticInitializationElement<[a: boolean, b: string]>(args, fallbackElmFn, elm),
|
||||||
|
(result: HTMLElement) => expect(result).toBe(elm),
|
||||||
|
],
|
||||||
|
null: [
|
||||||
|
staticInitializationElement<[a: boolean, b: string]>(args, fallbackElmFn, null),
|
||||||
|
(result: HTMLElement) => expect(result).toBe(fallbackElm),
|
||||||
|
],
|
||||||
|
false: [
|
||||||
|
staticInitializationElement<[a: boolean, b: string]>(args, fallbackElmFn, false),
|
||||||
|
(result: HTMLElement) => expect(result).toBe(fallbackElm),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const fns = {
|
||||||
|
elm: [
|
||||||
|
staticInitializationElement<[a: boolean, b: string]>(args, fallbackElmFn, elmFn),
|
||||||
|
(result: HTMLElement) => {
|
||||||
|
expect(result).toBe(elm);
|
||||||
|
expect(elmFn).toHaveBeenCalledTimes(1);
|
||||||
|
expect(elmFn).toHaveBeenLastCalledWith(...args);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
null: [
|
||||||
|
staticInitializationElement<[a: boolean, b: string]>(args, fallbackElmFn, nullFn),
|
||||||
|
(result: HTMLElement) => {
|
||||||
|
expect(result).toBe(fallbackElm);
|
||||||
|
expect(nullFn).toHaveBeenCalledTimes(1);
|
||||||
|
expect(nullFn).toHaveBeenLastCalledWith(...args);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
false: [
|
||||||
|
staticInitializationElement<[a: boolean, b: string]>(args, fallbackElmFn, falseFn),
|
||||||
|
(result: HTMLElement) => {
|
||||||
|
expect(result).toBe(fallbackElm);
|
||||||
|
expect(falseFn).toHaveBeenCalledTimes(1);
|
||||||
|
expect(falseFn).toHaveBeenLastCalledWith(...args);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.keys(values).forEach((key) => {
|
||||||
|
const [result, assertion] = values[key];
|
||||||
|
assertion(result);
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.keys(fns).forEach((key) => {
|
||||||
|
const [result, assertion] = fns[key];
|
||||||
|
assertion(result);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('dynamicInitializationElement', () => {
|
||||||
|
test('defined', () => {
|
||||||
|
const args: [a: boolean, b: string] = [true, ''];
|
||||||
|
const fallbackElm = createDiv();
|
||||||
|
const defaultElm = createDiv();
|
||||||
|
const elm = createDiv();
|
||||||
|
const fallbackElmFn = jest.fn(() => fallbackElm);
|
||||||
|
const elmFn = jest.fn(() => elm);
|
||||||
|
const snullFn = jest.fn(() => null);
|
||||||
|
const falseFn = jest.fn<false, any[]>(() => false);
|
||||||
|
const trueFn = jest.fn<true, any[]>(() => true);
|
||||||
|
|
||||||
|
const values = {
|
||||||
|
elm: [
|
||||||
|
dynamicInitializationElement<[a: boolean, b: string]>(
|
||||||
|
args,
|
||||||
|
fallbackElmFn,
|
||||||
|
defaultElm,
|
||||||
|
elm
|
||||||
|
),
|
||||||
|
(result: HTMLElement | false) => expect(result).toBe(elm),
|
||||||
|
],
|
||||||
|
null: [
|
||||||
|
dynamicInitializationElement<[a: boolean, b: string]>(
|
||||||
|
args,
|
||||||
|
fallbackElmFn,
|
||||||
|
defaultElm,
|
||||||
|
null
|
||||||
|
),
|
||||||
|
(result: HTMLElement | false) => expect(result).toBe(false),
|
||||||
|
],
|
||||||
|
false: [
|
||||||
|
dynamicInitializationElement<[a: boolean, b: string]>(
|
||||||
|
args,
|
||||||
|
fallbackElmFn,
|
||||||
|
defaultElm,
|
||||||
|
false
|
||||||
|
),
|
||||||
|
(result: HTMLElement | false) => expect(result).toBe(false),
|
||||||
|
],
|
||||||
|
true: [
|
||||||
|
dynamicInitializationElement<[a: boolean, b: string]>(
|
||||||
|
args,
|
||||||
|
fallbackElmFn,
|
||||||
|
defaultElm,
|
||||||
|
true
|
||||||
|
),
|
||||||
|
(result: HTMLElement | false) => expect(result).toBe(fallbackElm),
|
||||||
|
],
|
||||||
|
undefined: [
|
||||||
|
dynamicInitializationElement<[a: boolean, b: string]>(
|
||||||
|
args,
|
||||||
|
fallbackElmFn,
|
||||||
|
defaultElm,
|
||||||
|
undefined
|
||||||
|
),
|
||||||
|
(result: HTMLElement | false) => expect(result).toBe(defaultElm),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const fns = {
|
||||||
|
elm: [
|
||||||
|
dynamicInitializationElement<[a: boolean, b: string]>(
|
||||||
|
args,
|
||||||
|
fallbackElmFn,
|
||||||
|
defaultElm,
|
||||||
|
elmFn
|
||||||
|
),
|
||||||
|
(result: HTMLElement | false) => {
|
||||||
|
expect(result).toBe(elm);
|
||||||
|
expect(elmFn).toHaveBeenCalledTimes(1);
|
||||||
|
expect(elmFn).toHaveBeenLastCalledWith(...args);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
null: [
|
||||||
|
dynamicInitializationElement<[a: boolean, b: string]>(
|
||||||
|
args,
|
||||||
|
fallbackElmFn,
|
||||||
|
defaultElm,
|
||||||
|
snullFn
|
||||||
|
),
|
||||||
|
(result: HTMLElement | false) => {
|
||||||
|
expect(result).toBe(false);
|
||||||
|
expect(snullFn).toHaveBeenCalledTimes(1);
|
||||||
|
expect(snullFn).toHaveBeenLastCalledWith(...args);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
false: [
|
||||||
|
dynamicInitializationElement<[a: boolean, b: string]>(
|
||||||
|
args,
|
||||||
|
fallbackElmFn,
|
||||||
|
defaultElm,
|
||||||
|
falseFn
|
||||||
|
),
|
||||||
|
(result: HTMLElement | false) => {
|
||||||
|
expect(result).toBe(false);
|
||||||
|
expect(falseFn).toHaveBeenCalledTimes(1);
|
||||||
|
expect(falseFn).toHaveBeenLastCalledWith(...args);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
true: [
|
||||||
|
dynamicInitializationElement<[a: boolean, b: string]>(
|
||||||
|
args,
|
||||||
|
fallbackElmFn,
|
||||||
|
defaultElm,
|
||||||
|
trueFn
|
||||||
|
),
|
||||||
|
(result: HTMLElement | false) => {
|
||||||
|
expect(result).toBe(fallbackElm);
|
||||||
|
expect(falseFn).toHaveBeenCalledTimes(1);
|
||||||
|
expect(falseFn).toHaveBeenLastCalledWith(...args);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.keys(values).forEach((key) => {
|
||||||
|
const [result, assertion] = values[key];
|
||||||
|
assertion(result);
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.keys(fns).forEach((key) => {
|
||||||
|
const [result, assertion] = fns[key];
|
||||||
|
assertion(result);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('default', () => {
|
||||||
|
const args: [a: boolean, b: string] = [true, ''];
|
||||||
|
const fallbackElm = createDiv();
|
||||||
|
const elm = createDiv();
|
||||||
|
const fallbackElmFn = jest.fn(() => fallbackElm);
|
||||||
|
const elmFn = jest.fn(() => elm);
|
||||||
|
const nullFn = jest.fn(() => null);
|
||||||
|
const falseFn = jest.fn<false, any[]>(() => false);
|
||||||
|
const trueFn = jest.fn<true, any[]>(() => true);
|
||||||
|
|
||||||
|
const values = {
|
||||||
|
elm: [
|
||||||
|
dynamicInitializationElement<[a: boolean, b: string]>(args, fallbackElmFn, elm),
|
||||||
|
(result: HTMLElement | false) => expect(result).toBe(elm),
|
||||||
|
],
|
||||||
|
null: [
|
||||||
|
dynamicInitializationElement<[a: boolean, b: string]>(args, fallbackElmFn, null),
|
||||||
|
(result: HTMLElement | false) => expect(result).toBe(false),
|
||||||
|
],
|
||||||
|
false: [
|
||||||
|
dynamicInitializationElement<[a: boolean, b: string]>(args, fallbackElmFn, false),
|
||||||
|
(result: HTMLElement | false) => expect(result).toBe(false),
|
||||||
|
],
|
||||||
|
true: [
|
||||||
|
dynamicInitializationElement<[a: boolean, b: string]>(args, fallbackElmFn, true),
|
||||||
|
(result: HTMLElement | false) => expect(result).toBe(fallbackElm),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const fns = {
|
||||||
|
elm: [
|
||||||
|
dynamicInitializationElement<[a: boolean, b: string]>(args, fallbackElmFn, elmFn),
|
||||||
|
(result: HTMLElement | false) => {
|
||||||
|
expect(result).toBe(elm);
|
||||||
|
expect(elmFn).toHaveBeenCalledTimes(1);
|
||||||
|
expect(elmFn).toHaveBeenLastCalledWith(...args);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
null: [
|
||||||
|
dynamicInitializationElement<[a: boolean, b: string]>(args, fallbackElmFn, nullFn),
|
||||||
|
(result: HTMLElement | false) => {
|
||||||
|
expect(result).toBe(false);
|
||||||
|
expect(nullFn).toHaveBeenCalledTimes(1);
|
||||||
|
expect(nullFn).toHaveBeenLastCalledWith(...args);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
false: [
|
||||||
|
dynamicInitializationElement<[a: boolean, b: string]>(args, fallbackElmFn, falseFn),
|
||||||
|
(result: HTMLElement | false) => {
|
||||||
|
expect(result).toBe(false);
|
||||||
|
expect(falseFn).toHaveBeenCalledTimes(1);
|
||||||
|
expect(falseFn).toHaveBeenLastCalledWith(...args);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
true: [
|
||||||
|
dynamicInitializationElement<[a: boolean, b: string]>(args, fallbackElmFn, trueFn),
|
||||||
|
(result: HTMLElement | false) => {
|
||||||
|
expect(result).toBe(fallbackElm);
|
||||||
|
expect(falseFn).toHaveBeenCalledTimes(1);
|
||||||
|
expect(falseFn).toHaveBeenLastCalledWith(...args);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.keys(values).forEach((key) => {
|
||||||
|
const [result, assertion] = values[key];
|
||||||
|
assertion(result);
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.keys(fns).forEach((key) => {
|
||||||
|
const [result, assertion] = fns[key];
|
||||||
|
assertion(result);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('cancelInitialization', () => {
|
||||||
|
describe('nativeScrollbarsOverlaid', () => {
|
||||||
|
test('defined', () => {
|
||||||
|
(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
nativeScrollbarsOverlaid: false,
|
||||||
|
body: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nativeScrollbarsOverlaid: true,
|
||||||
|
body: false,
|
||||||
|
},
|
||||||
|
] as Initialization['cancel'][]
|
||||||
|
).forEach((defaultCancelInitialization) => {
|
||||||
|
[
|
||||||
|
{ nativeScrollbarsOverlaid: false },
|
||||||
|
{ nativeScrollbarsOverlaid: true },
|
||||||
|
{ nativeScrollbarsOverlaid: undefined },
|
||||||
|
].forEach((initializationValue) => {
|
||||||
|
[
|
||||||
|
{
|
||||||
|
_nativeScrollbarsOverlaid: {
|
||||||
|
x: false,
|
||||||
|
y: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_nativeScrollbarsOverlaid: {
|
||||||
|
x: false,
|
||||||
|
y: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_nativeScrollbarsOverlaid: {
|
||||||
|
x: true,
|
||||||
|
y: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
].forEach((env) => {
|
||||||
|
(getEnvironment as jest.Mock).mockImplementation(() => ({
|
||||||
|
...jest.requireActual('environment').getEnvironment(),
|
||||||
|
...env,
|
||||||
|
}));
|
||||||
|
const hasOverlaidScrollbars =
|
||||||
|
env._nativeScrollbarsOverlaid.x || env._nativeScrollbarsOverlaid.y;
|
||||||
|
const expected =
|
||||||
|
hasOverlaidScrollbars &&
|
||||||
|
(initializationValue.nativeScrollbarsOverlaid ??
|
||||||
|
defaultCancelInitialization.nativeScrollbarsOverlaid);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
cancelInitialization(false, defaultCancelInitialization, initializationValue)
|
||||||
|
).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('default', () => {
|
||||||
|
(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
nativeScrollbarsOverlaid: false,
|
||||||
|
body: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nativeScrollbarsOverlaid: true,
|
||||||
|
body: false,
|
||||||
|
},
|
||||||
|
] as Initialization['cancel'][]
|
||||||
|
).forEach((defaultCancelInitialization) => {
|
||||||
|
[
|
||||||
|
{
|
||||||
|
_nativeScrollbarsOverlaid: {
|
||||||
|
x: false,
|
||||||
|
y: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_nativeScrollbarsOverlaid: {
|
||||||
|
x: false,
|
||||||
|
y: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_nativeScrollbarsOverlaid: {
|
||||||
|
x: true,
|
||||||
|
y: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
].forEach((env) => {
|
||||||
|
(getEnvironment as jest.Mock).mockImplementation(() => ({
|
||||||
|
...jest.requireActual('environment').getEnvironment(),
|
||||||
|
...env,
|
||||||
|
}));
|
||||||
|
const hasOverlaidScrollbars =
|
||||||
|
env._nativeScrollbarsOverlaid.x || env._nativeScrollbarsOverlaid.y;
|
||||||
|
const expected =
|
||||||
|
hasOverlaidScrollbars && defaultCancelInitialization.nativeScrollbarsOverlaid;
|
||||||
|
|
||||||
|
expect(cancelInitialization(false, defaultCancelInitialization)).toEqual(expected);
|
||||||
|
expect(cancelInitialization(false, defaultCancelInitialization, undefined)).toEqual(
|
||||||
|
expected
|
||||||
|
);
|
||||||
|
expect(cancelInitialization(false, defaultCancelInitialization, null)).toEqual(
|
||||||
|
expected
|
||||||
|
);
|
||||||
|
expect(cancelInitialization(false, defaultCancelInitialization, false)).toEqual(
|
||||||
|
expected
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('body', () => {
|
||||||
|
test('defined', () => {
|
||||||
|
(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
nativeScrollbarsOverlaid: false,
|
||||||
|
body: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nativeScrollbarsOverlaid: false,
|
||||||
|
body: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nativeScrollbarsOverlaid: false,
|
||||||
|
body: null,
|
||||||
|
},
|
||||||
|
] as Initialization['cancel'][]
|
||||||
|
).forEach((defaultCancelInitialization) => {
|
||||||
|
[{ body: false }, { body: true }, { body: null }, { body: undefined }].forEach(
|
||||||
|
(initializationValue) => {
|
||||||
|
[{ _nativeScrollbarsHiding: false }, { _nativeScrollbarsHiding: true }].forEach(
|
||||||
|
(env) => {
|
||||||
|
[false, true].forEach((isBody) => {
|
||||||
|
(getEnvironment as jest.Mock).mockImplementation(() => ({
|
||||||
|
...jest.requireActual('environment').getEnvironment(),
|
||||||
|
...env,
|
||||||
|
}));
|
||||||
|
const defaultBody = defaultCancelInitialization.body;
|
||||||
|
const bodyValue = initializationValue.body;
|
||||||
|
const finalBody = bodyValue === undefined ? defaultBody : bodyValue;
|
||||||
|
const expected =
|
||||||
|
isBody && (finalBody === null ? !env._nativeScrollbarsHiding : finalBody);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
cancelInitialization(isBody, defaultCancelInitialization, initializationValue)
|
||||||
|
).toEqual(expected);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('default', () => {
|
||||||
|
(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
nativeScrollbarsOverlaid: false,
|
||||||
|
body: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nativeScrollbarsOverlaid: false,
|
||||||
|
body: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nativeScrollbarsOverlaid: false,
|
||||||
|
body: null,
|
||||||
|
},
|
||||||
|
] as Initialization['cancel'][]
|
||||||
|
).forEach((defaultCancelInitialization) => {
|
||||||
|
[{ _nativeScrollbarsHiding: false }, { _nativeScrollbarsHiding: true }].forEach((env) => {
|
||||||
|
[false, true].forEach((isBody) => {
|
||||||
|
(getEnvironment as jest.Mock).mockImplementation(() => ({
|
||||||
|
...jest.requireActual('environment').getEnvironment(),
|
||||||
|
...env,
|
||||||
|
}));
|
||||||
|
const defaultBody = defaultCancelInitialization.body;
|
||||||
|
const expected =
|
||||||
|
isBody && (defaultBody === null ? !env._nativeScrollbarsHiding : defaultBody);
|
||||||
|
|
||||||
|
expect(cancelInitialization(isBody, defaultCancelInitialization)).toEqual(expected);
|
||||||
|
expect(cancelInitialization(isBody, defaultCancelInitialization, undefined)).toEqual(
|
||||||
|
expected
|
||||||
|
);
|
||||||
|
expect(cancelInitialization(isBody, defaultCancelInitialization, null)).toEqual(
|
||||||
|
expected
|
||||||
|
);
|
||||||
|
expect(cancelInitialization(isBody, defaultCancelInitialization, false)).toEqual(
|
||||||
|
expected
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { noop, debounce } from 'support/utils/function';
|
import { noop, debounce, selfClearTimeout } from 'support/utils/function';
|
||||||
import { rAF, setT } from 'support/compatibility/apis';
|
import { rAF, cAF, setT, clearT } from 'support/compatibility/apis';
|
||||||
|
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
|
|
||||||
@@ -318,4 +318,105 @@ describe('function', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('selfClearTimeout', () => {
|
||||||
|
test('without timeout', () => {
|
||||||
|
let i = 0;
|
||||||
|
const [timeout, clear] = selfClearTimeout();
|
||||||
|
|
||||||
|
expect(rAF).not.toHaveBeenCalled();
|
||||||
|
expect(cAF).not.toHaveBeenCalled();
|
||||||
|
expect(setT).not.toHaveBeenCalled();
|
||||||
|
expect(clearT).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
timeout(() => {
|
||||||
|
i += 1;
|
||||||
|
});
|
||||||
|
clear();
|
||||||
|
|
||||||
|
expect(rAF).toHaveBeenCalledTimes(1);
|
||||||
|
expect(cAF).toHaveBeenCalledTimes(2);
|
||||||
|
expect(setT).not.toHaveBeenCalled();
|
||||||
|
expect(clearT).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
expect(i).toBe(0);
|
||||||
|
timeout(() => {
|
||||||
|
i += 1;
|
||||||
|
});
|
||||||
|
timeout(() => {
|
||||||
|
i += 1;
|
||||||
|
});
|
||||||
|
timeout(() => {
|
||||||
|
i += 1;
|
||||||
|
});
|
||||||
|
jest.runAllTimers();
|
||||||
|
expect(i).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('with timeout', () => {
|
||||||
|
let i = 0;
|
||||||
|
const [timeout, clear] = selfClearTimeout(100);
|
||||||
|
|
||||||
|
expect(rAF).not.toHaveBeenCalled();
|
||||||
|
expect(cAF).not.toHaveBeenCalled();
|
||||||
|
expect(setT).not.toHaveBeenCalled();
|
||||||
|
expect(clearT).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
timeout(() => {
|
||||||
|
i += 1;
|
||||||
|
});
|
||||||
|
clear();
|
||||||
|
|
||||||
|
expect(rAF).not.toHaveBeenCalled();
|
||||||
|
expect(cAF).not.toHaveBeenCalled();
|
||||||
|
expect(setT).toHaveBeenCalledTimes(1);
|
||||||
|
expect(clearT).toHaveBeenCalledTimes(2);
|
||||||
|
|
||||||
|
expect(i).toBe(0);
|
||||||
|
timeout(() => {
|
||||||
|
i += 1;
|
||||||
|
});
|
||||||
|
timeout(() => {
|
||||||
|
i += 1;
|
||||||
|
});
|
||||||
|
timeout(() => {
|
||||||
|
i += 1;
|
||||||
|
});
|
||||||
|
jest.runAllTimers();
|
||||||
|
expect(i).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('with timeout function', () => {
|
||||||
|
let i = 0;
|
||||||
|
const [timeout, clear] = selfClearTimeout(() => 100);
|
||||||
|
|
||||||
|
expect(rAF).not.toHaveBeenCalled();
|
||||||
|
expect(cAF).not.toHaveBeenCalled();
|
||||||
|
expect(setT).not.toHaveBeenCalled();
|
||||||
|
expect(clearT).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
timeout(() => {
|
||||||
|
i += 1;
|
||||||
|
});
|
||||||
|
clear();
|
||||||
|
|
||||||
|
expect(rAF).not.toHaveBeenCalled();
|
||||||
|
expect(cAF).not.toHaveBeenCalled();
|
||||||
|
expect(setT).toHaveBeenCalledTimes(1);
|
||||||
|
expect(clearT).toHaveBeenCalledTimes(2);
|
||||||
|
|
||||||
|
expect(i).toBe(0);
|
||||||
|
timeout(() => {
|
||||||
|
i += 1;
|
||||||
|
});
|
||||||
|
timeout(() => {
|
||||||
|
i += 1;
|
||||||
|
});
|
||||||
|
timeout(() => {
|
||||||
|
i += 1;
|
||||||
|
});
|
||||||
|
jest.runAllTimers();
|
||||||
|
expect(i).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user