Add tests missing for object* methods (#1171)

* Add tests missing for object* methods

* Extend objectProperty comments

* Additional test

* objectProperties this test

* Adjust
This commit is contained in:
Jaco
2021-11-11 14:38:58 +02:00
committed by GitHub
parent 67450bc225
commit 30dd8169bc
3 changed files with 142 additions and 3 deletions
+15
View File
@@ -0,0 +1,15 @@
// Copyright 2017-2021 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { objectCopy } from '.';
describe('objectCopy', (): void => {
it('makes a shallow copy of the object', (): void => {
const a = { a: 1, b: 2, c: { d: 3, e: 4 } };
const b = objectCopy(a);
expect(a).toEqual(b);
expect(a === b).toEqual(false);
expect(a.c === b.c).toEqual(true);
});
});
+120
View File
@@ -0,0 +1,120 @@
// Copyright 2017-2021 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { objectProperties, objectProperty } from '.';
describe('objectProperty/objectProperties', (): void => {
it('sets a property', (): void => {
const test: Record<string, unknown> = {};
expect(test.a).toEqual(undefined);
objectProperty(test, 'a', () => 2);
expect(test.a).toEqual(2);
});
it('does not override an existing property', (): void => {
const test: Record<string, unknown> = { a: 1 };
expect(test.a).toEqual(1);
objectProperty(test, 'a', () => 2);
expect(test.a).toEqual(1);
});
it('does not override an existing property (inherited)', (): void => {
class Parent extends Map<string, unknown> {
constructor () {
super();
this.set('a', 1);
}
get a (): unknown {
return this.get('a');
}
}
class Child extends Parent {
constructor () {
super();
this.set('b', 1);
}
get b (): unknown {
return this.get('b');
}
}
const test = new Child() as unknown as Record<string, unknown>;
expect(test.a).toEqual(1);
expect(test.b).toEqual(1);
expect(test.c).toEqual(undefined);
objectProperties(test, ['a', 'b', 'c'], () => 2);
expect(test.a).toEqual(1);
expect(test.b).toEqual(1);
expect(test.c).toEqual(2);
});
it('works with this used in classes', (): void => {
class Test extends Map<string, unknown> {
constructor () {
super();
this.set('a', 1);
objectProperty(this, 'a', (k) => this.get(k));
}
}
const test = new Test() as unknown as Record<string, unknown>;
expect(test.a).toEqual(1);
});
it('works with this used in classes (multiples)', (): void => {
class Test extends Map<string, unknown> {
constructor () {
super();
this.set('a', 1);
this.set('b', 2);
objectProperties(this, ['a', 'b'], (k) => this.get(k));
}
}
const test = new Test() as unknown as Record<string, unknown>;
expect(test.a).toEqual(1);
expect(test.b).toEqual(2);
});
it('calls back with the key name (single)', (): void => {
const test: Record<string, unknown> = {};
const getter = jest.fn(() => 123);
objectProperty(test, 'a', getter);
expect(getter).not.toHaveBeenCalled();
expect(test.a).toEqual(123);
expect(getter).toHaveBeenCalledWith('a');
});
it('calls back with the key name & index (numtiple)', (): void => {
const test: Record<string, unknown> = {};
const getter = jest.fn(() => 123);
objectProperties(test, ['a', 'b', 'c'], getter);
expect(getter).not.toHaveBeenCalled();
expect(test.b).toEqual(123);
expect(getter).toHaveBeenCalledWith('b', 1);
});
});
+7 -3
View File
@@ -11,9 +11,13 @@ export function objectProperty (that: object, key: string, getter: (k: string) =
// We use both the hasOwnProperty as well as isUndefined checks here, since it may be set
// in inherited classes and _Own_ properties refers to the class only, not only parents
if (!Object.prototype.hasOwnProperty.call(that, key) && isUndefined((that as Record<string, unknown>)[key])) {
const get = () => getter(key);
Object.defineProperty(that, key, { enumerable: true, get });
Object.defineProperty(that, key, {
enumerable: true,
// Since we don't use any additional this internally, we can use arrow (unlike lazy)
// Unlike in lazy, we always call into the upper function, i.e. this method
// does not cache old values (it is expected to be used for dynamic values)
get: () => getter(key)
});
}
}