UNPKG

@v4fire/core

Version:
646 lines (519 loc) 10.6 kB
/* eslint-disable max-lines-per-function, max-lines */ /*! * V4Fire Core * https://github.com/V4Fire/Core * * Released under the MIT license * https://github.com/V4Fire/Core/blob/master/LICENSE */ describe('core/prelude/object/mixin', () => { it('simple extending of an object', () => { const base = { a: 1, b: 2 }; const clone = Object.mixin(false, {}, base); expect(clone).not.toBe(base); expect(clone).toEqual(base); }); it('simple extending of an object without specifying the base object', () => { const base = { a: 1, b: 2 }; const clone = Object.mixin(false, undefined, base); expect(clone).not.toBe(base); expect(clone).toEqual(base); }); it('simple extending of an array', () => { const base = [1, 2], clone = Object.mixin(false, undefined, base); expect(clone).not.toBe(base); expect(clone).toEqual(base); }); it('simple extending of a map', () => { const base = new Map([[0, 1], [1, 2]]), clone = Object.mixin(false, undefined, base); expect(clone).not.toBe(base); expect(clone).toEqual(base); }); it('simple extend of a weak map', () => { const key1 = Object(0), key2 = Object(1); const base = new Map([[key1, 1], [key2, 2]]), clone = Object.mixin(false, new WeakMap(), base); expect(clone).not.toBe(base); expect(clone instanceof WeakMap).toBeTruthy(); expect(clone.has(key1)).toBeTruthy(); expect(clone.has(key2)).toBeTruthy(); }); it('simple extending of a set', () => { const base = new Set([1, 2]), clone = Object.mixin(false, undefined, base); expect(clone).not.toBe(base); expect(clone).toEqual(base); }); it('simple extending of a weak set', () => { const key1 = Object(0), key2 = Object(1); const base = new Set([key1, key2]), clone = Object.mixin(false, new WeakSet(), base); expect(clone).not.toBe(base); expect(clone instanceof WeakSet).toBeTruthy(); expect(clone.has(key1)).toBeTruthy(); expect(clone.has(key2)).toBeTruthy(); }); it('extending of an object with undefined fields', () => { const base = { a: 1, b: 2, c: undefined }; const clone1 = Object.mixin(false, undefined, base); expect(clone1).not.toBe(base); expect(clone1).toEqual({a: 1, b: 2}); const clone2 = Object.mixin({skipUndefs: false}, undefined, base); expect(clone2).not.toBe(base); expect(clone2).toEqual(base); }); it('extending of an object with undefined fields (legacy)', () => { const base = { a: 1, b: 2, c: undefined }; const clone1 = Object.mixin(false, undefined, base); expect(clone1).not.toBe(base); expect(clone1).toEqual({a: 1, b: 2}); const clone2 = Object.mixin({withUndef: true}, undefined, base); expect(clone2).not.toBe(base); expect(clone2).toEqual(base); }); it('extending of an object with new properties', () => { const base1 = { a: 1, b: 2 }; const base2 = { a: 2, c: 3 }; expect(Object.mixin({propsToCopy: 'new'}, undefined, base1, base2)).toEqual({ a: 1, b: 2, c: 3 }); }); it('extending of an object with new properties (legacy)', () => { const base1 = { a: 1, b: 2 }; const base2 = { a: 2, c: 3 }; expect(Object.mixin({onlyNew: true}, undefined, base1, base2)).toEqual({ a: 1, b: 2, c: 3 }); }); it('extending of an object with not new properties', () => { const base1 = { a: 1, b: 2 }; const base2 = { a: 2, c: 3 }; expect(Object.mixin({propsToCopy: 'exist'}, base1, base2)).toEqual({ a: 2, b: 2 }); }); it('extending of an object with not new properties (legacy)', () => { const base1 = { a: 1, b: 2 }; const base2 = { a: 2, c: 3 }; expect(Object.mixin({onlyNew: -1}, base1, base2)).toEqual({ a: 2, b: 2 }); }); it('extending of an object with accessors', () => { const base = { _a: 1, get a() { return this._a; }, set a(value) { this._a = value; } }; const clone = Object.mixin({withDescriptors: 'onlyAccessors'}, undefined, base); expect(clone).not.toBe(base); expect(clone._a).toBe(1); clone.a = 2; expect(clone._a).toBe(2); }); it('extending of an object with accessors (legacy)', () => { const base = { _a: 1, get a() { return this._a; }, set a(value) { this._a = value; } }; const clone = Object.mixin({withAccessors: true}, undefined, base); expect(clone).not.toBe(base); expect(clone._a).toBe(1); clone.a = 2; expect(clone._a).toBe(2); }); it('extending of an object with descriptors', () => { const base = {}; Object.defineProperty(base, 'a', { enumerable: true, writable: false, value: 1 }); const clone = Object.mixin({withDescriptors: true}, undefined, base); expect(clone).not.toBe(base); expect(Object.getOwnPropertyDescriptor(clone, 'a')).toEqual({ enumerable: true, configurable: false, writable: false, value: 1 }); }); it('extending of an object with descriptors (legacy)', () => { const base = {}; Object.defineProperty(base, 'a', { enumerable: true, writable: false, value: 1 }); const clone = Object.mixin({withDescriptor: true}, undefined, base); expect(clone).not.toBe(base); expect(Object.getOwnPropertyDescriptor(clone, 'a')).toEqual({ enumerable: true, configurable: false, writable: false, value: 1 }); }); it('extending of an object with the prototype', () => { const proto = { a: 1, b: { c: 2, arr: [1] } }; const base1 = Object.create(proto); Object.mixin(false, base1, { a: 2, b: { e: 3, arr: [2] } }); expect(base1).toEqual({ a: 2, b: { e: 3, arr: [2] } }); expect(proto).toEqual({ a: 1, b: { c: 2, arr: [1] } }); const base2 = Object.create(proto); Object.mixin({deep: true, withProto: true}, base2, { a: 2, b: { e: 3 } }); expect(base2).toEqual({ a: 2, b: { e: 3 } }); expect(proto).toEqual({ a: 1, b: { c: 2, arr: [1] } }); expect(Object.mixin({deep: true, withProto: true}, {}, base2)).toEqual({ a: 2, b: { c: 2, e: 3, arr: [1] } }); const base3 = Object.create(proto); Object.mixin({deep: true, withProto: true}, base3, { a: 2, b: { c: 3, arr: [1] } }); expect(base3).toEqual({ a: 2, b: { c: 3, arr: [1] } }); expect(proto).toEqual({ a: 1, b: { c: 2, arr: [1] } }); const base4 = Object.create(proto); Object.mixin({deep: true}, base4, { a: 2, b: { c: 3, arr: [1] } }); expect(base4).toEqual({ a: 2, b: { c: 3, arr: [1] } }); expect(proto).toEqual({ a: 1, b: { c: 3, arr: [1] } }); }); it('deep extending', () => { const base = { a: { b: 2 }, c: new Set([1, 2, 3]), d: [1, 2, 3] }; Object.mixin(true, base, { a: { b: 3, b2: 3 }, c: new Set([4]), d: [2, 3] }); expect(base).toEqual({ a: { b: 3, b2: 3 }, c: new Set([1, 2, 3, 4]), d: [2, 3, 3] }); }); it('deep extending with not own properties', () => { expect(Object.mixin(false, {}, {__proto__: {a: 1}})).toEqual({}); expect(Object.mixin(true, {}, {__proto__: {a: 1}})).toEqual({a: 1}); }); it('deep extending with non-enumerable properties', () => { const base = { a: 1, b: { c: 2 } }; Object.defineProperty(base.b, 'd', {value: 3}); expect(Object.mixin(true, {}, base)).toEqual({ a: 1, b: { c: 2 } }); expect(Object.mixin({deep: true, withNonEnumerables: true}, {}, base)).toEqual({ a: 1, b: { c: 2, d: 3 } }); }); it('deep extending with the concatenation of arrays', () => { const base = { a: [1, 2, 3] }; Object.mixin({deep: true, concatArray: true}, base, { a: [2, 3] }); expect(base).toEqual({ a: [1, 2, 3, 2, 3] }); }); it('deep extending with preserving descriptors and concatenation of arrays', () => { const obj1 = {a: [1, 2, 3]}, obj2 = {}; Object.defineProperty(obj2, 'a', { enumerable: true, configurable: true, writable: false, value: [4, 5] }); const clone = Object.mixin({deep: true, concatArray: true, withDescriptors: true}, null, obj1, obj2); expect(clone).toEqual({ a: [1, 2, 3, 4, 5] }); expect(Object.getOwnPropertyDescriptor(clone, 'a')).toEqual({ enumerable: true, configurable: true, writable: false, value: [1, 2, 3, 4, 5] }); }); it('deep extending with the custom array concatenation', () => { const base = { a: [1, 2, 3] }; const concatFn = (a, b) => [...new Set(a.concat(b))]; Object.mixin({deep: true, concatArrays: concatFn}, base, { a: [2, 3, 4] }); expect(base).toEqual({ a: [1, 2, 3, 4] }); }); it('deep extending with the custom array concatenation (legacy)', () => { const base = { a: [1, 2, 3] }; const concatFn = (a, b) => [...new Set(a.concat(b))]; Object.mixin({deep: true, concatArray: true, concatFn}, base, { a: [2, 3, 4] }); expect(base).toEqual({ a: [1, 2, 3, 4] }); }); it('deep extending with {arrayConcat: true, withProto: true}', () => { const proto = { a: [1, 2, 3] }; const clone = Object.mixin({deep: true, concatArray: true}, Object.create(proto), { a: [2, 3] }); expect(clone).toEqual({ a: [1, 2, 3, 2, 3] }); expect(proto).toEqual({ a: [1, 2, 3] }); }); it('deep extending with the custom filter', () => { const base = { a: { b: 2 }, c: new Set([1, 2, 3]) }; const filter = (val) => { if (val instanceof Set) { return false; } return true; }; Object.mixin({deep: true, filter}, base, { a: { b: 3, b2: 3 }, c: new Set([4]) }); expect(base).toEqual({ a: { b: 3, b2: 3 }, c: new Set([1, 2, 3]) }); }); it('deep extending with the custom extend filter', () => { const base = { a: { b: 2 }, c: new Set([1, 2, 3]) }; const extendFilter = (val) => !(val instanceof Set); Object.mixin({deep: true, extendFilter}, base, { a: { b: 3, b2: 3 }, c: new Set([4]) }); expect(base).toEqual({ a: { b: 3, b2: 3 }, c: new Set([4]) }); }); it('functional overloads', () => { expect(Object.mixin({propsToCopy: 'new'})({a: 1}, {a: 2, b: 2})).toEqual({a: 1, b: 2}); expect(Object.mixin({propsToCopy: 'new'}, {a: 1})({a: 2, b: 2})).toEqual({a: 1, b: 2}); }); });