mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-06-05 10:42:27 +03:00
WIP: v2.0.0 intial commit
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
import { jsAPI, cssProperty, cssPropertyValue } from 'core/compatibility/vendors';
|
||||
|
||||
describe('vendors', () => {
|
||||
describe('jsAPI', () => {
|
||||
test('gets MutationObserver', () => {
|
||||
const mutationObserver = jsAPI('MutationObserver');
|
||||
expect(mutationObserver).toBe(MutationObserver);
|
||||
});
|
||||
|
||||
test('gets requestAnimationFrame', () => {
|
||||
const rAF = jsAPI('requestAnimationFrame');
|
||||
expect(rAF).toBe(requestAnimationFrame);
|
||||
});
|
||||
|
||||
test('gets undefined', () => {
|
||||
const apiWhichDontExist = jsAPI('apiWhichDontExist');
|
||||
expect(apiWhichDontExist).toBeUndefined();
|
||||
});
|
||||
|
||||
test('cache is used', () => {
|
||||
const name = 'CacheTestJsAPIWhichDontExists';
|
||||
const fn = () => { };
|
||||
window[name] = fn;
|
||||
|
||||
expect(jsAPI(name)).toBe(fn);
|
||||
|
||||
delete window[name];
|
||||
|
||||
expect(jsAPI(name)).toBe(fn);
|
||||
});
|
||||
});
|
||||
|
||||
describe('cssProperty', () => {
|
||||
test('gets transform', () => {
|
||||
const transform = cssProperty('transform');
|
||||
expect(transform).not.toBeUndefined();
|
||||
});
|
||||
|
||||
test('gets undefined', () => {
|
||||
const propWhichDontExist = cssProperty('propWhichDontExist');
|
||||
expect(propWhichDontExist).toBeUndefined();
|
||||
});
|
||||
|
||||
test('cache is used', () => {
|
||||
const spy = jest.spyOn(Document.prototype, 'createElement');
|
||||
|
||||
cssProperty('cachePropWhichDontExist');
|
||||
expect(spy).toBeCalledTimes(1);
|
||||
cssProperty('cachePropWhichDontExist');
|
||||
expect(spy).toBeCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('cssPropertyValue', () => {
|
||||
test('gets calc', () => {
|
||||
const calc = cssPropertyValue('width', 'calc', '(1px)');
|
||||
expect(calc).not.toBeUndefined();
|
||||
});
|
||||
|
||||
test('gets calc as second value', () => {
|
||||
const calc = cssPropertyValue('width', 'nonexistend-calc calc', '(1px)');
|
||||
expect(calc).not.toBeUndefined();
|
||||
});
|
||||
|
||||
test('gets undefined', () => {
|
||||
const nonexistend = cssPropertyValue('width', 'nonexistend');
|
||||
expect(nonexistend).toBeUndefined();
|
||||
});
|
||||
|
||||
test('cache is used', () => {
|
||||
let expectedCalledTimes = 0;
|
||||
const spy = jest.spyOn(Document.prototype, 'createElement');
|
||||
const run = (propName: string, propValue: string) => {
|
||||
expectedCalledTimes++;
|
||||
cssPropertyValue(propName, propValue);
|
||||
expect(spy).toBeCalledTimes(expectedCalledTimes);
|
||||
cssPropertyValue(propName, propValue);
|
||||
expect(spy).toBeCalledTimes(expectedCalledTimes);
|
||||
}
|
||||
|
||||
run('width', 'cacheNonexistendValue');
|
||||
run('height', 'cacheNonexistendValue');
|
||||
run('width', 'cacheNonexistendValue cacheNonexistendValue2');
|
||||
run('height', 'cacheNonexistendValue cacheNonexistendValue2');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
import { attr, removeAttr, val, scrollLeft, scrollTop } from 'core/dom/attributes';
|
||||
|
||||
const testElm = document.body;
|
||||
const setAttribute = (name: string, value: string) => {
|
||||
testElm.setAttribute(name, value);
|
||||
};
|
||||
const setScrollLeft = (value: number) => {
|
||||
testElm.scrollLeft = value;
|
||||
};
|
||||
const setScrollTop = (value: number) => {
|
||||
testElm.scrollTop = value;
|
||||
};
|
||||
const removeAttribute = (name: string) => {
|
||||
testElm.removeAttribute(name);
|
||||
};
|
||||
|
||||
describe('dom attributes', () => {
|
||||
describe('attr', () => {
|
||||
test('get', () => {
|
||||
const attrName = 'data-test-get';
|
||||
|
||||
setAttribute(attrName, '123');
|
||||
expect(attr(testElm, attrName)).toBe('123');
|
||||
|
||||
setAttribute(attrName, 'abc');
|
||||
expect(attr(testElm, attrName)).toBe('abc');
|
||||
|
||||
removeAttribute(attrName);
|
||||
});
|
||||
|
||||
test('set', () => {
|
||||
const attrName = 'data-test-set';
|
||||
|
||||
attr(testElm, attrName, '123');
|
||||
expect(attr(testElm, attrName)).toBe('123');
|
||||
|
||||
attr(testElm, attrName, 'abc');
|
||||
expect(attr(testElm, attrName)).toBe('abc');
|
||||
|
||||
removeAttribute(attrName);
|
||||
});
|
||||
});
|
||||
|
||||
describe('scrollLeft', () => {
|
||||
test('get', () => {
|
||||
setScrollLeft(100);
|
||||
expect(scrollLeft(testElm)).toBe(100);
|
||||
setScrollLeft(0);
|
||||
});
|
||||
|
||||
test('set', () => {
|
||||
scrollLeft(testElm, 100);
|
||||
expect(scrollLeft(testElm)).toBe(100);
|
||||
setScrollLeft(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('scrollTop', () => {
|
||||
test('get', () => {
|
||||
setScrollTop(100);
|
||||
expect(scrollTop(testElm)).toBe(100);
|
||||
setScrollTop(0);
|
||||
});
|
||||
|
||||
test('set', () => {
|
||||
scrollTop(testElm, 100);
|
||||
expect(scrollTop(testElm)).toBe(100);
|
||||
setScrollTop(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('val', () => {
|
||||
const input = document.createElement('input');
|
||||
|
||||
test('get', () => {
|
||||
input.value = 'hi';
|
||||
expect(val(input)).toBe('hi');
|
||||
input.value = '';
|
||||
});
|
||||
|
||||
test('set', () => {
|
||||
val(input, 'hi2');
|
||||
expect(val(input)).toBe('hi2');
|
||||
val(input, '');
|
||||
expect(val(input)).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
test('remove attribute', () => {
|
||||
const attrName = 'data-test-remove';
|
||||
|
||||
setAttribute(attrName, '123');
|
||||
removeAttr(testElm, attrName);
|
||||
|
||||
expect(attr(testElm, attrName)).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,85 @@
|
||||
import { addClass, removeClass, hasClass, conditionalClass } from 'core/dom/classes';
|
||||
|
||||
const testElm = document.body;
|
||||
const removeAllClassNames = () => {
|
||||
while (testElm.classList.length > 0) {
|
||||
const classToRemove = testElm.classList.item(0);
|
||||
if (classToRemove) {
|
||||
testElm.classList.remove(classToRemove);
|
||||
}
|
||||
}
|
||||
};
|
||||
const hasClassName = (className: string) => {
|
||||
return testElm.classList.contains(className);
|
||||
};
|
||||
|
||||
describe('dom class names', () => {
|
||||
afterEach(() => {
|
||||
removeAllClassNames();
|
||||
});
|
||||
|
||||
test('add none', () => {
|
||||
addClass(testElm, '');
|
||||
// @ts-ignore
|
||||
addClass(testElm, null);
|
||||
// @ts-ignore
|
||||
addClass(testElm, 2);
|
||||
expect(testElm.classList.length).toBe(0);
|
||||
});
|
||||
|
||||
test('add single', () => {
|
||||
addClass(testElm, 'test-class');
|
||||
expect(hasClassName('test-class')).toBe(true);
|
||||
});
|
||||
|
||||
test('add multiple', () => {
|
||||
addClass(testElm, 'test-class test-class2');
|
||||
expect(hasClassName('test-class')).toBe(true);
|
||||
expect(hasClassName('test-class2')).toBe(true);
|
||||
});
|
||||
|
||||
test('remove none', () => {
|
||||
addClass(testElm, 'test-class');
|
||||
removeClass(testElm, '');
|
||||
// @ts-ignore
|
||||
removeClass(testElm, null);
|
||||
// @ts-ignore
|
||||
removeClass(testElm, 2);
|
||||
expect(testElm.classList.length).toBe(1);
|
||||
});
|
||||
|
||||
test('remove single', () => {
|
||||
addClass(testElm, 'test-class');
|
||||
expect(hasClassName('test-class')).toBe(true);
|
||||
removeClass(testElm, 'test-class');
|
||||
expect(hasClassName('test-class')).toBe(false);
|
||||
});
|
||||
|
||||
test('remove multiple', () => {
|
||||
addClass(testElm, 'test-class test-class2');
|
||||
removeClass(testElm, 'test-class test-class2');
|
||||
expect(hasClassName('test-class')).toBe(false);
|
||||
expect(hasClassName('test-class2')).toBe(false);
|
||||
});
|
||||
|
||||
test('has', () => {
|
||||
addClass(testElm, 'test-class');
|
||||
expect(hasClass(testElm, 'test-class')).toBe(true);
|
||||
});
|
||||
|
||||
test('conditional single', () => {
|
||||
conditionalClass(testElm, 'test-class', true)
|
||||
expect(hasClass(testElm, 'test-class')).toBe(true);
|
||||
conditionalClass(testElm, 'test-class', false)
|
||||
expect(hasClass(testElm, 'test-class')).toBe(false);
|
||||
});
|
||||
|
||||
test('conditional multiple', () => {
|
||||
conditionalClass(testElm, 'test-class test-class2', true)
|
||||
expect(hasClass(testElm, 'test-class')).toBe(true);
|
||||
expect(hasClass(testElm, 'test-class2')).toBe(true);
|
||||
conditionalClass(testElm, 'test-class test-class2', false)
|
||||
expect(hasClass(testElm, 'test-class')).toBe(false);
|
||||
expect(hasClass(testElm, 'test-class2')).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,74 @@
|
||||
import { each } from 'core/utils';
|
||||
import { createDiv, createDOM } from 'core/dom/create';
|
||||
|
||||
const slotElm = document.body;
|
||||
const testHTML = '<div id="parent" class="parent-class"><div id="child" class="child-class"></div></div><p>2</p><input type="text" value="3"></input>';
|
||||
|
||||
describe('dom create', () => {
|
||||
afterEach(() => {
|
||||
slotElm.innerHTML = '';
|
||||
});
|
||||
|
||||
describe('createDiv', () => {
|
||||
test('correct element tag', () => {
|
||||
const createdDiv = createDiv();
|
||||
expect(createdDiv.tagName.toLowerCase()).toBe('div');
|
||||
});
|
||||
|
||||
test('no class names', () => {
|
||||
const createdDiv = createDiv();
|
||||
expect(createdDiv.classList.length).toBe(0);
|
||||
});
|
||||
|
||||
test('no style', () => {
|
||||
const createdDiv = createDiv();
|
||||
expect(createdDiv.style.length).toBe(0);
|
||||
});
|
||||
|
||||
test('not in document', () => {
|
||||
const createdDiv = createDiv();
|
||||
expect(createdDiv.parentElement).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('createDOM', () => {
|
||||
test('correct elements length', () => {
|
||||
const dom = createDOM(testHTML);
|
||||
expect(dom.length).toBe(3);
|
||||
});
|
||||
|
||||
test('elements arent child of any element', () => {
|
||||
const dom = createDOM(testHTML);
|
||||
each(dom, (elm) => {
|
||||
expect(elm.parentElement).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
test('elements are created correctly', () => {
|
||||
const dom = createDOM(testHTML);
|
||||
each(dom, (elm) => {
|
||||
slotElm.append(elm);
|
||||
});
|
||||
const parentElm = slotElm.querySelector('#parent');
|
||||
const childElm = slotElm.querySelector('#child');
|
||||
const pElm = slotElm.querySelector('p');
|
||||
const inputElm = slotElm.querySelector('input');
|
||||
|
||||
expect(parentElm).toBeDefined();
|
||||
expect(childElm).toBeDefined();
|
||||
expect(pElm).toBeDefined();
|
||||
expect(inputElm).toBeDefined();
|
||||
|
||||
expect(parentElm?.parentElement).toBe(slotElm);
|
||||
expect(pElm?.parentElement).toBe(slotElm);
|
||||
expect(inputElm?.parentElement).toBe(slotElm);
|
||||
expect(childElm?.parentElement).toBe(parentElm);
|
||||
|
||||
expect(parentElm?.classList.contains('parent-class')).toBeTruthy();
|
||||
expect(childElm?.classList.contains('child-class')).toBeTruthy();
|
||||
expect(pElm?.textContent).toBe('2');
|
||||
expect(inputElm?.value).toBe('3');
|
||||
expect(inputElm?.getAttribute('type')).toBe('text');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,349 @@
|
||||
import { createDiv, contents, appendChildren, prependChildren, insertBefore, insertAfter, removeElements } from 'core/dom';
|
||||
import { each, isArray, isHTMLElement } from 'core/utils';
|
||||
|
||||
const slotElm = document.body;
|
||||
const fillSlotElm = () => {
|
||||
const content = [createDiv(), createDiv(), createDiv(), createDiv(), createDiv()];
|
||||
content.forEach((elm, i) => {
|
||||
elm.setAttribute('id', i.toString());
|
||||
slotElm.append(elm);
|
||||
});
|
||||
};
|
||||
const clearSlotElm = () => {
|
||||
contents(slotElm).forEach(elm => {
|
||||
elm.remove();
|
||||
});
|
||||
};
|
||||
const compareToNative = (target: Node, method: string, snapshot: Array<Node>, elms: Element | Node | Array<Element> | Array<Node>, compareIds: boolean = false) => {
|
||||
if (!compareIds) {
|
||||
if (!isArray(elms)) {
|
||||
elms = [elms];
|
||||
}
|
||||
elms.forEach(e => {
|
||||
if (isHTMLElement(e))
|
||||
e.remove();
|
||||
});
|
||||
target[method](...elms);
|
||||
expect(Array.from(slotElm.childNodes)).toEqual(snapshot);
|
||||
}
|
||||
else {
|
||||
clearSlotElm();
|
||||
fillSlotElm();
|
||||
|
||||
|
||||
if (!isArray(elms)) {
|
||||
elms = [elms];
|
||||
}
|
||||
|
||||
const realElms: Array<Element> = [];
|
||||
elms.forEach((elm) => {
|
||||
slotElm.childNodes.forEach((child) => {
|
||||
if (isHTMLElement(child)) {
|
||||
if (isHTMLElement(elm) && child.getAttribute('id') === elm.getAttribute('id')) {
|
||||
realElms.push(child);
|
||||
}
|
||||
if (compareIds && target !== slotElm && isHTMLElement(target) && child.getAttribute('id') === target.getAttribute('id')) {
|
||||
target = child;
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
target[method](...realElms);
|
||||
|
||||
const mapIds = (elm: Node) => isHTMLElement(elm) ? elm.getAttribute('id') || '' : '';
|
||||
const snapshotIdArr: Array<string> = snapshot.map(mapIds);
|
||||
const elmsIdArr: Array<string> = Array.from(slotElm.childNodes).map(mapIds);
|
||||
|
||||
expect(JSON.stringify(elmsIdArr)).toEqual(JSON.stringify(snapshotIdArr));
|
||||
}
|
||||
};
|
||||
|
||||
describe('dom manipulation', () => {
|
||||
beforeEach(() => fillSlotElm());
|
||||
afterEach(() => clearSlotElm());
|
||||
|
||||
describe('appendChildren', () => {
|
||||
test('single created', () => {
|
||||
const createdDiv = createDiv();
|
||||
const childNodes = slotElm.childNodes;
|
||||
const length = childNodes.length;
|
||||
|
||||
appendChildren(slotElm, createdDiv);
|
||||
expect(createdDiv).toBe(childNodes[childNodes.length - 1]);
|
||||
expect(childNodes.length).toBe(length + 1);
|
||||
|
||||
compareToNative(slotElm, 'append', Array.from(childNodes), createdDiv);
|
||||
});
|
||||
|
||||
test('multiple created', () => {
|
||||
const createdDivs = [createDiv(), createDiv(), createDiv()];
|
||||
const childNodes = slotElm.childNodes;
|
||||
const length = childNodes.length;
|
||||
|
||||
appendChildren(slotElm, createdDivs);
|
||||
expect(createdDivs[0]).toBe(childNodes[childNodes.length - 3]);
|
||||
expect(createdDivs[1]).toBe(childNodes[childNodes.length - 2]);
|
||||
expect(createdDivs[2]).toBe(childNodes[childNodes.length - 1]);
|
||||
expect(childNodes.length).toBe(length + createdDivs.length);
|
||||
|
||||
compareToNative(slotElm, 'append', Array.from(childNodes), createdDivs);
|
||||
});
|
||||
|
||||
test('single existing', () => {
|
||||
const childNodes = slotElm.childNodes;
|
||||
const elm = childNodes[1];
|
||||
|
||||
appendChildren(slotElm, elm);
|
||||
expect(elm).toBe(childNodes[childNodes.length - 1]);
|
||||
|
||||
compareToNative(slotElm, 'append', Array.from(childNodes), elm, true);
|
||||
});
|
||||
|
||||
test('multiple existing', () => {
|
||||
const childNodes = slotElm.childNodes;
|
||||
const elms = [childNodes[1], childNodes[0], childNodes[2]];
|
||||
|
||||
appendChildren(slotElm, elms);
|
||||
expect(elms[0]).toBe(childNodes[childNodes.length - 3]);
|
||||
expect(elms[1]).toBe(childNodes[childNodes.length - 2]);
|
||||
expect(elms[2]).toBe(childNodes[childNodes.length - 1]);
|
||||
|
||||
compareToNative(slotElm, 'append', Array.from(childNodes), elms, true);
|
||||
});
|
||||
|
||||
test('none', () => {
|
||||
const childNodes = slotElm.childNodes;
|
||||
const length = childNodes.length;
|
||||
|
||||
appendChildren(slotElm, null);
|
||||
appendChildren(null, childNodes);
|
||||
|
||||
expect(childNodes.length).toBe(length);
|
||||
});
|
||||
});
|
||||
|
||||
describe('prependChildren', () => {
|
||||
test('single created', () => {
|
||||
const createdDiv = createDiv();
|
||||
const childNodes = slotElm.childNodes;
|
||||
const length = childNodes.length;
|
||||
|
||||
prependChildren(slotElm, createdDiv);
|
||||
expect(createdDiv).toBe(childNodes[0]);
|
||||
expect(childNodes.length).toBe(length + 1);
|
||||
|
||||
compareToNative(slotElm, 'prepend', Array.from(childNodes), createdDiv);
|
||||
});
|
||||
|
||||
test('multiple created', () => {
|
||||
const createdDivs = [createDiv(), createDiv(), createDiv()];
|
||||
const childNodes = slotElm.childNodes;
|
||||
const length = childNodes.length;
|
||||
|
||||
prependChildren(slotElm, createdDivs);
|
||||
expect(createdDivs[0]).toBe(childNodes[0]);
|
||||
expect(createdDivs[1]).toBe(childNodes[1]);
|
||||
expect(createdDivs[2]).toBe(childNodes[2]);
|
||||
expect(childNodes.length).toBe(length + createdDivs.length);
|
||||
|
||||
compareToNative(slotElm, 'prepend', Array.from(childNodes), createdDivs);
|
||||
});
|
||||
|
||||
test('single existing', () => {
|
||||
const childNodes = slotElm.childNodes;
|
||||
const elm = childNodes[1];
|
||||
|
||||
prependChildren(slotElm, elm);
|
||||
expect(elm).toBe(childNodes[0]);
|
||||
|
||||
compareToNative(slotElm, 'prepend', Array.from(childNodes), elm, true);
|
||||
});
|
||||
|
||||
test('multiple existing', () => {
|
||||
const childNodes = slotElm.childNodes;
|
||||
const elms = [childNodes[1], childNodes[0], childNodes[2]];
|
||||
|
||||
prependChildren(slotElm, elms);
|
||||
expect(elms[0]).toBe(childNodes[0]);
|
||||
expect(elms[1]).toBe(childNodes[1]);
|
||||
expect(elms[2]).toBe(childNodes[2]);
|
||||
|
||||
compareToNative(slotElm, 'prepend', Array.from(childNodes), elms, true);
|
||||
});
|
||||
|
||||
test('none', () => {
|
||||
const childNodes = slotElm.childNodes;
|
||||
const length = childNodes.length;
|
||||
|
||||
prependChildren(slotElm, null);
|
||||
prependChildren(null, childNodes);
|
||||
|
||||
expect(childNodes.length).toBe(length);
|
||||
});
|
||||
});
|
||||
|
||||
describe('insertBefore', () => {
|
||||
test('single created', () => {
|
||||
const createdDiv = createDiv();
|
||||
const childNodes = slotElm.childNodes;
|
||||
const length = childNodes.length;
|
||||
const target = childNodes[1];
|
||||
|
||||
insertBefore(target, createdDiv);
|
||||
expect(createdDiv).toBe(childNodes[1]);
|
||||
expect(childNodes.length).toBe(length + 1);
|
||||
|
||||
compareToNative(target, 'before', Array.from(childNodes), createdDiv);
|
||||
});
|
||||
|
||||
test('multiple created', () => {
|
||||
const createdDivs = [createDiv(), createDiv(), createDiv()];
|
||||
const childNodes = slotElm.childNodes;
|
||||
const length = childNodes.length;
|
||||
const target = childNodes[1];
|
||||
|
||||
insertBefore(target, createdDivs);
|
||||
expect(createdDivs[0]).toBe(childNodes[1]);
|
||||
expect(createdDivs[1]).toBe(childNodes[2]);
|
||||
expect(createdDivs[2]).toBe(childNodes[3]);
|
||||
expect(childNodes.length).toBe(length + createdDivs.length);
|
||||
|
||||
compareToNative(target, 'before', Array.from(childNodes), createdDivs);
|
||||
});
|
||||
|
||||
test('single existing', () => {
|
||||
const childNodes = slotElm.childNodes;
|
||||
const target = childNodes[1];
|
||||
const elm = childNodes[2];
|
||||
|
||||
insertBefore(target, elm);
|
||||
expect(elm).toBe(childNodes[1]);
|
||||
|
||||
compareToNative(target, 'before', Array.from(childNodes), elm, true);
|
||||
});
|
||||
|
||||
test('multiple existing', () => {
|
||||
const childNodes = slotElm.childNodes;
|
||||
const target = childNodes[1];
|
||||
const elms = [childNodes[4], childNodes[1], childNodes[2]];
|
||||
|
||||
insertBefore(target, elms);
|
||||
expect(elms[0]).toBe(childNodes[1]);
|
||||
expect(elms[1]).toBe(childNodes[2]);
|
||||
expect(elms[2]).toBe(childNodes[3]);
|
||||
|
||||
compareToNative(target, 'before', Array.from(childNodes), elms, true);
|
||||
});
|
||||
|
||||
test('none', () => {
|
||||
const childNodes = slotElm.childNodes;
|
||||
const length = childNodes.length;
|
||||
|
||||
insertBefore(slotElm, null);
|
||||
insertBefore(null, childNodes);
|
||||
|
||||
expect(childNodes.length).toBe(length);
|
||||
});
|
||||
});
|
||||
|
||||
describe('insertAfter', () => {
|
||||
test('single created', () => {
|
||||
const createdDiv = createDiv();
|
||||
const childNodes = slotElm.childNodes;
|
||||
const length = childNodes.length;
|
||||
const target = childNodes[1];
|
||||
|
||||
insertAfter(target, createdDiv);
|
||||
expect(createdDiv).toBe(childNodes[2]);
|
||||
expect(childNodes.length).toBe(length + 1);
|
||||
|
||||
compareToNative(target, 'after', Array.from(childNodes), createdDiv);
|
||||
});
|
||||
|
||||
test('multiple created', () => {
|
||||
const createdDivs = [createDiv(), createDiv(), createDiv()];
|
||||
const childNodes = slotElm.childNodes;
|
||||
const length = childNodes.length;
|
||||
const target = childNodes[1];
|
||||
|
||||
insertAfter(target, createdDivs);
|
||||
expect(createdDivs[0]).toBe(childNodes[2]);
|
||||
expect(createdDivs[1]).toBe(childNodes[3]);
|
||||
expect(createdDivs[2]).toBe(childNodes[4]);
|
||||
expect(childNodes.length).toBe(length + createdDivs.length);
|
||||
|
||||
compareToNative(target, 'after', Array.from(childNodes), createdDivs);
|
||||
});
|
||||
|
||||
test('single existing', () => {
|
||||
const childNodes = slotElm.childNodes;
|
||||
const target = childNodes[1];
|
||||
const elm = childNodes[0];
|
||||
|
||||
insertAfter(target, elm);
|
||||
expect(elm).toBe(childNodes[1]);
|
||||
|
||||
compareToNative(target, 'after', Array.from(childNodes), elm, true);
|
||||
});
|
||||
|
||||
test('multiple existing', () => {
|
||||
const childNodes = slotElm.childNodes;
|
||||
const target = childNodes[1];
|
||||
const elms = [childNodes[4], childNodes[1], childNodes[2]];
|
||||
|
||||
insertAfter(target, elms);
|
||||
expect(elms[0]).toBe(childNodes[1]);
|
||||
expect(elms[1]).toBe(childNodes[2]);
|
||||
expect(elms[2]).toBe(childNodes[3]);
|
||||
|
||||
compareToNative(target, 'after', Array.from(childNodes), elms, true);
|
||||
});
|
||||
|
||||
test('none', () => {
|
||||
const childNodes = slotElm.childNodes;
|
||||
const length = childNodes.length;
|
||||
|
||||
insertAfter(slotElm, null);
|
||||
insertAfter(null, childNodes);
|
||||
|
||||
expect(childNodes.length).toBe(length);
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeElm', () => {
|
||||
test('single created', () => {
|
||||
const createdDiv = createDiv();
|
||||
expect(createdDiv.parentElement).toBeNull();
|
||||
removeElements(createdDiv);
|
||||
});
|
||||
|
||||
test('multiple created', () => {
|
||||
const createdDivs: Array<HTMLElement> = [createDiv(), createDiv(), createDiv(), createDiv()];
|
||||
each(createdDivs, (createdDiv: HTMLElement) => {
|
||||
expect(createdDiv.parentElement).toBeNull();
|
||||
});
|
||||
removeElements(createdDivs);
|
||||
});
|
||||
|
||||
test('single existing', () => {
|
||||
const childNodes = slotElm.childNodes;
|
||||
const length = childNodes.length;
|
||||
expect(length).not.toBe(0);
|
||||
removeElements(childNodes[0]);
|
||||
expect(childNodes.length).toBe(length - 1);
|
||||
});
|
||||
|
||||
test('multiple existing', () => {
|
||||
const childNodes = slotElm.childNodes;
|
||||
expect(childNodes.length).not.toBe(0)
|
||||
removeElements(childNodes);
|
||||
expect(childNodes.length).toBe(0);
|
||||
});
|
||||
|
||||
test('none', () => {
|
||||
// @ts-ignore
|
||||
removeElements(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,213 @@
|
||||
import { find, findFirst, is, children, contents, parent, createDiv } from 'core/dom';
|
||||
|
||||
const slotElm = document.body;
|
||||
const testHTML = '<div id="parent" class="div-class"><div id="child" class="div-class"></div></div><p>2</p><input type="text" value="3"></input>abc';
|
||||
|
||||
describe('dom traversal', () => {
|
||||
beforeEach(() => {
|
||||
slotElm.innerHTML = testHTML;
|
||||
});
|
||||
afterEach(() => {
|
||||
slotElm.innerHTML = '';
|
||||
});
|
||||
|
||||
describe('find', () => {
|
||||
test('by class', () => {
|
||||
const divClass = find('.div-class');
|
||||
|
||||
expect(divClass.length).toBe(2);
|
||||
expect(divClass[1].parentElement).toBe(divClass[0]);
|
||||
});
|
||||
|
||||
test('by id', () => {
|
||||
const parentId = find('#parent');
|
||||
|
||||
expect(parentId.length).toBe(1);
|
||||
expect(parentId[0]).toBe(document.querySelector('#parent'));
|
||||
});
|
||||
|
||||
test('all', () => {
|
||||
const all = find('*');
|
||||
const allNative = document.querySelectorAll('*');
|
||||
|
||||
expect(all.length).toBe(allNative.length);
|
||||
expect(Array.from(all)).toEqual(Array.from(allNative));
|
||||
});
|
||||
|
||||
test('all with defined parent', () => {
|
||||
const all = find('*', document.querySelector('#parent'));
|
||||
const allNative = document.querySelector('#parent')?.querySelectorAll('*');
|
||||
|
||||
expect(all.length).toBe(allNative?.length);
|
||||
expect(Array.from(all)).toEqual(Array.from(allNative!));
|
||||
});
|
||||
|
||||
test('all with null parent', () => {
|
||||
const all = find('*', null);
|
||||
const allNative = document.querySelectorAll('*');
|
||||
|
||||
expect(all.length).toBe(allNative.length);
|
||||
expect(Array.from(all)).toEqual(Array.from(allNative!));
|
||||
});
|
||||
|
||||
test('non-existent', () => {
|
||||
const nonExistent = find('#non-existent');
|
||||
|
||||
expect(nonExistent.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('findFirst', () => {
|
||||
test('by class', () => {
|
||||
const divClass = findFirst('.div-class');
|
||||
|
||||
expect(divClass).toBe(document.querySelector('.div-class'));
|
||||
});
|
||||
|
||||
test('by id', () => {
|
||||
const parentId = findFirst('#parent');
|
||||
|
||||
expect(parentId).toBe(document.querySelector('#parent'));
|
||||
});
|
||||
|
||||
test('all', () => {
|
||||
const all = findFirst('*');
|
||||
const allNative = document.querySelector('*');
|
||||
|
||||
expect(all).toBe(allNative);
|
||||
});
|
||||
|
||||
test('all with defined parent', () => {
|
||||
const all = findFirst('*', document.querySelector('#parent'));
|
||||
const allNative = document.querySelector('#parent')?.querySelector('*');
|
||||
|
||||
expect(all).toBe(allNative);
|
||||
});
|
||||
|
||||
test('all with null parent', () => {
|
||||
const all = findFirst('*', null);
|
||||
const allNative = document.querySelector('*');
|
||||
|
||||
expect(all).toBe(allNative);
|
||||
});
|
||||
|
||||
test('non-existent', () => {
|
||||
const nonExistent = findFirst('#non-existent');
|
||||
|
||||
expect(nonExistent).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('is', () => {
|
||||
test('tag', () => {
|
||||
expect(is(findFirst('input'), 'input')).toBe(true);
|
||||
expect(is(findFirst('body'), 'body')).toBe(true);
|
||||
expect(is(findFirst('div'), 'div')).toBe(true);
|
||||
|
||||
expect(is(findFirst('input'), 'body')).toBe(false);
|
||||
expect(is(findFirst('body'), 'input')).toBe(false);
|
||||
expect(is(findFirst('div'), 'head')).toBe(false);
|
||||
});
|
||||
|
||||
test('id', () => {
|
||||
expect(is(findFirst('#parent'), '#parent')).toBe(true);
|
||||
expect(is(findFirst('#child'), '#parent')).toBe(false);
|
||||
});
|
||||
|
||||
test('class', () => {
|
||||
expect(is(findFirst('.div-class'), '.div-class')).toBe(true);
|
||||
expect(is(findFirst('.div-class'), '.other-class')).toBe(false);
|
||||
});
|
||||
|
||||
test('visibility', () => {
|
||||
expect(is(findFirst('.div-class'), ':visible')).toBe(false);
|
||||
expect(is(findFirst('.div-class'), ':hidden')).toBe(true);
|
||||
});
|
||||
|
||||
test('created', () => {
|
||||
const div = createDiv();
|
||||
expect(div.parentNode).toBeNull();
|
||||
|
||||
expect(is(div, 'div')).toBe(true);
|
||||
|
||||
expect(is(div, 'body')).toBe(false);
|
||||
expect(is(div, 'input')).toBe(false);
|
||||
expect(is(div, 'head')).toBe(false);
|
||||
|
||||
expect(is(div, '#parent')).toBe(false);
|
||||
expect(is(div, '#parent')).toBe(false);
|
||||
|
||||
expect(is(div, '.div-class')).toBe(false);
|
||||
expect(is(div, '.other-class')).toBe(false);
|
||||
|
||||
expect(is(div, ':visible')).toBe(false);
|
||||
expect(is(div, ':hidden')).toBe(true);
|
||||
});
|
||||
|
||||
test('none', () => {
|
||||
expect(is(null, 'body')).toBe(false);
|
||||
expect(is(null, 'input')).toBe(false);
|
||||
expect(is(null, 'head')).toBe(false);
|
||||
|
||||
expect(is(null, '#parent')).toBe(false);
|
||||
expect(is(null, '#parent')).toBe(false);
|
||||
|
||||
expect(is(null, '.div-class')).toBe(false);
|
||||
expect(is(null, '.other-class')).toBe(false);
|
||||
|
||||
expect(is(null, ':visible')).toBe(false);
|
||||
expect(is(null, ':hidden')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('children', () => {
|
||||
test('available element', () => {
|
||||
const childs = children(document.body);
|
||||
|
||||
expect(childs.length).toBe(document.body.children.length);
|
||||
expect(childs).toEqual(Array.from(document.body.children));
|
||||
});
|
||||
|
||||
test('unavailable element', () => {
|
||||
const childs = children(null);
|
||||
|
||||
expect(childs.length).toEqual(0);
|
||||
});
|
||||
|
||||
test('with selector', () => {
|
||||
const childs = children(document.body, 'input');
|
||||
|
||||
expect(childs.length).toBe(1);
|
||||
expect(childs[0]).toBe(findFirst('input'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('contents', () => {
|
||||
test('available element', () => {
|
||||
const childs = contents(document.body);
|
||||
|
||||
expect(childs.length).toBe(document.body.childNodes.length);
|
||||
expect(childs).toEqual(Array.from(document.body.childNodes));
|
||||
});
|
||||
|
||||
test('unavailable element', () => {
|
||||
const childs = contents(null);
|
||||
|
||||
expect(childs.length).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('parent', () => {
|
||||
test('available element', () => {
|
||||
const p = parent(document.body);
|
||||
|
||||
expect(p).toBe(document.body.parentElement);
|
||||
});
|
||||
|
||||
test('unavailable element', () => {
|
||||
const p = parent(null);
|
||||
|
||||
expect(p).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,77 @@
|
||||
import { OptionsTemplate, OptionsAndOptionsTemplate, PlainObject } from "core/typings";
|
||||
import { optionsTemplateTypes as oTypes, transform } from "core/options";
|
||||
|
||||
type TestOptionsObj = { propA: 'propA', null: null };
|
||||
type TestOptionsEnum = 'A' | 'B' | 'C';
|
||||
type TestOptions = {
|
||||
str?: string;
|
||||
strArrNull?: string | Array<string> | null;
|
||||
nullbool?: boolean | null;
|
||||
nested?: {
|
||||
num?: number;
|
||||
switch?: boolean;
|
||||
abc?: TestOptionsEnum;
|
||||
};
|
||||
obj?: TestOptionsObj | null;
|
||||
abc?: TestOptionsEnum;
|
||||
arr?: Array<any>;
|
||||
func?: () => void;
|
||||
}
|
||||
type DeepRequired<T> = {
|
||||
[P in keyof T]-?: PlainObject extends T[P] ? DeepRequired<T[P]> : T[P];
|
||||
};
|
||||
|
||||
const options: DeepRequired<TestOptions> = {
|
||||
str: 'hi',
|
||||
strArrNull: null,
|
||||
nullbool: true,
|
||||
nested: {
|
||||
num: 1,
|
||||
switch: false,
|
||||
abc: 'B',
|
||||
},
|
||||
obj: { propA: 'propA', null: null },
|
||||
abc: 'A',
|
||||
arr: [1, 2, 3],
|
||||
func: () => { }
|
||||
}
|
||||
|
||||
const optionsTemplate: OptionsTemplate<Required<TestOptions>> = {
|
||||
str: oTypes.string,
|
||||
strArrNull: [oTypes.string, oTypes.array, oTypes.null],
|
||||
nullbool: [oTypes.boolean, oTypes.null],
|
||||
nested: {
|
||||
num: oTypes.number,
|
||||
switch: oTypes.boolean,
|
||||
abc: 'A B C',
|
||||
},
|
||||
obj: [oTypes.object, oTypes.null],
|
||||
abc: 'A B C',
|
||||
arr: oTypes.array,
|
||||
func: oTypes.function,
|
||||
}
|
||||
|
||||
const optionsAndOptionsTemplate: OptionsAndOptionsTemplate<Required<TestOptions>> = {
|
||||
str: [options.str, optionsTemplate.str],
|
||||
strArrNull: [options.strArrNull, optionsTemplate.strArrNull],
|
||||
nullbool: [options.nullbool, optionsTemplate.nullbool],
|
||||
nested: {
|
||||
num: [options.nested.num, optionsTemplate.nested.num],
|
||||
switch: [options.nested.switch, optionsTemplate.nested.switch],
|
||||
abc: [options.nested.abc, optionsTemplate.nested.abc],
|
||||
},
|
||||
obj: [options.obj, optionsTemplate.obj],
|
||||
abc: [options.abc, optionsTemplate.abc],
|
||||
arr: [options.arr, optionsTemplate.arr],
|
||||
func: [options.func, optionsTemplate.func]
|
||||
};
|
||||
|
||||
describe('options and options template object transformation', () => {
|
||||
test('transforms correctly into options object', () => {
|
||||
expect(transform(optionsAndOptionsTemplate)).toEqual(options);
|
||||
});
|
||||
|
||||
test('transforms correctly into template object', () => {
|
||||
expect(transform(optionsAndOptionsTemplate, true)).toEqual(optionsTemplate);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,370 @@
|
||||
import { validate, optionsTemplateTypes as oTypes } from 'core/options';
|
||||
import { extend, isEmptyObject } from 'core/utils';
|
||||
import { OptionsTemplate } from 'core/typings';
|
||||
|
||||
type TestOptionsObj = { propA: 'propA', null: null };
|
||||
type TestOptionsEnum = 'A' | 'B' | 'C';
|
||||
type TestOptions = {
|
||||
str?: string;
|
||||
strArrNull?: string | Array<string> | null;
|
||||
nullbool?: boolean | null;
|
||||
nested?: {
|
||||
num?: number;
|
||||
switch?: boolean;
|
||||
abc?: TestOptionsEnum;
|
||||
};
|
||||
obj?: TestOptionsObj | null;
|
||||
abc?: TestOptionsEnum;
|
||||
arr?: Array<any>;
|
||||
func?: () => void;
|
||||
}
|
||||
|
||||
const options: TestOptions = {
|
||||
str: 'hi',
|
||||
strArrNull: null,
|
||||
nullbool: true,
|
||||
nested: {
|
||||
num: 1,
|
||||
switch: false,
|
||||
abc: 'B',
|
||||
},
|
||||
obj: { propA: 'propA', null: null },
|
||||
abc: 'A',
|
||||
arr: [1, 2, 3],
|
||||
func: () => { }
|
||||
}
|
||||
|
||||
const template: OptionsTemplate<Required<TestOptions>> = {
|
||||
str: oTypes.string,
|
||||
strArrNull: [oTypes.string, oTypes.array, oTypes.null],
|
||||
nullbool: [oTypes.boolean, oTypes.null],
|
||||
nested: {
|
||||
num: oTypes.number,
|
||||
switch: oTypes.boolean,
|
||||
abc: 'A B C',
|
||||
},
|
||||
obj: [oTypes.object, oTypes.null],
|
||||
abc: 'A B C',
|
||||
arr: oTypes.array,
|
||||
func: oTypes.function,
|
||||
}
|
||||
|
||||
describe('options validation', () => {
|
||||
describe('object return & mutation', () => {
|
||||
test('foreign properties wont affect validated object', () => {
|
||||
const foreignObj = { foreignProp: 'foreign', foreignDeep: { a: 'A', b: 'B' } };
|
||||
const modifiedOptions = extend({}, options, { nested: foreignObj }, foreignObj);
|
||||
const result = validate(modifiedOptions, template);
|
||||
const { validated } = result;
|
||||
|
||||
expect(validated).toEqual(options);
|
||||
});
|
||||
|
||||
test('passed objects arent mutated', () => {
|
||||
const clonedOptions = extend({}, options);
|
||||
validate(clonedOptions, template, clonedOptions);
|
||||
|
||||
expect(clonedOptions).toEqual(options);
|
||||
});
|
||||
|
||||
test('passed object isnt returned object', () => {
|
||||
const clonedOptions = extend({}, options);
|
||||
const result = validate(clonedOptions, template);
|
||||
|
||||
expect(result.validated).not.toBe(clonedOptions);
|
||||
});
|
||||
});
|
||||
|
||||
describe('foreign property return', () => {
|
||||
test('return no foreign property', () => {
|
||||
const result = validate(options, template);
|
||||
|
||||
expect(isEmptyObject(result.foreign)).toBe(true);
|
||||
});
|
||||
|
||||
test('return signle non-object foreign property', () => {
|
||||
const foreignObj = { foreignProp: 'foreign' };
|
||||
const modifiedOptions = extend({}, options, foreignObj);
|
||||
const result = validate(modifiedOptions, template);
|
||||
const { foreign } = result;
|
||||
|
||||
expect(foreign).toEqual(foreignObj);
|
||||
});
|
||||
|
||||
test('return complex foreign properties', () => {
|
||||
const foreignObj = { foreignProp: 'foreign', foreignDeep: { a: 'A', b: 'B' } };
|
||||
const modifiedOptions = extend({}, options, foreignObj);
|
||||
const result = validate(modifiedOptions, template);
|
||||
const { foreign } = result;
|
||||
|
||||
expect(foreign).toEqual(foreignObj);
|
||||
});
|
||||
|
||||
test('return nested complex foreign properties', () => {
|
||||
const foreignObj = { foreignProp: 'foreign', foreignDeep: { a: 'A', b: 'B' } };
|
||||
const modifiedOptions = extend({}, options, { nested: foreignObj }, foreignObj);
|
||||
const result = validate(modifiedOptions, template);
|
||||
const { foreign } = result;
|
||||
|
||||
expect(foreign.nested).toEqual(foreignObj);
|
||||
delete foreign.nested;
|
||||
expect(foreign).toEqual(foreignObj);
|
||||
});
|
||||
});
|
||||
|
||||
describe('diff property return', () => {
|
||||
test('one value changed', () => {
|
||||
const modifiedOptions = extend({}, options, { str: 'newvaluetest' });
|
||||
const result = validate(modifiedOptions, template, options);
|
||||
const { validated } = result;
|
||||
|
||||
expect(validated.str).toBe('newvaluetest');
|
||||
delete validated.str;
|
||||
expect(isEmptyObject(validated)).toBe(true);
|
||||
});
|
||||
|
||||
test('multiple values changed', () => {
|
||||
const modifiedOptions = extend({}, options, { str: 'newvaluetest', nullbool: null });
|
||||
const result = validate(modifiedOptions, template, options);
|
||||
const { validated } = result;
|
||||
|
||||
expect(validated.str).toBe('newvaluetest');
|
||||
expect(validated.nullbool).toBe(null);
|
||||
delete validated.str;
|
||||
delete validated.nullbool;
|
||||
expect(isEmptyObject(validated)).toBe(true);
|
||||
});
|
||||
|
||||
test('one nested value changed', () => {
|
||||
const modifiedOptions = extend({}, options, { nested: { num: -1293 } });
|
||||
const result = validate(modifiedOptions, template, options);
|
||||
const { validated } = result;
|
||||
|
||||
expect(validated.nested?.num).toBe(-1293);
|
||||
delete validated.nested?.num;
|
||||
expect(isEmptyObject(validated.nested)).toBe(true);
|
||||
delete validated.nested;
|
||||
expect(isEmptyObject(validated)).toBe(true);
|
||||
});
|
||||
|
||||
test('multiple nested values changed', () => {
|
||||
const modifiedOptions = extend({}, options, { nested: { num: -1293, abc: 'C' } });
|
||||
const result = validate(modifiedOptions, template, options);
|
||||
const { validated } = result;
|
||||
|
||||
expect(validated.nested?.num).toBe(-1293);
|
||||
expect(validated.nested?.abc).toBe('C');
|
||||
delete validated.nested?.num;
|
||||
delete validated.nested?.abc;
|
||||
expect(isEmptyObject(validated.nested)).toBe(true);
|
||||
delete validated.nested;
|
||||
expect(isEmptyObject(validated)).toBe(true);
|
||||
});
|
||||
|
||||
test('various values changed', () => {
|
||||
const newFunc = () => { };
|
||||
const modifiedOptions = extend({}, options, { str: 'newstrvalue', func: newFunc, abc: 'C', nested: { num: -1293, abc: 'C' } });
|
||||
const result = validate(modifiedOptions, template, options);
|
||||
const { validated } = result;
|
||||
|
||||
expect(validated.str).toBe('newstrvalue');
|
||||
expect(validated.func).toBe(newFunc);
|
||||
expect(validated.abc).toBe('C');
|
||||
delete validated.str;
|
||||
delete validated.func;
|
||||
delete validated.abc;
|
||||
expect(validated.nested?.num).toBe(-1293);
|
||||
expect(validated.nested?.abc).toBe('C');
|
||||
delete validated.nested?.num;
|
||||
delete validated.nested?.abc;
|
||||
expect(isEmptyObject(validated.nested)).toBe(true);
|
||||
delete validated.nested;
|
||||
expect(isEmptyObject(validated)).toBe(true);
|
||||
});
|
||||
|
||||
test('various values changed with foreign properties', () => {
|
||||
const foreignObj = { foreignProp: 'foreign', foreignDeep: { a: 'A', b: 'B' } };
|
||||
const newFunc = () => { };
|
||||
const modifiedOptions = extend({}, options, { str: 'newstrvalue', func: newFunc, abc: 'C', nested: { num: -1293, abc: 'C' } }, foreignObj, { nested: foreignObj });
|
||||
const result = validate(modifiedOptions, template, options);
|
||||
const { validated } = result;
|
||||
|
||||
expect(validated.str).toBe('newstrvalue');
|
||||
expect(validated.func).toBe(newFunc);
|
||||
expect(validated.abc).toBe('C');
|
||||
delete validated.str;
|
||||
delete validated.func;
|
||||
delete validated.abc;
|
||||
expect(validated.nested?.num).toBe(-1293);
|
||||
expect(validated.nested?.abc).toBe('C');
|
||||
delete validated.nested?.num;
|
||||
delete validated.nested?.abc;
|
||||
expect(isEmptyObject(validated.nested)).toBe(true);
|
||||
delete validated.nested;
|
||||
expect(isEmptyObject(validated)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('value validity', () => {
|
||||
test('single value doesnt match template', () => {
|
||||
const modifiedOptions = extend({}, options, { str: 1 });
|
||||
const result = validate(modifiedOptions, template);
|
||||
const { validated } = result;
|
||||
|
||||
expect(validated).not.toHaveProperty('str');
|
||||
});
|
||||
|
||||
test('single enum value doesnt match template', () => {
|
||||
const modifiedOptions = extend({}, options, { abc: 'testval' });
|
||||
const result = validate(modifiedOptions, template);
|
||||
const { validated } = result;
|
||||
|
||||
expect(validated).not.toHaveProperty('abc');
|
||||
});
|
||||
|
||||
test('multiple values dont match template', () => {
|
||||
const modifiedOptions = extend({}, options, { str: 1, abc: 'testval', nullbool: 'string' });
|
||||
const result = validate(modifiedOptions, template);
|
||||
const { validated } = result;
|
||||
|
||||
expect(validated).not.toHaveProperty('str');
|
||||
expect(validated).not.toHaveProperty('abc');
|
||||
expect(validated).not.toHaveProperty('nullbool');
|
||||
});
|
||||
|
||||
test('single nested value dont match template', () => {
|
||||
const modifiedOptions = extend({}, options, { nested: { num: 'hi' } });
|
||||
const result = validate(modifiedOptions, template);
|
||||
const { validated } = result;
|
||||
|
||||
expect(validated.nested).not.toHaveProperty('num');
|
||||
});
|
||||
|
||||
test('single nested enum value dont match template', () => {
|
||||
const modifiedOptions = extend({}, options, { nested: { abc: 'testabc' } });
|
||||
const result = validate(modifiedOptions, template);
|
||||
const { validated } = result;
|
||||
|
||||
expect(validated.nested).not.toHaveProperty('abc');
|
||||
});
|
||||
|
||||
test('multiple nested values dont match template', () => {
|
||||
const modifiedOptions = extend({}, options, { nested: { num: 'hi', abc: 'testabc' } });
|
||||
const result = validate(modifiedOptions, template);
|
||||
const { validated } = result;
|
||||
|
||||
expect(validated.nested).not.toHaveProperty('num');
|
||||
expect(validated.nested).not.toHaveProperty('abc');
|
||||
});
|
||||
|
||||
test('all nested values dont match template', () => {
|
||||
const modifiedOptions = extend({}, options, { nested: { num: 'hi', abc: 'testabc', switch: 1 } });
|
||||
const result = validate(modifiedOptions, template);
|
||||
const { validated } = result;
|
||||
|
||||
expect(validated).not.toHaveProperty('nested');
|
||||
});
|
||||
|
||||
test('all nested values dont match template with foreign property', () => {
|
||||
const modifiedOptions = extend({}, options, { nested: { foreign: 'foreign', num: 'hi', abc: 'testabc', switch: 1 } });
|
||||
const result = validate(modifiedOptions, template);
|
||||
const { validated } = result;
|
||||
|
||||
expect(validated).not.toHaveProperty('nested');
|
||||
});
|
||||
|
||||
test('various values dont match template', () => {
|
||||
const modifiedOptions = extend({}, options, { nested: { switch: null }, obj: 1, abc: 'testest', func: {} });
|
||||
const result = validate(modifiedOptions, template);
|
||||
const { validated } = result;
|
||||
|
||||
expect(validated.nested).not.toHaveProperty('switch');
|
||||
expect(validated).not.toHaveProperty('obj');
|
||||
expect(validated).not.toHaveProperty('abc');
|
||||
expect(validated).not.toHaveProperty('func');
|
||||
});
|
||||
|
||||
test('various values dont match template with foreign properties', () => {
|
||||
const foreignObj = { foreignProp: 'foreign', foreignDeep: { a: 'A', b: 'B' } };
|
||||
const modifiedOptions = extend({}, options, { nested: { switch: null }, obj: 1, abc: 'testest', func: {} }, foreignObj, { nested: foreignObj });
|
||||
const result = validate(modifiedOptions, template);
|
||||
const { validated, foreign } = result;
|
||||
|
||||
expect(foreign.nested).toEqual(foreignObj);
|
||||
delete foreign.nested;
|
||||
expect(foreign).toEqual(foreignObj);
|
||||
|
||||
expect(validated.nested).not.toHaveProperty('switch');
|
||||
expect(validated).not.toHaveProperty('obj');
|
||||
expect(validated).not.toHaveProperty('abc');
|
||||
expect(validated).not.toHaveProperty('func');
|
||||
});
|
||||
|
||||
test('nested object is string', () => {
|
||||
const modifiedOptions = extend({}, options, { nested: 'string' });
|
||||
const result = validate(modifiedOptions, template);
|
||||
const { validated } = result;
|
||||
|
||||
expect(validated).not.toHaveProperty('nested');
|
||||
});
|
||||
|
||||
test('nested object is null', () => {
|
||||
const modifiedOptions = extend({}, options, { nested: null });
|
||||
const result = validate(modifiedOptions, template);
|
||||
const { validated } = result;
|
||||
|
||||
expect(validated).not.toHaveProperty('nested');
|
||||
});
|
||||
|
||||
test('nested object is undefined', () => {
|
||||
const modifiedOptions = extend({}, options);
|
||||
modifiedOptions.nested = undefined;
|
||||
const result = validate(modifiedOptions, template);
|
||||
const { validated } = result;
|
||||
|
||||
expect(validated).not.toHaveProperty('nested');
|
||||
});
|
||||
});
|
||||
|
||||
describe('error logging', () => {
|
||||
test('dont log error if nothing is wrong', () => {
|
||||
const warn = console.warn;
|
||||
console.warn = jest.fn();
|
||||
|
||||
validate(options, template, {}, true);
|
||||
expect(console.warn).not.toBeCalled();
|
||||
|
||||
console.warn = warn;
|
||||
});
|
||||
|
||||
test('dont log error if something is wrong and flag is false', () => {
|
||||
const warn = console.warn;
|
||||
console.warn = jest.fn();
|
||||
|
||||
const modifiedOptions = extend({}, options, { str: 1 });
|
||||
validate(modifiedOptions, template, {}, false);
|
||||
expect(console.warn).not.toBeCalled();
|
||||
|
||||
console.warn = warn;
|
||||
});
|
||||
|
||||
test('log error if something is wrong and flag is true', () => {
|
||||
const warn = console.warn;
|
||||
console.warn = jest.fn();
|
||||
|
||||
// str must be string
|
||||
validate(extend({}, options, { str: 1 }), template, {}, true);
|
||||
expect(console.warn).toBeCalledTimes(1);
|
||||
|
||||
// abc must be A | B | C
|
||||
validate(extend({}, options, { abc: 'some string' }), template, {}, true);
|
||||
expect(console.warn).toBeCalledTimes(2);
|
||||
|
||||
// everthing OK
|
||||
validate(extend({}, options, { abc: 'C' }), template, {}, true);
|
||||
expect(console.warn).toBeCalledTimes(2);
|
||||
|
||||
console.warn = warn;
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,176 @@
|
||||
import { each, indexOf } from 'core/utils/arrays';
|
||||
|
||||
describe('array utilities', () => {
|
||||
describe('each', () => {
|
||||
describe('each through Array', () => {
|
||||
test('returns input', () => {
|
||||
const arr = [1, 2, 3];
|
||||
expect(each(arr, () => { })).toBe(arr);
|
||||
});
|
||||
|
||||
test('correct times', () => {
|
||||
const arr = [1, 2, 3];
|
||||
const eachCallback = jest.fn();
|
||||
|
||||
each(arr, eachCallback);
|
||||
expect(eachCallback).toBeCalledTimes(arr.length);
|
||||
});
|
||||
|
||||
test('correct callback values', () => {
|
||||
const arr = [1, 2, 3];
|
||||
each(arr, (value, index, src) => {
|
||||
expect(value).toBe(arr[index]);
|
||||
expect(arr).toBe(src);
|
||||
});
|
||||
});
|
||||
|
||||
test('return false equals break', () => {
|
||||
const arr = [1, 2, 3];
|
||||
const testFunc = jest.fn();
|
||||
|
||||
each(arr, () => {
|
||||
testFunc();
|
||||
return false;
|
||||
});
|
||||
|
||||
expect(testFunc).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
test('return true equals continue', () => {
|
||||
const arr = [1, 2, 3];
|
||||
const testFunc = jest.fn();
|
||||
|
||||
each(arr, (value, index) => {
|
||||
if (index === 0)
|
||||
return true;
|
||||
testFunc();
|
||||
});
|
||||
|
||||
expect(testFunc).toBeCalledTimes(arr.length - 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('each through Object', () => {
|
||||
test('returns input', () => {
|
||||
const obj = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
c: 3
|
||||
};
|
||||
expect(each(obj, () => { })).toBe(obj);
|
||||
});
|
||||
|
||||
test('correct times', () => {
|
||||
const obj = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
c: 3
|
||||
};
|
||||
const eachCallback = jest.fn();
|
||||
|
||||
each(obj, eachCallback);
|
||||
expect(eachCallback).toBeCalledTimes(Object.keys(obj).length);
|
||||
});
|
||||
|
||||
test('correct callback values', () => {
|
||||
const obj = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
c: 3
|
||||
};
|
||||
each(obj, (value, key, src) => {
|
||||
expect(value).toBe(obj[key]);
|
||||
expect(obj).toBe(src);
|
||||
});
|
||||
});
|
||||
|
||||
test('return false equals break', () => {
|
||||
const obj = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
c: 3
|
||||
};
|
||||
const testFunc = jest.fn();
|
||||
|
||||
each(obj, () => {
|
||||
testFunc();
|
||||
return false;
|
||||
});
|
||||
|
||||
expect(testFunc).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
test('return true equals continue', () => {
|
||||
const obj = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
c: 3
|
||||
};
|
||||
const testFunc = jest.fn();
|
||||
let index = -1;
|
||||
|
||||
each(obj, (value) => {
|
||||
index++;
|
||||
if (index === 0)
|
||||
return true;
|
||||
testFunc();
|
||||
});
|
||||
|
||||
expect(testFunc).toBeCalledTimes(Object.keys(obj).length - 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('each through ArrayLike Object', () => {
|
||||
test('returns input', () => {
|
||||
const arrLikeObj = document.querySelectorAll('*');
|
||||
expect(each(arrLikeObj, () => { })).toBe(arrLikeObj);
|
||||
});
|
||||
|
||||
test('correct times', () => {
|
||||
const arrLikeObj = document.querySelectorAll('*');
|
||||
const eachCallback = jest.fn();
|
||||
|
||||
each(arrLikeObj, eachCallback);
|
||||
expect(eachCallback).toBeCalledTimes(arrLikeObj.length);
|
||||
});
|
||||
|
||||
test('correct callback values', () => {
|
||||
const arrLikeObj = document.querySelectorAll('*');
|
||||
each(arrLikeObj, (value, index, src) => {
|
||||
expect(value).toBe(arrLikeObj[index]);
|
||||
expect(src).toBe(arrLikeObj);
|
||||
});
|
||||
});
|
||||
|
||||
test('return false equals break', () => {
|
||||
const arrLikeObj = document.querySelectorAll('*');
|
||||
const testFunc = jest.fn();
|
||||
|
||||
each(arrLikeObj, () => {
|
||||
testFunc();
|
||||
return false;
|
||||
});
|
||||
|
||||
expect(testFunc).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
test('return true equals continue', () => {
|
||||
const arrLikeObj = document.querySelectorAll('*');
|
||||
const testFunc = jest.fn();
|
||||
|
||||
each(arrLikeObj, (value, index) => {
|
||||
if (index === 0)
|
||||
return true;
|
||||
testFunc();
|
||||
});
|
||||
|
||||
expect(testFunc).toBeCalledTimes(arrLikeObj.length - 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('indexOf', () => {
|
||||
const idx = indexOf([1, 2, 3], 2);
|
||||
expect(idx).toBe(1);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,148 @@
|
||||
import { extend } from 'core/utils/extend';
|
||||
import { isPlainObject } from 'core/utils/types';
|
||||
|
||||
//type DeepPartial<T> = T extends object ? { [K in keyof T]?: DeepPartial<T[K]> } : T
|
||||
type Deep = {
|
||||
foo?: {
|
||||
bar?: boolean,
|
||||
baz?: boolean
|
||||
},
|
||||
foo2?: Document
|
||||
};
|
||||
type Settings = {
|
||||
xnumber0?: null,
|
||||
xnumber1?: number | null,
|
||||
xnumber2?: number | null,
|
||||
xstring1?: string,
|
||||
xstring2?: string,
|
||||
xxx?: string
|
||||
};
|
||||
type NestedArray = {
|
||||
arr: Array<any> | object
|
||||
};
|
||||
|
||||
//https://github.com/jquery/jquery/blob/master/test/unit/core.js#L965
|
||||
describe('extend', () => {
|
||||
test('equals object assign', () => {
|
||||
let settings: Settings = { xnumber1: 5, xnumber2: 7, xstring1: "peter", xstring2: "pan" };
|
||||
const options: Settings = { xnumber2: 1, xstring2: "x", xxx: "newstring" };
|
||||
const optionsCopy: Settings = { xnumber2: 1, xstring2: "x", xxx: "newstring" };
|
||||
const merged: Settings = { xnumber1: 5, xnumber2: 1, xstring1: "peter", xstring2: "x", xxx: "newstring" };
|
||||
|
||||
extend(settings, options);
|
||||
expect(settings).toEqual(merged);
|
||||
expect(options).toEqual(optionsCopy);
|
||||
|
||||
extend(settings, null, options);
|
||||
expect(settings).toEqual(merged);
|
||||
expect(options).toEqual(optionsCopy);
|
||||
|
||||
|
||||
const deep1: Deep = { foo: { bar: true } };
|
||||
const deep2: Deep = { foo: { baz: true }, foo2: document };
|
||||
const deep2copy: Deep = { foo: { baz: true }, foo2: document };
|
||||
const deepmerged: Deep = { foo: { bar: true, baz: true }, foo2: document };
|
||||
|
||||
extend(deep1, deep2);
|
||||
expect(deep1.foo).toEqual(deepmerged.foo);
|
||||
expect(deep2.foo).toEqual(deep2copy.foo);
|
||||
expect(deep1.foo2).toBe(document);
|
||||
|
||||
|
||||
const arr = [1, 2, 3];
|
||||
const nestedArray: NestedArray = { arr: arr };
|
||||
|
||||
expect(extend({}, nestedArray).arr).not.toBe(arr);
|
||||
expect(Array.isArray(extend({ arr: {} }, nestedArray).arr)).toBeTruthy();
|
||||
expect(Array.isArray(extend({ arr: {} }, nestedArray).arr)).toBeTruthy();
|
||||
expect(isPlainObject(extend({ arr: arr }, { arr: {} }).arr)).toBeTruthy();
|
||||
|
||||
let empty = {};
|
||||
const optionsWithLength = { "foo": { "length": -1 } };
|
||||
|
||||
|
||||
extend(empty, optionsWithLength);
|
||||
expect(empty["foo"]).toEqual(optionsWithLength["foo"]);
|
||||
|
||||
empty = {};
|
||||
const optionsWithDate = { "foo": { "date": new Date() } };
|
||||
|
||||
|
||||
extend(empty, optionsWithDate);
|
||||
expect(empty["foo"]).toEqual(optionsWithDate["foo"]);
|
||||
|
||||
/** @constructor */
|
||||
const myKlass = function () { };
|
||||
// @ts-ignore
|
||||
const customObject = new myKlass();
|
||||
const optionsWithCustomObject = { "foo": { "date": customObject } };
|
||||
empty = {};
|
||||
|
||||
extend(empty, optionsWithCustomObject);
|
||||
expect(empty["foo"] && empty["foo"]["date"] === customObject).toBeTruthy();
|
||||
|
||||
// Makes the class a little more realistic
|
||||
myKlass.prototype = { "someMethod": function () { } };
|
||||
empty = {};
|
||||
|
||||
extend(empty, optionsWithCustomObject);
|
||||
expect(empty["foo"] && empty["foo"]["date"] === customObject).toBeTruthy();
|
||||
|
||||
const MyNumber = Number;
|
||||
|
||||
var ret: any = extend({ foo: 4 }, { foo: new MyNumber(5) });
|
||||
expect(parseInt(ret.foo?.toString() as string, 10) === 5).toBeTruthy();
|
||||
|
||||
let nullUndef = extend({}, options, { xnumber2: null });
|
||||
expect(nullUndef.xnumber2).toBe(null);
|
||||
|
||||
// @ts-ignore
|
||||
nullUndef = extend({}, options, { xnumber2: undefined });
|
||||
expect(nullUndef.xnumber2).toBe(options.xnumber2);
|
||||
|
||||
// @ts-ignore
|
||||
nullUndef = extend({}, options, { xnumber0: null });
|
||||
expect(nullUndef.xnumber0).toBe(null);
|
||||
|
||||
const target = {};
|
||||
const recursive = { foo: target, bar: 5 };
|
||||
|
||||
extend(target, recursive);
|
||||
expect(target).toEqual({ bar: 5 });
|
||||
|
||||
ret = extend({ foo: [] }, { foo: [0] });
|
||||
expect(ret.foo?.length).toBe(1);
|
||||
|
||||
ret = extend({ foo: "1,2,3" }, { foo: [1, 2, 3] });
|
||||
expect(typeof ret.foo !== "string").toBeTruthy();
|
||||
|
||||
ret = extend({ foo: "bar" }, { foo: null });
|
||||
expect(typeof ret.foo !== "undefined").toBeTruthy();
|
||||
|
||||
const obj = { foo: null };
|
||||
extend(obj, { foo: "notnull" });
|
||||
expect(obj.foo).toBe("notnull");
|
||||
|
||||
const func: { (): void, key?: string } = () => { };
|
||||
extend(func, { key: "value" });
|
||||
expect(func.key).toBe("value");
|
||||
|
||||
const defaults = { xnumber1: 5, xnumber2: 7, xstring1: "peter", xstring2: "pan" };
|
||||
const defaultsCopy = { xnumber1: 5, xnumber2: 7, xstring1: "peter", xstring2: "pan" };
|
||||
const options1 = { xnumber2: 1, xstring2: "x" };
|
||||
const options1Copy = { xnumber2: 1, xstring2: "x" };
|
||||
const options2 = { xstring2: "xx", xxx: "newstringx" };
|
||||
const options2Copy = { xstring2: "xx", xxx: "newstringx" };
|
||||
const merged2 = { xnumber1: 5, xnumber2: 1, xstring1: "peter", xstring2: "xx", xxx: "newstringx" };
|
||||
|
||||
settings = extend({}, defaults, options1, options2);
|
||||
expect(settings).toEqual(merged2);
|
||||
expect(defaults).toEqual(defaultsCopy);
|
||||
expect(options1).toEqual(options1Copy);
|
||||
expect(options2).toEqual(options2Copy);
|
||||
|
||||
expect(extend('', { foo: 1 })).toEqual({ foo: 1 });
|
||||
expect(extend(null, { foo: null, deep: { foo: null } })).toEqual({ foo: null, deep: { foo: null } });
|
||||
expect(extend(12, { foo: 1, deep: { foo: null, text: '' } })).toEqual({ foo: 1, deep: { foo: null, text: '' } });
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,216 @@
|
||||
import { type, isNumber, isString, isBoolean, isFunction, isArray, isObject, isUndefined, isNull, isArrayLike, isPlainObject, isEmptyObject, isHTMLElement } from 'core/utils/types';
|
||||
|
||||
const testfn = function () { };
|
||||
const testfnAsync = async function () { };
|
||||
|
||||
const typeNameValueMap = {
|
||||
null: null,
|
||||
undefined: undefined,
|
||||
void0: void 0,
|
||||
infinity: Infinity,
|
||||
number: 0,
|
||||
string: '0',
|
||||
booleanTrue: true,
|
||||
booleanFalse: false,
|
||||
function: testfn,
|
||||
functionAsync: testfnAsync,
|
||||
functionArrow: () => { },
|
||||
functionArrowAsync: async () => { },
|
||||
functionConstructor: new (testfn as any)(),
|
||||
arrayEmpty: [],
|
||||
objectEmpty: {},
|
||||
array: [1, 2, 3],
|
||||
object: { a: 1, b: 2, c: 3 },
|
||||
objectCreate: Object.create(null),
|
||||
arrayLikeObject: { 0: 0, 1: 1, 2: 2, length: 3 },
|
||||
newNumber: new Number(0),
|
||||
newString: new String('0'),
|
||||
newBoolean: new Boolean(false),
|
||||
newFunction: new Function(''),
|
||||
newArray: new Array(),
|
||||
document: document,
|
||||
window: window,
|
||||
body: document.body,
|
||||
querySelectorAll: document.querySelectorAll('*'),
|
||||
};
|
||||
|
||||
const testTypeFn = (typeFunc: Function, expectedTypeNameValueResultMap: any) => {
|
||||
Object.keys(typeNameValueMap).forEach(comparisonKey => {
|
||||
const comparisonValue = typeNameValueMap[comparisonKey];
|
||||
const result = typeFunc(comparisonValue);
|
||||
if (expectedTypeNameValueResultMap.hasOwnProperty(comparisonKey)) {
|
||||
const todoComparisonValue = expectedTypeNameValueResultMap[comparisonKey];
|
||||
expect(result + comparisonKey).toBe(todoComparisonValue + comparisonKey);
|
||||
}
|
||||
else {
|
||||
expect(result + comparisonKey).toBe(false + comparisonKey);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
describe('types', () => {
|
||||
test('type', () => {
|
||||
expect(type(undefined)).toBe("undefined");
|
||||
expect(type(null)).toBe("null");
|
||||
expect(type(true)).toBe("boolean");
|
||||
expect(type(new Boolean())).toBe("boolean");
|
||||
expect(type(3)).toBe("number");
|
||||
expect(type(new Number(3))).toBe("number");
|
||||
expect(type("test")).toBe("string");
|
||||
expect(type(new String("test"))).toBe("string");
|
||||
expect(type(function () { })).toBe("function");
|
||||
expect(type([])).toBe("array");
|
||||
expect(type(new Array())).toBe("array");
|
||||
expect(type(new Date())).toBe("date");
|
||||
expect(type(new Error())).toBe("error");
|
||||
expect(type(Symbol())).toBe("symbol");
|
||||
expect(type(Object(Symbol()))).toBe("symbol");
|
||||
expect(type(/test/)).toBe("regexp");
|
||||
});
|
||||
|
||||
test('isNumber', () => {
|
||||
testTypeFn(isNumber, {
|
||||
number: true,
|
||||
infinity: true,
|
||||
newNumber: false // new Number() not a number is ok
|
||||
});
|
||||
});
|
||||
|
||||
test('isString', () => {
|
||||
testTypeFn(isString, {
|
||||
string: true,
|
||||
newString: false // new String() not a string is ok
|
||||
});
|
||||
});
|
||||
|
||||
test('isBoolean', () => {
|
||||
testTypeFn(isBoolean, {
|
||||
booleanTrue: true,
|
||||
booleanFalse: true,
|
||||
newBoolean: false // new Boolean() not a boolean is ok
|
||||
});
|
||||
});
|
||||
|
||||
test('isFunction', () => {
|
||||
testTypeFn(isFunction, {
|
||||
function: true,
|
||||
functionAsync: true,
|
||||
functionArrow: true,
|
||||
functionArrowAsync: true,
|
||||
newFunction: true
|
||||
});
|
||||
});
|
||||
|
||||
test('isArray', () => {
|
||||
testTypeFn(isArray, {
|
||||
array: true,
|
||||
arrayEmpty: true,
|
||||
newArray: true,
|
||||
});
|
||||
});
|
||||
|
||||
test('isObject', () => {
|
||||
testTypeFn(isObject, {
|
||||
object: true,
|
||||
objectEmpty: true,
|
||||
objectCreate: true,
|
||||
document: true,
|
||||
window: true,
|
||||
body: true,
|
||||
querySelectorAll: true,
|
||||
functionConstructor: true,
|
||||
arrayLikeObject: true,
|
||||
|
||||
// is ok since nobody does this
|
||||
newNumber: true,
|
||||
newString: true,
|
||||
newBoolean: true,
|
||||
});
|
||||
});
|
||||
|
||||
test('isUndefined', () => {
|
||||
testTypeFn(isUndefined, {
|
||||
undefined: true,
|
||||
void0: true,
|
||||
});
|
||||
});
|
||||
|
||||
test('isNull', () => {
|
||||
testTypeFn(isNull, {
|
||||
null: true,
|
||||
});
|
||||
});
|
||||
|
||||
test('isArrayLike', () => {
|
||||
testTypeFn(isArrayLike, {
|
||||
array: true,
|
||||
arrayEmpty: true,
|
||||
arrayLikeObject: true,
|
||||
querySelectorAll: true,
|
||||
string: true,
|
||||
newString: true,
|
||||
newArray: true,
|
||||
// is ok I guess...
|
||||
window: true,
|
||||
});
|
||||
});
|
||||
|
||||
test('isPlainObject', () => {
|
||||
testTypeFn(isPlainObject, {
|
||||
object: true,
|
||||
objectEmpty: true,
|
||||
objectCreate: true,
|
||||
arrayLikeObject: true,
|
||||
});
|
||||
});
|
||||
|
||||
test('isEmptyObject', () => {
|
||||
testTypeFn(isEmptyObject, {
|
||||
objectEmpty: true,
|
||||
objectCreate: true,
|
||||
arrayEmpty: true,
|
||||
|
||||
newNumber: true,
|
||||
newBoolean: true,
|
||||
newFunction: true,
|
||||
newArray: true,
|
||||
|
||||
null: true,
|
||||
undefined: true,
|
||||
booleanTrue: true,
|
||||
booleanFalse: true,
|
||||
void0: true,
|
||||
number: true,
|
||||
infinity: true,
|
||||
functionConstructor: true,
|
||||
function: true,
|
||||
functionAsync: true,
|
||||
functionArrow: true,
|
||||
functionArrowAsync: true,
|
||||
});
|
||||
});
|
||||
|
||||
test('isHTMLElement', () => {
|
||||
const temp = window.HTMLElement;
|
||||
|
||||
testTypeFn(isHTMLElement, {
|
||||
body: true
|
||||
});
|
||||
Array.from(document.querySelectorAll('*')).forEach((elm) => {
|
||||
expect(isHTMLElement(elm)).toBeTruthy();
|
||||
});
|
||||
|
||||
delete window.HTMLElement;
|
||||
// @ts-ignore
|
||||
window.HTMLElement = null;
|
||||
|
||||
testTypeFn(isHTMLElement, {
|
||||
body: true
|
||||
});
|
||||
Array.from(document.querySelectorAll('*')).forEach((elm) => {
|
||||
expect(isHTMLElement(elm)).toBeTruthy();
|
||||
});
|
||||
|
||||
window.HTMLElement = temp;
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
import { addInstance, removeInstance, getInstance, allInstances } from 'instances';
|
||||
|
||||
const testElm = document.body;
|
||||
const testInstance = { value: 'value' };
|
||||
|
||||
describe('instances', () => {
|
||||
afterEach(() => {
|
||||
removeInstance(testElm);
|
||||
});
|
||||
|
||||
test('add instance', () => {
|
||||
addInstance(testElm, testInstance);
|
||||
|
||||
expect(allInstances().size).toBe(1);
|
||||
});
|
||||
|
||||
test('remove instance', () => {
|
||||
addInstance(testElm, testInstance);
|
||||
removeInstance(testElm);
|
||||
|
||||
expect(allInstances().size).toBe(0);
|
||||
});
|
||||
|
||||
test('get instance', () => {
|
||||
addInstance(testElm, testInstance);
|
||||
|
||||
expect(getInstance(testElm)).toBe(testInstance);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
import { validate } from 'core/options';
|
||||
import { defaultOptions, optionsTemplate } from 'options';
|
||||
|
||||
describe('options', () => {
|
||||
test('default options matching the options template', () => {
|
||||
const { validated } = validate(defaultOptions, optionsTemplate);
|
||||
expect(validated).toEqual(defaultOptions);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user