further improve repo setup

This commit is contained in:
Rene Haas
2022-07-30 20:43:46 +02:00
parent 843d627715
commit 95678c8d75
45 changed files with 153 additions and 391 deletions
-13
View File
@@ -1,13 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>OverlayScrollbars</title>
</head>
<body>
<div id="hi">hi</div>
<script type="text/javascript" src="./dist/overlayscrollbars.js"></script>
</body>
</html>
@@ -51,7 +51,7 @@ const resolveInitialization = <T>(value: any, args: any): T =>
isFunction(value) ? value.apply(0, args) : value;
const staticInitializationElement = <T extends StaticInitializationElement<any>>(
args: Parameters<Extract<T, (...args: any[]) => any>>,
args: Parameters<Extract<T, (...initializationFnArgs: any[]) => any>>,
fallbackStaticInitializationElement: FallbackInitializtationElement<T>,
defaultStaticInitializationElementStrategy: T,
staticInitializationElementValue?: T
@@ -67,7 +67,7 @@ const staticInitializationElement = <T extends StaticInitializationElement<any>>
};
const dynamicInitializationElement = <T extends DynamicInitializationElement<any>>(
args: Parameters<Extract<T, (...args: any[]) => any>>,
args: Parameters<Extract<T, (...initializationFnArgs: any[]) => any>>,
fallbackDynamicInitializationElement: FallbackInitializtationElement<T>,
defaultDynamicInitializationElementStrategy: T,
dynamicInitializationElementValue?: T
@@ -152,6 +152,7 @@ export interface OverlayScrollbars {
* Height intrinsic detection use "content: true" init strategy - or open ticket for custom height intrinsic observer
*/
// eslint-disable-next-line @typescript-eslint/no-redeclare
export const OverlayScrollbars: OverlayScrollbarsStatic = (
target,
options?,
@@ -203,7 +204,7 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
destroyed = true;
// eslint-disable-next-line no-use-before-define
// eslint-disable-next-line @typescript-eslint/no-use-before-define
triggerEvent('destroyed', [instance, !!canceled]);
removeEvent();
};
@@ -62,11 +62,8 @@ export function style<CustomCssProps>(
elm: HTMLElement | false | null | undefined,
styles: StyleObject<CustomCssProps>
): void;
export function style<CustomCssProps>(
elm: HTMLElement | false | null | undefined,
styles: string
): string;
export function style<CustomCssProps>(
export function style(elm: HTMLElement | false | null | undefined, styles: string): string;
export function style(
elm: HTMLElement | false | null | undefined,
styles: Array<string> | string
): { [key: string]: string };
@@ -21,6 +21,7 @@ const manageListener = <EventMap extends Record<string, any[]>>(
export const createEventListenerHub = <EventMap extends Record<string, any[]>>(
initialEventListeners?: InitialEventListeners<EventMap>
) => {
// eslint-disable-next-line @typescript-eslint/no-shadow
type EventListener<Name extends keyof EventMap = keyof EventMap> = (
...args: EventMap[Name]
) => void;
@@ -87,7 +88,7 @@ export const createEventListenerHub = <EventMap extends Record<string, any[]>>(
each(from(eventSet), (event) => {
if (args && !isEmptyArray(args)) {
(event as (...args: EventMap[keyof EventMap]) => void).apply(0, args as any);
(event as (...eventArgs: EventMap[keyof EventMap]) => void).apply(0, args as any);
} else {
(event as () => void)();
}
@@ -9,9 +9,7 @@ interface GenericLexicon<T extends boolean> {
_lt: T extends true ? 'l' : 't';
}
export interface Lexicon<T extends boolean> extends GenericLexicon<T> {
// _inverted: Lexicon<T extends true ? false : true>;
}
export type Lexicon<T extends boolean> = GenericLexicon<T>
export const getLexicon = <T extends boolean = false>(horizontal?: T): Lexicon<T> =>
({
@@ -96,7 +96,7 @@ export const assignDeep: AssignDeep = <T, U, V, W, X, Y, Z>(
* @param obj The Object.
*/
export const isEmptyObject = (obj: any): boolean => {
/* eslint-disable no-restricted-syntax, guard-for-in */
// eslint-disable-next-line no-restricted-syntax, no-unreachable-loop, guard-for-in
for (const name in obj) return false;
return true;
/* eslint-enable */
@@ -229,16 +229,16 @@ const assertCorrectSetupElements = (
strategy: StructureStaticInitializationElement | StructureDynamicInitializationElement,
kind: 'padding' | 'viewport' | 'content' | 'host'
) => {
const input = isFunction(inputStrategy) ? inputStrategy(target) : inputStrategy;
if (input) {
const resolvedInputStrategy = isFunction(inputStrategy) ? inputStrategy(target) : inputStrategy;
if (resolvedInputStrategy) {
if (!_viewportIsTarget) {
expect(elm).toBeTruthy();
}
} else {
if (input === false) {
if (resolvedInputStrategy === false) {
expect(elm).toBeFalsy();
}
if (input === undefined) {
if (resolvedInputStrategy === undefined) {
if (isStaticStrategy) {
strategy = strategy as StructureStaticInitializationElement;
const resultingStrategy = typeof strategy === 'function' ? strategy(target) : strategy;
@@ -11,7 +11,12 @@ jest.mock('support/compatibility/apis', () => {
});
// eslint-disable-next-line no-return-await
const timeout = async (timeout = 100) => await new Promise((r) => setTimeout(r, timeout));
const timeout = async (timeoutMs = 100) => {
const result = await new Promise((r) => {
setTimeout(r, timeoutMs);
});
return result;
};
describe('function', () => {
test('noop', () => {
@@ -1,9 +1,13 @@
import 'index.scss';
import './index.scss';
import should from 'should';
import { generateSelectCallback, iterateSelect } from '@/testing-browser/Select';
import { timeout } from '@/testing-browser/timeout';
import { setTestResult, waitForOrFailTest } from '@/testing-browser/TestResult';
import {
generateSelectCallback,
iterateSelect,
timeout,
setTestResult,
waitForOrFailTest,
} from '@local/browser-testing';
import {
appendChildren,
createDiv,
@@ -302,8 +306,8 @@ const addRemoveElementsTest = async (
| DOMContentObserverResult[]
| undefined;
if (changeThrough && !isArray(changeThrough)) {
addChangeThrough = (changeThrough as SeparateChangeThrough).added;
removeChangeThrough = (changeThrough as SeparateChangeThrough).removed;
addChangeThrough = changeThrough.added;
removeChangeThrough = changeThrough.removed;
}
const addElm = async () => {
@@ -685,12 +689,24 @@ const triggerBetweenSummaryChange = async () => {
await triggerSummaryElemet(summaryBetween);
};
addRemoveTargetElms?.addEventListener('click', addRemoveTargetElmsFn);
addRemoveTargetContentElms?.addEventListener('click', addRemoveTargetContentElmsFn);
addRemoveTargetContentBetweenElms?.addEventListener('click', addRemoveTargetContentBetweenElmsFn);
addRemoveImgElms?.addEventListener('click', () => addRemoveImgElmsFn());
addRemoveTransitionElms?.addEventListener('click', addRemoveTransitionElmsFn);
ignoreTargetChange?.addEventListener('click', ignoreTargetChangeFn);
addRemoveTargetElms?.addEventListener('click', () => {
addRemoveTargetElmsFn();
});
addRemoveTargetContentElms?.addEventListener('click', () => {
addRemoveTargetContentElmsFn();
});
addRemoveTargetContentBetweenElms?.addEventListener('click', () => {
addRemoveTargetContentBetweenElmsFn();
});
addRemoveImgElms?.addEventListener('click', () => {
addRemoveImgElmsFn();
});
addRemoveTransitionElms?.addEventListener('click', () => {
addRemoveTransitionElmsFn();
});
ignoreTargetChange?.addEventListener('click', () => {
ignoreTargetChangeFn();
});
setTargetAttr?.addEventListener('change', attrChangeListener(targetElm));
setFilteredTargetAttr?.addEventListener('change', attrChangeListener(targetElm));
setContentAttr?.addEventListener('change', attrChangeListener(contentElmAttrChange));
@@ -743,6 +759,8 @@ const start = async () => {
setTestResult(true);
};
startBtn?.addEventListener('click', start);
startBtn?.addEventListener('click', () => {
start();
});
export { start };
@@ -2,16 +2,17 @@ import 'index.scss';
import './index.scss';
import './handleEnvironment';
import should from 'should';
import { hasDimensions, offsetSize, WH, style } from 'support';
import { addPlugin, sizeObserverPlugin } from 'plugins';
import { createSizeObserver } from 'observers/sizeObserver';
import {
generateClassChangeSelectCallback,
iterateSelect,
selectOption,
} from '@/testing-browser/Select';
import { setTestResult, waitForOrFailTest } from '@/testing-browser/TestResult';
import { timeout } from '@/testing-browser/timeout';
timeout,
setTestResult,
waitForOrFailTest,
} from '@local/browser-testing';
import { hasDimensions, offsetSize, WH, style } from 'support';
import { addPlugin, sizeObserverPlugin } from 'plugins';
import { createSizeObserver } from 'observers/sizeObserver';
if (!window.ResizeObserver) {
addPlugin(sizeObserverPlugin);
@@ -2,16 +2,17 @@ import 'index.scss';
import './index.scss';
import './handleEnvironment';
import should from 'should';
import { offsetSize } from 'support';
import { createTrinsicObserver } from 'observers/trinsicObserver';
import { addPlugin, sizeObserverPlugin } from 'plugins';
import {
generateClassChangeSelectCallback,
iterateSelect,
selectOption,
} from '@/testing-browser/Select';
import { timeout } from '@/testing-browser/timeout';
import { setTestResult, waitForOrFailTest } from '@/testing-browser/TestResult';
timeout,
setTestResult,
waitForOrFailTest,
} from '@local/browser-testing';
import { offsetSize } from 'support';
import { createTrinsicObserver } from 'observers/trinsicObserver';
import { addPlugin, sizeObserverPlugin } from 'plugins';
if (!window.ResizeObserver) {
addPlugin(sizeObserverPlugin);
@@ -1,10 +1,8 @@
import './index.scss';
import 'index.scss';
import should from 'should';
import { timeout, setTestResult, waitForOrFailTest, resize } from '@local/browser-testing';
import { OverlayScrollbars } from 'overlayscrollbars';
import { resize } from '@/testing-browser/Resize';
import { timeout } from '@/testing-browser/timeout';
import { setTestResult, waitForOrFailTest } from '@/testing-browser/TestResult';
import { addClass, each, isArray, removeAttr, style } from 'support';
import { addPlugin, scrollbarsHidingPlugin, sizeObserverPlugin } from 'plugins';
@@ -3,6 +3,14 @@ import './index.scss';
import './handleEnvironment';
import { OverlayScrollbars } from 'overlayscrollbars';
import should from 'should';
import {
generateClassChangeSelectCallback,
iterateSelect,
resize,
timeout,
setTestResult,
waitForOrFailTest,
} from '@local/browser-testing';
import {
assignDeep,
clientSize,
@@ -18,10 +26,6 @@ import {
createDOM,
hasClass,
} from 'support';
import { resize } from '@/testing-browser/Resize';
import { setTestResult, waitForOrFailTest } from '@/testing-browser/TestResult';
import { generateClassChangeSelectCallback, iterateSelect } from '@/testing-browser/Select';
import { timeout } from '@/testing-browser/timeout';
import { Options } from 'options';
import { DeepPartial } from 'typings';
import { addPlugin, scrollbarsHidingPlugin, sizeObserverPlugin } from 'plugins';
@@ -97,9 +101,9 @@ const fixedDigitsOffset = 3;
const startBtn: HTMLButtonElement | null = document.querySelector('#start');
const target: HTMLElement | null = document.querySelector('#target');
const targetMetrics: HTMLElement | null = document.querySelector('#targetMetrics');
const targetMetricsElement: HTMLElement | null = document.querySelector('#targetMetrics');
const comparison: HTMLElement | null = document.querySelector('#comparison');
const comparisonMetrics: HTMLElement | null = document.querySelector('#comparisonMetrics');
const comparisonMetricsElement: HTMLElement | null = document.querySelector('#comparisonMetrics');
const targetResize: HTMLElement | null = document.querySelector('#target .resize');
const comparisonResize: HTMLElement | null = document.querySelector('#comparison .resize');
const targetPercent: HTMLElement | null = document.querySelector('#target .percent');
@@ -213,9 +217,9 @@ const getMetrics = (elm: HTMLElement): Metrics => {
};
if (elmIsTarget) {
targetMetrics!.textContent = JSON.stringify(results, null, 2);
targetMetricsElement!.textContent = JSON.stringify(results, null, 2);
} else {
comparisonMetrics!.textContent = JSON.stringify(results, null, 2);
comparisonMetricsElement!.textContent = JSON.stringify(results, null, 2);
}
return results;
-5
View File
@@ -2,10 +2,5 @@
"extends": "@local/tsconfig",
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"@/playwright/rollup": ["../playwright.rollup"],
"@/testing-browser*": ["../../testing-browser/src*"],
"@/overlayscrollbars*": ["../../overlayscrollbars/src*"]
}
}
}
-5
View File
@@ -1,5 +0,0 @@
{
"private": true,
"name": "testing",
"version": "0.0.0"
}
-107
View File
@@ -1,107 +0,0 @@
// @ts-ignore
import {
createDiv,
appendChildren,
parent,
style,
on,
off,
addClass,
WH,
XY,
clientSize,
each,
} from '@/overlayscrollbars/support';
type ResizeListener = (width: number, height: number) => void;
export const resize = (element: HTMLElement) => {
const resizeListeners: ResizeListener[] = [];
const strMouseTouchDownEvent = 'mousedown touchstart';
const strMouseTouchUpEvent = 'mouseup touchend';
const strMouseTouchMoveEvent = 'mousemove touchmove';
const strSelectStartEvent = 'selectstart';
const dragStartSize: WH<number> = { w: 0, h: 0 };
const dragStartPosition: XY<number> = { x: 0, y: 0 };
const resizeBtn = createDiv('resizeBtn');
appendChildren(element, resizeBtn);
addClass(element, 'resizer');
let dragResizeBtn: HTMLElement | undefined;
let dragResizer: HTMLElement | undefined;
const onSelectStart = (event: Event) => {
event.preventDefault();
return false;
};
const resizerResize = (event: MouseEvent | TouchEvent) => {
const isTouchEvent = (event as TouchEvent).touches !== undefined;
const mouseOffsetHolder = isTouchEvent
? (event as TouchEvent).touches[0]
: (event as MouseEvent);
const sizeStyle = {
width: dragStartSize.w + mouseOffsetHolder.pageX - dragStartPosition.x,
height: dragStartSize.h + mouseOffsetHolder.pageY - dragStartPosition.y,
};
style(dragResizer, sizeStyle);
each(resizeListeners, (listener: ResizeListener) => {
if (listener) {
listener(sizeStyle.width, sizeStyle.height);
}
});
event.stopPropagation();
};
const resizerResized = () => {
off(document, strSelectStartEvent, onSelectStart);
off(document, strMouseTouchMoveEvent, resizerResize);
off(document, strMouseTouchUpEvent, resizerResized);
dragResizer = undefined;
dragResizeBtn = undefined;
};
on(
resizeBtn,
strMouseTouchDownEvent,
(event: MouseEvent | TouchEvent) => {
const { currentTarget } = event;
const correctButton = (event as MouseEvent).buttons === 1 || event.which === 1;
const isTouchEvent = (event as TouchEvent).touches !== undefined;
const mouseOffsetHolder = isTouchEvent
? (event as TouchEvent).touches[0]
: (event as MouseEvent);
if (correctButton || isTouchEvent) {
dragStartPosition.x = mouseOffsetHolder.pageX;
dragStartPosition.y = mouseOffsetHolder.pageY;
dragResizeBtn = currentTarget as HTMLElement;
dragResizer = parent(currentTarget as HTMLElement) as HTMLElement;
const cSize = clientSize(element);
dragStartSize.w = cSize.w;
dragStartSize.h = cSize.h;
on(document, strSelectStartEvent, onSelectStart, { _passive: false });
on(document, strMouseTouchMoveEvent, resizerResize, { _passive: false });
on(document, strMouseTouchUpEvent, resizerResized, { _passive: false });
event.preventDefault();
event.stopPropagation();
}
},
{ _passive: false }
);
return {
addResizeListener(listener: ResizeListener) {
resizeListeners.push(listener);
},
};
};
-110
View File
@@ -1,110 +0,0 @@
function isEvent(obj: any): obj is Event {
return obj instanceof Event || !!obj.target;
}
// eslint-disable-next-line
const noop = <T>(): T => {
return {} as T;
};
const getSelectOptions = (selectElement: HTMLSelectElement) =>
Array.from(selectElement.options).map((option) => option.value);
export const generateSelectCallback =
(
targetElms: HTMLElement[] | HTMLElement | null,
callback: (
targetAffectedElm: HTMLElement,
possibleValues: string[],
selectedValue: string
) => any
) =>
(event: Event | HTMLSelectElement | null) => {
const target: HTMLSelectElement | null = isEvent(event)
? (event.target as HTMLSelectElement)
: event;
if (target) {
const selectedOption = target.value;
const selectOptions = getSelectOptions(target);
const elmsArr = Array.isArray(targetElms) ? targetElms : [targetElms];
elmsArr.forEach((elm) => {
if (elm) {
callback(elm, selectOptions, selectedOption);
}
});
}
};
export const generateClassChangeSelectCallback = (targetElms: HTMLElement[] | HTMLElement | null) =>
generateSelectCallback(targetElms, (targetAffectedElm, possibleValues, selectedValue) => {
possibleValues.forEach((clazz) => targetAffectedElm.classList.remove(clazz));
targetAffectedElm.classList.add(selectedValue);
});
export const selectOption = (
select: HTMLSelectElement | null,
selectedOption: string | number
): boolean => {
if (!select) {
return false;
}
const options = getSelectOptions(select);
const currValue = select.value;
if (selectedOption === currValue) {
return false;
}
if (typeof selectedOption === 'string' && options.includes(selectedOption)) {
select.value = selectedOption;
} else if (
typeof selectedOption === 'number' &&
options.length < selectedOption &&
selectedOption > -1
) {
select.selectedIndex = selectedOption;
}
let event;
if (typeof Event === 'function') {
event = new Event('change');
} else {
event = document.createEvent('Event');
event.initEvent('change', true, true);
}
select.dispatchEvent(event);
return true;
};
export const iterateSelect = async <T>(
select: HTMLSelectElement | null,
options?: {
filter?: (value: string, index: number, array: string[]) => boolean;
beforeEach?: () => T | Promise<T>;
check?: (input: T, selectedOptions: string) => void | Promise<void>;
afterEach?: () => void | Promise<void>;
}
) => {
if (select) {
const { beforeEach = noop, check = noop, afterEach = noop, filter } = options || {};
const selectOptions = getSelectOptions(select);
const selectOptionsReversed = getSelectOptions(select).reverse();
const iterateOptions = [...selectOptions, ...selectOptionsReversed].filter(
filter || (() => true)
);
for (let i = 0; i < iterateOptions.length; i++) {
const option = iterateOptions[i];
// eslint-disable-next-line
const beforeEachObj: T = await beforeEach();
if (selectOption(select, option)) {
// eslint-disable-next-line
await check(beforeEachObj, option);
// eslint-disable-next-line
await afterEach();
}
}
}
};
@@ -1,33 +0,0 @@
import { waitFor, waitForOptions } from '@testing-library/dom';
const getTestResultElm = () => document.getElementById('testResult');
export const setTestResult = (result: boolean | null) => {
const elm = getTestResultElm();
if (elm) {
if (typeof result === 'boolean') {
if (result) {
if (elm.getAttribute('class') === 'failed') {
return;
}
}
elm.setAttribute('class', result ? 'passed' : 'failed');
} else {
elm.removeAttribute('class');
}
}
};
export const testPassed = (): boolean => {
const elm = getTestResultElm();
return elm ? elm.getAttribute('class') === 'passed' : false;
};
export const waitForOrFailTest = <T>(callback: () => T | Promise<T>, options?: waitForOptions) =>
waitFor(callback, {
...options,
onTimeout(error: Error): Error {
setTestResult(false);
return error;
},
});
-1
View File
@@ -1 +0,0 @@
export const timeout = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
-3
View File
@@ -1,3 +0,0 @@
export * from 'Select';
export * from 'TestResult';
export * from 'Timeout';
-6
View File
@@ -1,6 +0,0 @@
{
"extends": "@local/tsconfig",
"compilerOptions": {
"baseUrl": "./src/"
}
}