UNPKG

@deepkit/core

Version:
479 lines 16.4 kB
import { expect, test } from '@jest/globals'; import { asyncOperation, changeClass, collectForMicrotask, createDynamicClass, getClassName, getClassTypeFromInstance, getObjectKeysSize, getParentClass, getPathValue, isArray, isAsyncFunction, isClass, isClassInstance, isConstructable, isFunction, isNumeric, isObject, isPlainObject, isPromise, isPrototypeOfBase, isUndefined, setPathValue, sleep, stringifyValueWithType } from '../src/core'; class SimpleClass { constructor(name) { this.name = name; } } SimpleClass.__type = ['name', 'constructor', 'P&2!:"0"5']; test('helper getClassName', () => { class User { constructor(name) { this.name = name; } } User.__type = ['name', 'constructor', 'P&2!:"0"5']; class MyError extends Error { } MyError.__type = ['5']; expect(getClassName(new User('peter'))).toBe('User'); expect(getClassName(User)).toBe('User'); expect(getClassName(MyError)).toBe('MyError'); expect(getClassName(new MyError)).toBe('MyError'); }); test('helper isObject', () => { expect(isObject([])).toBe(false); expect(isObject(false)).toBe(false); expect(isObject(true)).toBe(false); expect(isObject(null)).toBe(false); expect(isObject(undefined)).toBe(false); expect(isObject(() => { })).toBe(false); expect(isObject(function () { })).toBe(false); expect(isObject(1)).toBe(false); expect(isObject('1')).toBe(false); expect(isObject({})).toBe(true); expect(isObject(new Date())).toBe(true); expect(isObject(new SimpleClass('asd'))).toBe(true); }); test('helper isPromise', async () => { expect(isPromise([])).toBe(false); expect(isPromise(false)).toBe(false); expect(isPromise(true)).toBe(false); expect(isPromise(null)).toBe(false); expect(isPromise(undefined)).toBe(false); expect(isPromise(() => { })).toBe(false); expect(isPromise(function () { })).toBe(false); expect(isPromise(1)).toBe(false); expect(isPromise('1')).toBe(false); function foo1() { } foo1.__type = ['foo1', 'P"/!']; const foo2 = () => { }; expect(isPromise(foo1())).toBe(false); expect(isPromise(foo2())).toBe(false); async function foo3() { } foo3.__type = ['foo3', 'P"/!']; function foo4() { return new Promise(Object.assign((resolve) => { resolve(1); }, { __type: ['resolve', '', 'P"2!"/"'] })); } foo4.__type = ['foo4', 'P"/!']; expect(isObject(foo3())).toBe(true); expect(isObject(foo4())).toBe(true); expect(isObject(await foo4())).toBe(false); expect(isObject((async () => { })())).toBe(true); }); test('helper isFunction', () => { expect(isFunction([])).toBe(false); expect(isFunction(false)).toBe(false); expect(isFunction(true)).toBe(false); expect(isFunction(null)).toBe(false); expect(isFunction(undefined)).toBe(false); expect(isFunction(1)).toBe(false); expect(isFunction('1')).toBe(false); expect(isFunction({})).toBe(false); expect(isFunction(new Date())).toBe(false); expect(isFunction(new SimpleClass('asd'))).toBe(false); expect(isFunction(isFunction)).toBe(true); expect(isFunction(() => { })).toBe(true); expect(isFunction(async () => { })).toBe(true); expect(isFunction(function () { })).toBe(true); expect(isFunction(async function () { })).toBe(true); }); test('helper isAsyncFunction', () => { expect(isAsyncFunction([])).toBe(false); expect(isAsyncFunction(false)).toBe(false); expect(isAsyncFunction(true)).toBe(false); expect(isAsyncFunction(null)).toBe(false); expect(isAsyncFunction(undefined)).toBe(false); expect(isAsyncFunction(1)).toBe(false); expect(isAsyncFunction('1')).toBe(false); expect(isAsyncFunction({})).toBe(false); expect(isAsyncFunction(new Date())).toBe(false); expect(isAsyncFunction(new SimpleClass('asd'))).toBe(false); expect(isAsyncFunction(isFunction)).toBe(false); expect(isAsyncFunction(() => { })).toBe(false); expect(isAsyncFunction(async () => { })).toBe(true); expect(isAsyncFunction(function () { })).toBe(false); expect(isAsyncFunction(async function () { })).toBe(true); }); test('helper isClass', () => { expect(isClass([])).toBe(false); expect(isClass(false)).toBe(false); expect(isClass(true)).toBe(false); expect(isClass(null)).toBe(false); expect(isClass(undefined)).toBe(false); expect(isClass(1)).toBe(false); expect(isClass('1')).toBe(false); expect(isClass({})).toBe(false); expect(isClass(new Date())).toBe(false); expect(isClass(new SimpleClass('asd'))).toBe(false); expect(isClass(isFunction)).toBe(false); expect(isClass(() => { })).toBe(false); expect(isClass(async () => { })).toBe(false); expect(isClass(function () { })).toBe(false); expect(isClass(async function () { })).toBe(false); expect(isClass(SimpleClass)).toBe(true); }); test('helper isPlainObject', () => { expect(isPlainObject([])).toBe(false); expect(isPlainObject(false)).toBe(false); expect(isPlainObject(true)).toBe(false); expect(isPlainObject(null)).toBe(false); expect(isPlainObject(undefined)).toBe(false); expect(isPlainObject(1)).toBe(false); expect(isPlainObject('1')).toBe(false); expect(isPlainObject(() => { })).toBe(false); expect(isPlainObject(function () { })).toBe(false); expect(isPlainObject(new Date())).toBe(false); expect(isPlainObject(new SimpleClass('asd'))).toBe(false); class O extends Object { } O.__type = ['5']; expect(isPlainObject(new O)).toBe(false); expect(isPlainObject({})).toBe(true); expect(isPlainObject(new Object)).toBe(true); }); test('helper is array', () => { expect(isArray({})).toBe(false); expect(isArray(new Date())).toBe(false); expect(isArray(new SimpleClass('asd'))).toBe(false); expect(isArray(false)).toBe(false); expect(isArray(true)).toBe(false); expect(isArray(null)).toBe(false); expect(isArray(undefined)).toBe(false); expect(isArray(1)).toBe(false); expect(isArray('1')).toBe(false); expect(isArray([])).toBe(true); }); test('helper is isUndefined', () => { expect(isUndefined({})).toBe(false); expect(isUndefined(new Date())).toBe(false); expect(isUndefined(new SimpleClass('asd'))).toBe(false); expect(isUndefined(false)).toBe(false); expect(isUndefined(true)).toBe(false); expect(isUndefined(null)).toBe(false); expect(isUndefined(1)).toBe(false); expect(isUndefined('1')).toBe(false); expect(isUndefined([])).toBe(false); expect(isUndefined(undefined)).toBe(true); }); test('test getPathValue', () => { expect(getPathValue({ bla: 3 }, 'bla')).toBe(3); expect(getPathValue({ bla: 3 }, 'bla2', null)).toBe(null); expect(getPathValue({}, 'bla', 'another')).toBe('another'); }); test('test getPathValue deep', () => { expect(getPathValue({ bla: { mowla: 5 } }, 'bla.mowla')).toBe(5); expect(getPathValue({ 'bla.mowla': 5 }, 'bla.mowla')).toBe(5); expect(getPathValue({ bla: { mowla: { evenDeeper: true } } }, 'bla.mowla.evenDeeper')).toBe(true); expect(getPathValue({ bla: { mowla: { evenDeeper: true } } }, 'bla.mowla')['evenDeeper']).toBe(true); }); test('test setPathValue ', () => { { const obj = {}; setPathValue(obj, 'bla2', 5); expect(obj['bla2']).toBe(5); } { const obj = {}; setPathValue(obj, 'bla.mowla', 6); expect(obj['bla']['mowla']).toBe(6); } }); test('asyncOperation maintain error stack trace', async () => { class MyError extends Error { } MyError.__type = ['5']; let fetched = false; try { async function doIt() { await asyncOperation(Object.assign((resolve, reject) => { setTimeout(() => { reject(new MyError('MyError1')); }); }, { __type: ['resolve', 'reject', '', 'P"2!"2""/#'] })); } doIt.__type = ['doIt', 'P"/!']; await doIt(); } catch (error) { fetched = true; expect(error).toBeInstanceOf(MyError); expect(error.stack).toContain('MyError1'); expect(error.stack).toContain('doIt'); } expect(fetched).toBe(true); }); test('asyncOperation catches async errors', async () => { class MyError extends Error { } MyError.__type = ['5']; let fetched = false; try { async function doIt() { await asyncOperation(Object.assign(async (resolve) => { await sleep(0.2); throw new MyError('MyError1'); }, { __type: ['resolve', '', 'P"2!"/"'] })); } doIt.__type = ['doIt', 'P"/!']; await doIt(); } catch (error) { fetched = true; expect(error).toBeInstanceOf(MyError); expect(error.stack).toContain('MyError1'); expect(error.stack).toContain('doIt'); } expect(fetched).toBe(true); }); test('asyncOperation deep', async () => { let fetched = false; try { async function doIt1() { await asyncOperation(Object.assign(async (resolve) => { await sleep(0.2); async function doIt2() { await asyncOperation(Object.assign(async (resolve) => { await sleep(0.2); throw new Error('MyError2'); }, { __type: ['resolve', '', 'P"2!"/"'] })); } doIt2.__type = ['doIt2', 'P"/!']; ; await doIt2(); }, { __type: ['resolve', '', 'P"2!"/"'] })); } doIt1.__type = ['doIt1', 'P"/!']; await doIt1(); } catch (error) { fetched = true; expect(error.stack).toContain('MyError2'); expect(error.stack).toContain('doIt1'); expect(error.stack).toContain('doIt2'); } expect(fetched).toBe(true); }); test('getObjectKeysSize', async () => { expect(getObjectKeysSize({})).toBe(0); expect(getObjectKeysSize({ a: true })).toBe(1); expect(getObjectKeysSize({ a: 1, b: 1, c: 3, d: 4, e: {} })).toBe(5); }); test('isPrototypeOfBase', () => { class Base { } Base.__type = ['5']; class Child1 extends Base { } Child1.__type = ['5']; class Child2 extends Base { } Child2.__type = ['5']; class Child1_1 extends Child1 { } Child1_1.__type = ['5']; class Child1_1_1 extends Child1_1 { } Child1_1_1.__type = ['5']; expect(isPrototypeOfBase(Base, Base)).toBe(true); expect(isPrototypeOfBase(Child1, Base)).toBe(true); expect(isPrototypeOfBase(Child2, Base)).toBe(true); expect(isPrototypeOfBase(Child1_1, Base)).toBe(true); expect(isPrototypeOfBase(Child1_1, Child1)).toBe(true); expect(isPrototypeOfBase(Child1_1_1, Base)).toBe(true); expect(isPrototypeOfBase(Child1_1_1, Child1_1)).toBe(true); }); test('isConstructable', () => { var _a, _b; expect(isConstructable((_a = class { }, _a.__type = ['5'], _a))).toBe(true); expect(isConstructable((_b = class { }, _b.__type = ['5'], _b).bind(undefined))).toBe(true); expect(isConstructable(function () { })).toBe(true); expect(isConstructable(function () { }.bind(undefined))).toBe(true); expect(isConstructable(() => { })).toBe(false); expect(isConstructable((() => { }).bind(undefined))).toBe(false); expect(isConstructable(async () => { })).toBe(false); expect(isConstructable(async function () { })).toBe(false); expect(isConstructable(function* () { })).toBe(false); //the runtime type transformer converts this to `{foo: function() {}}.foo` which is constructable again :( // expect(isConstructable({foo() {}}.foo)).toBe(false); expect(isConstructable(URL)).toBe(true); }); test('collectForMicrotask', async () => { let got = []; const collected = Object.assign((strings) => { got.length = 0; got.push(...strings); }, { __type: ['strings', '', 'P&F2!"/"'] }); const fn = collectForMicrotask(collected); fn('a'); fn('b'); fn('c'); await sleep(0.1); expect(got).toEqual(['a', 'b', 'c']); fn('d'); await sleep(0.1); expect(got).toEqual(['d']); }); test('stringifyValueWithType', async () => { class Peter { constructor() { this.id = 1; } } Peter.__type = ['5']; expect(stringifyValueWithType(new Peter)).toBe(`Peter {id: number(1)}`); expect(stringifyValueWithType({ id: 1 })).toBe(`object {id: number(1)}`); expect(stringifyValueWithType('foo')).toBe(`string(foo)`); expect(stringifyValueWithType(2)).toBe(`number(2)`); expect(stringifyValueWithType(true)).toBe(`boolean(true)`); expect(stringifyValueWithType(Object.assign(function Peter() { }, { __type: ['Peter', 'P"/!'] }))).toBe(`function Peter`); }); test('getClassTypeFromInstance', async () => { class Peter { } Peter.__type = ['5']; expect(getClassTypeFromInstance(new Peter)).toBe(Peter); expect(() => getClassTypeFromInstance({})).toThrow('Value is not a class instance'); expect(() => getClassTypeFromInstance('asd')).toThrow('Value is not a class instance'); expect(() => getClassTypeFromInstance(23)).toThrow('Value is not a class instance'); expect(() => getClassTypeFromInstance(undefined)).toThrow('Value is not a class instance'); }); test('isClassInstance', async () => { class Peter { } Peter.__type = ['5']; expect(isClassInstance(new Peter)).toBe(true); expect(isClassInstance({})).toBe(false); expect(isClassInstance('asd')).toBe(false); expect(isClassInstance(undefined)).toBe(false); expect(isClassInstance(null)).toBe(false); expect(isClassInstance(3223)).toBe(false); }); test('isClassInstance', async () => { class Model1 { constructor() { this.id = 0; } } Model1.__type = ['id', function () { return 0; }, '\'3!>"5']; class Base { } Base.__type = ['5']; class Model2 extends Base { constructor() { super(...arguments); this.id = 0; } model2() { return true; } } Model2.__type = ['id', function () { return 0; }, 'model2', '\'3!>"P"0#5']; const model1 = new Model1; model1.id = 22; changeClass(model1, Model2); expect(model1 instanceof Model1).toBe(true); expect(changeClass(model1, Model2) instanceof Model2).toBe(true); expect(changeClass(model1, Model2) instanceof Base).toBe(true); expect(changeClass(model1, Model2) instanceof Model1).toBe(false); expect(changeClass(model1, Model2).model2()).toBe(true); }); test('createDynamicClass', () => { const class1 = createDynamicClass('Model'); expect(getClassName(class1)).toBe('Model'); expect(getClassName(new class1)).toBe('Model'); expect(class1.toString()).toBe('class Model {}'); class Base { } Base.__type = ['5']; const class2 = createDynamicClass('Model2', Base); expect(getClassName(class2)).toBe('Model2'); expect(getClassName(new class2)).toBe('Model2'); expect(new class2).toBeInstanceOf(Base); expect(class2.toString()).toBe('class Model2 extends Base {}'); }); test('isNumeric', () => { expect(isNumeric(12)).toBe(true); expect(isNumeric(12.2)).toBe(true); expect(isNumeric('12')).toBe(true); expect(isNumeric('12.2')).toBe(true); expect(isNumeric('12.2 ')).toBe(false); expect(isNumeric('12..2')).toBe(false); }); test('getParentClass', () => { class User { } User.__type = ['5']; class Admin extends User { } Admin.__type = ['5']; class SuperAdmin extends Admin { } SuperAdmin.__type = ['5']; expect(getParentClass({})).toBe(undefined); expect(getParentClass(Object)).toBe(undefined); expect(getParentClass(User)).toBe(undefined); expect(getParentClass(Admin)).toBe(User); expect(getParentClass(SuperAdmin)).toBe(Admin); }); //# sourceMappingURL=core.spec.js.map