From 2e587409a23af74e0a63c7e8535e3554081706d4 Mon Sep 17 00:00:00 2001 From: Rene Haas Date: Fri, 29 Jul 2022 17:05:59 +0200 Subject: [PATCH] improve code and fix tests --- .../overlayscrollbars/src/plugins/plugins.ts | 9 +- .../structureSetup.initialization.ts | 2 +- .../src/support/compatibility/events.ts | 7 - .../src/support/compatibility/index.ts | 1 - .../src/support/dom/traversal.ts | 6 +- .../tests/jest/options.test.ts | 22 +- .../optionsValidation.test.ts | 8 +- .../optionsValidation/transformation.test.ts | 4 +- .../optionsValidation/validation.test.ts | 2 +- .../tests/jest/plugins/plugins.test.ts | 36 ++ .../structureSetup.elements.test.ts | 427 +++++++++--------- .../tests/jest/support/dom/style.test.ts | 27 +- .../tests/jest/support/dom/traversal.test.ts | 91 +++- 13 files changed, 374 insertions(+), 268 deletions(-) delete mode 100644 packages/overlayscrollbars/src/support/compatibility/events.ts create mode 100644 packages/overlayscrollbars/tests/jest/plugins/plugins.test.ts diff --git a/packages/overlayscrollbars/src/plugins/plugins.ts b/packages/overlayscrollbars/src/plugins/plugins.ts index aa3119a..047a399 100644 --- a/packages/overlayscrollbars/src/plugins/plugins.ts +++ b/packages/overlayscrollbars/src/plugins/plugins.ts @@ -1,4 +1,4 @@ -import { assignDeep, each, isArray, keys } from 'support'; +import { each, isArray, keys } from 'support'; import { OverlayScrollbars, OverlayScrollbarsStatic } from 'overlayscrollbars'; export type PluginInstance = @@ -10,12 +10,11 @@ export type Plugin = { const pluginRegistry: Record = {}; -export const getPlugins = () => assignDeep({}, pluginRegistry); +export const getPlugins = () => pluginRegistry; export const addPlugin = (addedPlugin: Plugin | Plugin[]) => { each((isArray(addedPlugin) ? addedPlugin : [addedPlugin]) as Plugin[], (plugin) => { - each(keys(plugin), (pluginName) => { - pluginRegistry[pluginName] = plugin[pluginName]; - }); + const pluginName = keys(plugin)[0]; + pluginRegistry[pluginName] = plugin[pluginName]; }); }; diff --git a/packages/overlayscrollbars/src/setups/structureSetup/structureSetup.initialization.ts b/packages/overlayscrollbars/src/setups/structureSetup/structureSetup.initialization.ts index e928894..bfb3e85 100644 --- a/packages/overlayscrollbars/src/setups/structureSetup/structureSetup.initialization.ts +++ b/packages/overlayscrollbars/src/setups/structureSetup/structureSetup.initialization.ts @@ -20,7 +20,7 @@ export type StructureDynamicInitializationElement = DynamicInitializationElement * If element is provided, the provided element takes all its responsibilities. * DOM hierarchy isn't checked in this case, its assumed that hieararchy is correct in such a case. * - * Null or Undefined means that the environment initialization strategy is used. + * undefined means that the default initialization strategy is used. */ export interface StructureInitialization { target: InitializationTargetElement; diff --git a/packages/overlayscrollbars/src/support/compatibility/events.ts b/packages/overlayscrollbars/src/support/compatibility/events.ts deleted file mode 100644 index 2a5250b..0000000 --- a/packages/overlayscrollbars/src/support/compatibility/events.ts +++ /dev/null @@ -1,7 +0,0 @@ -export const mouseButton = (event: MouseEvent): number => { - const { button } = event; - if (!event.which && button !== undefined) { - return button & 1 ? 1 : button & 2 ? 3 : button & 4 ? 2 : 0; // eslint-disable-line no-bitwise - } - return event.which; -}; diff --git a/packages/overlayscrollbars/src/support/compatibility/index.ts b/packages/overlayscrollbars/src/support/compatibility/index.ts index 1bdf704..efa64d2 100644 --- a/packages/overlayscrollbars/src/support/compatibility/index.ts +++ b/packages/overlayscrollbars/src/support/compatibility/index.ts @@ -1,3 +1,2 @@ export * from 'support/compatibility/vendors'; export * from 'support/compatibility/apis'; -export * from 'support/compatibility/events'; diff --git a/packages/overlayscrollbars/src/support/dom/traversal.ts b/packages/overlayscrollbars/src/support/dom/traversal.ts index c1774a0..ab8f27d 100644 --- a/packages/overlayscrollbars/src/support/dom/traversal.ts +++ b/packages/overlayscrollbars/src/support/dom/traversal.ts @@ -105,11 +105,15 @@ const liesBetween = ( ): boolean => { const closestHighBoundaryElm = elm && closest(elm, highBoundarySelector); const closestDeepBoundaryElm = elm && findFirst(deepBoundarySelector, closestHighBoundaryElm); + const deepBoundaryIsValid = + closest(closestDeepBoundaryElm, highBoundarySelector) === closestHighBoundaryElm; return closestHighBoundaryElm && closestDeepBoundaryElm ? closestHighBoundaryElm === elm || closestDeepBoundaryElm === elm || - closest(closest(elm, deepBoundarySelector), highBoundarySelector) !== closestHighBoundaryElm + (deepBoundaryIsValid && + closest(closest(elm, deepBoundarySelector), highBoundarySelector) !== + closestHighBoundaryElm) : false; }; diff --git a/packages/overlayscrollbars/tests/jest/options.test.ts b/packages/overlayscrollbars/tests/jest/options.test.ts index f6274f1..c6da23c 100644 --- a/packages/overlayscrollbars/tests/jest/options.test.ts +++ b/packages/overlayscrollbars/tests/jest/options.test.ts @@ -3,36 +3,26 @@ import { defaultOptions, getOptionsDiff } from 'options'; describe('options', () => { test('defaultOptions', () => { expect(defaultOptions).toEqual({ - resize: 'none', paddingAbsolute: false, + showNativeOverlaidScrollbars: false, updating: { elementEvents: [['img', 'load']], - attributes: null, debounce: [0, 33], + attributes: null, + ignoreMutation: null, }, overflow: { x: 'scroll', y: 'scroll', }, scrollbars: { + theme: 'os-theme-dark', visibility: 'auto', autoHide: 'never', - autoHideDelay: 800, + autoHideDelay: 1300, dragScroll: true, clickScroll: false, - touch: true, - }, - textarea: { - dynWidth: false, - dynHeight: false, - inheritedAttrs: ['style', 'class'], - }, - nativeScrollbarsOverlaid: { - show: false, - initialize: false, - }, - callbacks: { - onUpdated: null, + pointers: ['mouse', 'touch', 'pen'], }, }); }); diff --git a/packages/overlayscrollbars/tests/jest/plugins/optionsValidation/optionsValidation.test.ts b/packages/overlayscrollbars/tests/jest/plugins/optionsValidation/optionsValidation.test.ts index f69ce78..3f76071 100644 --- a/packages/overlayscrollbars/tests/jest/plugins/optionsValidation/optionsValidation.test.ts +++ b/packages/overlayscrollbars/tests/jest/plugins/optionsValidation/optionsValidation.test.ts @@ -1,8 +1,12 @@ import { defaultOptions } from 'options'; -import { optionsValidationPlugin, optionsValidationPluginName } from 'plugins/optionsValidation'; +import { + optionsValidationPlugin, + optionsValidationPluginName, +} from 'plugins/optionsValidationPlugin'; const getValidationFn = () => { - const [name, instance] = optionsValidationPlugin; + const name = Object.keys(optionsValidationPlugin)[0]; + const instance = optionsValidationPlugin[name]; const validationFn = instance._; expect(name).toBe(optionsValidationPluginName); diff --git a/packages/overlayscrollbars/tests/jest/plugins/optionsValidation/transformation.test.ts b/packages/overlayscrollbars/tests/jest/plugins/optionsValidation/transformation.test.ts index f50024c..06d1950 100644 --- a/packages/overlayscrollbars/tests/jest/plugins/optionsValidation/transformation.test.ts +++ b/packages/overlayscrollbars/tests/jest/plugins/optionsValidation/transformation.test.ts @@ -2,11 +2,11 @@ import { PlainObject } from 'typings'; import { optionsTemplateTypes as oTypes, OptionsTemplate, -} from 'plugins/optionsValidation/validation'; +} from 'plugins/optionsValidationPlugin/validation'; import { transformOptions, OptionsWithOptionsTemplate, -} from 'plugins/optionsValidation/transformation'; +} from 'plugins/optionsValidationPlugin/transformation'; type TestOptionsObj = { propA: 'propA'; null: null }; type TestOptionsEnum = 'A' | 'B' | 'C'; diff --git a/packages/overlayscrollbars/tests/jest/plugins/optionsValidation/validation.test.ts b/packages/overlayscrollbars/tests/jest/plugins/optionsValidation/validation.test.ts index 95091bf..32f4318 100644 --- a/packages/overlayscrollbars/tests/jest/plugins/optionsValidation/validation.test.ts +++ b/packages/overlayscrollbars/tests/jest/plugins/optionsValidation/validation.test.ts @@ -2,7 +2,7 @@ import { validateOptions, optionsTemplateTypes as oTypes, OptionsTemplate, -} from 'plugins/optionsValidation/validation'; +} from 'plugins/optionsValidationPlugin/validation'; import { assignDeep } from 'support/utils'; type TestOptionsObj = { propA: 'propA'; null: null }; diff --git a/packages/overlayscrollbars/tests/jest/plugins/plugins.test.ts b/packages/overlayscrollbars/tests/jest/plugins/plugins.test.ts new file mode 100644 index 0000000..c298f75 --- /dev/null +++ b/packages/overlayscrollbars/tests/jest/plugins/plugins.test.ts @@ -0,0 +1,36 @@ +import { addPlugin, getPlugins } from 'plugins'; + +describe('plugins', () => { + test('getPlugins', () => { + const plugins = getPlugins(); + expect(plugins).toEqual({}); + }); + + test('addPlugin single', () => { + const myPlugin = {}; + const myPlugin2 = {}; + addPlugin({ + myPlugin, + myPlugin2, + }); + const plugins = getPlugins(); + expect(plugins.myPlugin).toBe(myPlugin); + expect(plugins.myPlugin2).toBe(undefined); // one plugin per object + }); + + test('addPlugin multiple', () => { + const myPlugin = {}; + const myPlugin2 = {}; + addPlugin([ + { + myPlugin, + }, + { + myPlugin2, + }, + ]); + const plugins = getPlugins(); + expect(plugins.myPlugin).toBe(myPlugin); + expect(plugins.myPlugin2).toBe(myPlugin2); + }); +}); diff --git a/packages/overlayscrollbars/tests/jest/setups/structureSetup/structureSetup.elements.test.ts b/packages/overlayscrollbars/tests/jest/setups/structureSetup/structureSetup.elements.test.ts index 125ec4e..bb4621a 100644 --- a/packages/overlayscrollbars/tests/jest/setups/structureSetup/structureSetup.elements.test.ts +++ b/packages/overlayscrollbars/tests/jest/setups/structureSetup/structureSetup.elements.test.ts @@ -1,4 +1,4 @@ -import { hasClass, isFunction, isHTMLElement } from 'support'; +import { hasClass, is, isFunction, isHTMLElement } from 'support'; import { dataAttributeHost } from 'classnames'; import { InternalEnvironment } from 'environment'; import { @@ -34,27 +34,42 @@ interface StructureSetupElementsProxy { destroy: () => void; } +type TargetType = 'element' | 'textarea' | 'body'; + const textareaId = 'textarea'; const textareaHostId = 'host'; const elementId = 'target'; const dynamicContent = 'text

paragraph

'; const textareaContent = ``; -const getSnapshot = () => document.body.innerHTML; -const getTarget = (textarea?: boolean) => - document.getElementById(textarea ? textareaId : elementId)!; -const fillBody = (textarea?: boolean, customDOM?: (content: string, hostId: string) => string) => { - document.body.innerHTML = ` +const getSnapshot = () => document.documentElement.outerHTML; +const getTarget = (targetType: TargetType) => { + switch (targetType) { + case 'element': + return document.getElementById(elementId)!; + case 'textarea': + return document.getElementById(textareaId)!; + case 'body': + return document.body; + default: + throw new Error('Invalid Target'); + } +}; + +const fillBody = ( + targetType: TargetType, + customDOM?: (content: string, hostId: string) => string +) => { + const textarea = targetType === 'textarea'; + const customDomResult = + customDOM && + customDOM(textarea ? textareaContent : dynamicContent, textarea ? textareaHostId : elementId); + const normalDom = textarea ? textareaContent : `
${dynamicContent}
`; + document.body.innerHTML = + targetType === 'body' + ? dynamicContent + : ` - ${ - customDOM - ? customDOM( - textarea ? textareaContent : dynamicContent, - textarea ? textareaHostId : elementId - ) - : textarea - ? textareaContent - : `
${dynamicContent}
` - } + ${customDomResult || normalDom}
`; return getSnapshot(); @@ -63,8 +78,8 @@ const clearBody = () => { document.body.innerHTML = ''; }; -const getElements = (textarea?: boolean) => { - const target = getTarget(textarea); +const getElements = (targetType: TargetType) => { + const target = getTarget(targetType); const host = document.querySelector('[data-overlayscrollbars]')!; const padding = document.querySelector('.os-padding')!; const viewport = document.querySelector('.os-viewport')!; @@ -79,8 +94,8 @@ const getElements = (textarea?: boolean) => { }; }; -const assertCorrectDOMStructure = (textarea: boolean, viewportIsTarget: boolean) => { - const { target, host, padding, viewport, content } = getElements(textarea); +const assertCorrectDOMStructure = (targetType: TargetType, viewportIsTarget: boolean) => { + const { target, host, padding, viewport, content } = getElements(targetType); if (viewportIsTarget) { expect(target).toBe(host); @@ -100,12 +115,14 @@ const assertCorrectDOMStructure = (textarea: boolean, viewportIsTarget: boolean) expect(padding.parentElement).toBe(host); } - expect(host.parentElement).toBe(document.body); - expect(host.previousElementSibling).toBe(document.querySelector('nav')); - expect(host.nextElementSibling).toBe(document.querySelector('footer')); + if (targetType !== 'body') { + expect(host.parentElement).toBe(document.body); + expect(host.previousElementSibling).toBe(document.querySelector('nav')); + expect(host.nextElementSibling).toBe(document.querySelector('footer')); + } const contentElm = content || viewport; - if (textarea) { + if (targetType === 'textarea') { expect(target.parentElement).toBe(contentElm); expect(contentElm.innerHTML).toBe(textareaContent); } else { @@ -128,7 +145,7 @@ const createStructureSetupProxy = ( }; const assertCorrectSetupElements = ( - textarea: boolean, + targetType: TargetType, setupElementsProxy: StructureSetupElementsProxy, environment: InternalEnvironment ): [StructureSetupElementsObj, () => void] => { @@ -143,11 +160,13 @@ const assertCorrectSetupElements = ( _viewportHasClass, _viewportAddRemoveClass, } = elements; - const { target, host, padding, viewport, content } = getElements(textarea); + const { target, host, padding, viewport, content } = getElements(targetType); const isTextarea = target.matches('textarea'); const isBody = target.matches('body'); - expect(textarea).toBe(isTextarea); + if (targetType !== 'element') { + expect(target.matches(targetType)).toBe(true); + } expect(_target).toBe(target); expect(_host).toBe(host); @@ -222,52 +241,36 @@ const assertCorrectSetupElements = ( if (input === undefined) { if (isStaticStrategy) { strategy = strategy as StructureStaticInitializationElement; - if (typeof strategy === 'function') { - const result = strategy(target); - if (_viewportIsTarget) { - if (kind === 'host') { - expect(elm).toBeTruthy(); - } else { - expect(elm).toBeFalsy(); - } - } else if (result && !isTextarea) { - expect(result).toBe(elm); - } else { + const resultingStrategy = typeof strategy === 'function' ? strategy(target) : strategy; + if (_viewportIsTarget) { + if (kind === 'host') { expect(elm).toBeTruthy(); + } else { + expect(elm).toBeFalsy(); } + } else if (resultingStrategy && !isTextarea) { + expect(resultingStrategy).toBe(elm); } else { expect(elm).toBeTruthy(); } } else { strategy = strategy as StructureDynamicInitializationElement; - - if (typeof strategy === 'function') { - const result = strategy(target); - const resultIsBoolean = typeof result === 'boolean'; - if (_viewportIsTarget) { - if (kind === 'host') { - expect(elm).toBeTruthy(); - } else { - expect(elm).toBeFalsy(); - } - } else if (resultIsBoolean) { - if (result) { - expect(elm).toBeTruthy(); - } else { - expect(elm).toBeFalsy(); - } - } else if (result) { - expect(elm).toBe(result); + const resultingStrategy = typeof strategy === 'function' ? strategy(target) : strategy; + const resultIsBoolean = typeof resultingStrategy === 'boolean'; + if (_viewportIsTarget) { + if (kind === 'host') { + expect(elm).toBeTruthy(); + } else { + expect(elm).toBeFalsy(); } - } else { - const strategyIsBoolean = typeof strategy === 'boolean'; - if (strategyIsBoolean) { - if (strategy) { - expect(elm).toBeTruthy(); - } else { - expect(elm).toBeFalsy(); - } + } else if (resultIsBoolean) { + if (resultingStrategy) { + expect(elm).toBeTruthy(); + } else { + expect(elm).toBeFalsy(); } + } else if (resultingStrategy) { + expect(elm).toBe(resultingStrategy); } } } @@ -345,7 +348,7 @@ const envNativeScrollbarStyling = { name: 'native scrollbar styling', env: { ...env, - _nativeScrollbarStyling: true, + _nativeScrollbarsHiding: true, }, }; const envCssCustomProperties = { @@ -359,11 +362,12 @@ const envInitStrategyMin = { name: 'initialization strategy min', env: { ...env, - _getInitializationStrategy: () => ({ - _host: null, - _viewport: () => null, - _content: () => false, - _padding: false, + _getDefaultInitialization: () => ({ + ...env._staticDefaultInitialization, + host: null, + viewport: () => null, + content: () => false, + padding: false, }), }, }; @@ -371,11 +375,12 @@ const envInitStrategyMax = { name: 'initialization strategy max', env: { ...env, - _getInitializationStrategy: () => ({ - _host: null, - _viewport: null, - _content: true, - _padding: () => true, + _getDefaultInitialization: () => ({ + ...env._staticDefaultInitialization, + host: null, + viewport: null, + content: true, + padding: () => true, }), }, }; @@ -383,21 +388,23 @@ const envInitStrategyAssigned = { name: 'initialization strategy assigned', env: { ...env, - _getInitializationStrategy: () => ({ - _host: () => document.querySelector('#host1') as HTMLElement, - _viewport: (target: HTMLElement) => target.querySelector('#viewport') as HTMLElement, - _content: (target: HTMLElement) => target.querySelector('#content'), - _padding: (target: HTMLElement) => target.querySelector('#padding'), + _getDefaultInitialization: () => ({ + ...env._staticDefaultInitialization, + host: () => document.querySelector('#host1') as HTMLElement, + viewport: (target: HTMLElement) => target.querySelector('#viewport') as HTMLElement, + content: (target: HTMLElement) => target.querySelector('#content'), + padding: (target: HTMLElement) => target.querySelector('#padding'), }), }, }; const envInitStrategyViewportIsTarget = { - name: 'initialization strategy assigned', + name: 'initialization strategy viewport is target', env: { ...env, - _nativeScrollbarStyling: true, - _getInitializationStrategy: () => ({ - _viewport: (target: HTMLElement) => target, + _nativeScrollbarsHiding: true, + _getDefaultInitialization: () => ({ + ...env._staticDefaultInitialization, + viewport: (target: HTMLElement) => !is(target, 'textarea') && target, }), }, }; @@ -420,28 +427,28 @@ describe('structureSetup', () => { mockGetEnvironment.mockImplementation(() => currEnv); }); - [false, true].forEach((isTextarea) => { - describe(isTextarea ? 'textarea' : 'element', () => { + (['element', 'textarea', 'body'] as TargetType[]).forEach((targetType) => { + describe(targetType, () => { describe('basic', () => { test('Element', () => { - const snapshot = fillBody(isTextarea); + const snapshot = fillBody(targetType); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, - createStructureSetupProxy(getTarget(isTextarea)), + targetType, + createStructureSetupProxy(getTarget(targetType)), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('Object', () => { - const snapshot = fillBody(isTextarea); + const snapshot = fillBody(targetType); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, - createStructureSetupProxy({ target: getTarget(isTextarea) }), + targetType, + createStructureSetupProxy({ target: getTarget(targetType) }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); }); @@ -450,58 +457,58 @@ describe('structureSetup', () => { describe('single assigned', () => { test('padding', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), padding: () => document.querySelector('#padding')!, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('viewport', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: () => document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), viewport: document.querySelector('#viewport')!, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('content', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), content: document.querySelector('#content')!, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); }); @@ -509,176 +516,176 @@ describe('structureSetup', () => { describe('multiple assigned', () => { test('padding viewport content', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), padding: document.querySelector('#padding')!, viewport: document.querySelector('#viewport')!, content: () => document.querySelector('#content')!, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('padding viewport', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: () => document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), padding: document.querySelector('#padding')!, viewport: document.querySelector('#viewport')!, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('padding content', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), padding: () => document.querySelector('#padding')!, content: document.querySelector('#content')!, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('viewport content', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), viewport: document.querySelector('#viewport')!, content: () => document.querySelector('#content')!, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); }); describe('single false', () => { test('padding', () => { - const snapshot = fillBody(isTextarea); + const snapshot = fillBody(targetType); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ - target: getTarget(isTextarea), + target: getTarget(targetType), padding: false, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('content', () => { - const snapshot = fillBody(isTextarea); + const snapshot = fillBody(targetType); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ - target: getTarget(isTextarea), + target: getTarget(targetType), content: () => false, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); }); describe('single true', () => { test('padding', () => { - const snapshot = fillBody(isTextarea); + const snapshot = fillBody(targetType); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ - target: getTarget(isTextarea), + target: getTarget(targetType), padding: () => true, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('content', () => { - const snapshot = fillBody(isTextarea); + const snapshot = fillBody(targetType); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ - target: getTarget(isTextarea), + target: getTarget(targetType), content: true, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); }); describe('multiple false', () => { test('padding & content', () => { - const snapshot = fillBody(isTextarea); + const snapshot = fillBody(targetType); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ - target: getTarget(isTextarea), + target: getTarget(targetType), padding: false, content: false, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); }); describe('multiple true', () => { test('padding & content', () => { - const snapshot = fillBody(isTextarea); + const snapshot = fillBody(targetType); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ - target: getTarget(isTextarea), + target: getTarget(targetType), padding: true, content: true, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); }); @@ -686,329 +693,329 @@ describe('structureSetup', () => { describe('mixed', () => { test('false: padding & content | assigned: viewport', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), padding: false, viewport: document.querySelector('#viewport')!, content: false, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('true: padding & content | assigned: viewport', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), padding: true, viewport: document.querySelector('#viewport')!, content: true, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('true: content | false: padding | assigned: viewport', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), padding: () => false, viewport: document.querySelector('#viewport')!, content: () => true, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('true: padding | false: content | assigned: viewport', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), padding: true, viewport: () => document.querySelector('#viewport')!, content: false, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('false: padding | assigned: content', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), padding: false, content: document.querySelector('#content')!, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('true: padding | assigned: content', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), padding: true, content: document.querySelector('#content')!, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('false: padding | assigned: viewport', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), padding: () => false, viewport: document.querySelector('#viewport')!, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('true: padding | assigned: viewport', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), padding: true, viewport: document.querySelector('#viewport')!, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('false: padding | assigned: viewport & content', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), viewport: document.querySelector('#viewport')!, padding: false, content: () => document.querySelector('#content')!, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('true: padding | assigned: viewport & content', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), viewport: () => document.querySelector('#viewport')!, padding: true, content: document.querySelector('#content')!, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('false: content | assigned: padding', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), padding: document.querySelector('#padding')!, content: false, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('true: content | assigned: padding', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: () => document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), padding: document.querySelector('#padding')!, content: true, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('false: content | assigned: viewport', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), viewport: () => document.querySelector('#viewport')!, content: false, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('true: content | assigned: viewport', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), viewport: document.querySelector('#viewport')!, content: true, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('false: content | assigned: padding & viewport', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), padding: () => document.querySelector('#padding')!, viewport: document.querySelector('#viewport')!, content: () => false, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); test('true: content | assigned: padding & viewport', () => { const snapshot = fillBody( - isTextarea, + targetType, (content, hostId) => `
${content}
` ); const [elements, destroy] = assertCorrectSetupElements( - isTextarea, + targetType, createStructureSetupProxy({ host: () => document.querySelector('#host')!, - target: getTarget(isTextarea), + target: getTarget(targetType), padding: document.querySelector('#padding')!, viewport: () => document.querySelector('#viewport')!, content: true, }), currEnv ); - assertCorrectDOMStructure(isTextarea, elements._viewportIsTarget); + assertCorrectDOMStructure(targetType, elements._viewportIsTarget); assertCorrectDestroy(snapshot, destroy); }); }); diff --git a/packages/overlayscrollbars/tests/jest/support/dom/style.test.ts b/packages/overlayscrollbars/tests/jest/support/dom/style.test.ts index cd08e6f..7d9deba 100644 --- a/packages/overlayscrollbars/tests/jest/support/dom/style.test.ts +++ b/packages/overlayscrollbars/tests/jest/support/dom/style.test.ts @@ -1,7 +1,6 @@ import { isEmptyObject } from 'support/utils/object'; import { isString, isPlainObject } from 'support/utils/types'; -import { style, hide, show, topRightBottomLeft } from 'support/dom/style'; -import { StyleObject } from 'typings'; +import { style, hide, show, topRightBottomLeft, directionIsRTL } from 'support/dom/style'; describe('dom style', () => { afterEach(() => { @@ -36,8 +35,6 @@ describe('dom style', () => { style(document.body, { width: '123px' }); expect(document.body.style.width).toBe('123px'); - interface O {} - expect(document.body.style.getPropertyValue('--custom')).toBe(''); style<'--custom'>(document.body, { '--custom': '123px' }); expect(document.body.style.getPropertyValue('--custom')).toBe('123px'); @@ -62,7 +59,13 @@ describe('dom style', () => { expect(document.body.style.zIndex).toBe(''); expect(document.body.style.lineHeight).toBe(''); expect(document.body.style.getPropertyValue('--custom')).toBe(''); - style<'--custom'>(document.body, { width: '123px', height: 321, opacity: '0.5', zIndex: 1, '--custom': '123px' }); + style<'--custom'>(document.body, { + width: '123px', + height: 321, + opacity: '0.5', + zIndex: 1, + '--custom': '123px', + }); expect(document.body.style.width).toBe('123px'); expect(document.body.style.height).toBe('321px'); expect(document.body.style.opacity).toBe('0.5'); @@ -138,4 +141,18 @@ describe('dom style', () => { }); }); }); + + describe('directionIsRTL', () => { + test('normal', () => { + document.body.setAttribute('style', 'direction: rtl'); + expect(directionIsRTL(document.body)).toBe(true); + + document.body.setAttribute('style', 'direction: ltr'); + expect(directionIsRTL(document.body)).toBe(false); + }); + + test('null', () => { + expect(directionIsRTL(null)).toBe(false); + }); + }); }); diff --git a/packages/overlayscrollbars/tests/jest/support/dom/traversal.test.ts b/packages/overlayscrollbars/tests/jest/support/dom/traversal.test.ts index 7227bc2..74e5c01 100644 --- a/packages/overlayscrollbars/tests/jest/support/dom/traversal.test.ts +++ b/packages/overlayscrollbars/tests/jest/support/dom/traversal.test.ts @@ -1,7 +1,18 @@ -import { find, findFirst, is, children, contents, parent, createDiv, liesBetween, createDOM } from 'support/dom'; +import { + find, + findFirst, + is, + children, + contents, + parent, + createDiv, + liesBetween, + createDOM, +} from 'support/dom'; const slotElm = document.body; -const testHTML = '

2

abc'; +const testHTML = + '

2

abc'; describe('dom traversal', () => { beforeEach(() => { @@ -225,10 +236,18 @@ describe('dom traversal', () => { }); describe('liesBetween', () => { - const elmsBetween = ['.host', '.something', '.something-a', '.something-b', '.padding', '.viewport', '.content']; + const elmsBetween = [ + '.host', + '.something', + '.something-a', + '.something-b', + '.padding', + '.viewport', + '.content', + ]; const elmsOutside = ['.allowed-a', '.allowed-b', '.allowed-c', '.deeper-a', '.deeper-b']; const elmsToTest = [...elmsBetween, ...elmsOutside]; - const domPart = (id: string, content?: string) => ` + const nestedDomPart = (id: string, content?: string) => `
@@ -244,17 +263,39 @@ describe('dom traversal', () => {
- - `; - const createTestDOM = (nestings = 0) => { + `; + const createNestedTestDOM = (nestings = 0) => { let part = ''; for (let i = 0; i < nestings + 1; i++) { - part = domPart(`host-${nestings - i}`, part); + part = nestedDomPart(`host-${nestings - i}`, part); } return part; }; - const genericTest = (nestings: number) => { + const createSpecialTestDOM = () => ` +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
`; + const genericTest = (nestings = 0) => { const allHostIds = Array(nestings) .fill(0) .map((_, index) => `#host-${index}`); @@ -263,11 +304,19 @@ describe('dom traversal', () => { const runExpectance = (id: string) => { const isRemainingId = remainingIds.includes(id); elmsToTest.forEach((elm) => { - const hostElm = findFirst(`${id}`); - const searchElm = hostElm?.classList.contains(elm.substring(1)) ? hostElm : findFirst(`${id} ${elm}`); + const hostElm = findFirst(`${id}`) as HTMLElement; + const searchElm = hostElm?.classList.contains(elm.substring(1)) + ? hostElm + : findFirst(`${id} ${elm}`); expect(liesBetween(searchElm, `${hostId}`, '.content')).toBe( - isRemainingId ? false : elmsBetween.includes(elm) ? true : elmsOutside.includes(elm) ? false : undefined + isRemainingId + ? false + : elmsBetween.includes(elm) + ? true + : elmsOutside.includes(elm) + ? false + : undefined ); }); }; @@ -295,24 +344,32 @@ describe('dom traversal', () => { } }; - test('with native closest', () => { - slotElm.innerHTML = createTestDOM(3); + test('nested with native closest', () => { + slotElm.innerHTML = createNestedTestDOM(3); genericTest(3); }); - test('with polyfill closest', () => { + test('nested with polyfill closest', () => { const original = Element.prototype.closest; // @ts-ignore Element.prototype.closest = undefined; - slotElm.innerHTML = createTestDOM(3); + slotElm.innerHTML = createNestedTestDOM(3); genericTest(3); Element.prototype.closest = original; }); + test('special with polyfill closest', () => { + slotElm.innerHTML = createSpecialTestDOM(); + genericTest(); + }); + test('text node', () => { - expect(liesBetween(createDOM('
textnodehere
')[0].firstChild, '.a', '.b')).toEqual(false); + slotElm.innerHTML = createNestedTestDOM(3); + expect(liesBetween(createDOM('
textnodehere
')[0].firstChild, '.a', '.b')).toEqual( + false + ); }); }); });