Allow silent changes to observed property
This commit is contained in:
parent
ae6b90bee3
commit
e634e3a01d
@ -30,6 +30,9 @@ export default class uObserve {
|
||||
* @param {ObserveCallback=} p2
|
||||
*/
|
||||
static observe(obj, p1, p2) {
|
||||
if (typeof obj !== 'object' || obj === null) {
|
||||
throw new Error('Invalid argument: invalid object');
|
||||
}
|
||||
if (typeof p2 === 'function') {
|
||||
this.observeProperty(obj, p1, p2);
|
||||
} else if (typeof p1 === 'function') {
|
||||
@ -62,6 +65,31 @@ export default class uObserve {
|
||||
}
|
||||
}
|
||||
|
||||
static isObserved(obj, property) {
|
||||
if (typeof obj !== 'object' || obj === null) {
|
||||
return false;
|
||||
}
|
||||
return obj.hasOwnProperty(property) && obj.hasOwnProperty('_values') &&
|
||||
obj._values.hasOwnProperty(property) && !!Object.getOwnPropertyDescriptor(obj, property)['set'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set observed property value without notifying observers
|
||||
* @param {Object} obj
|
||||
* @param {string} property
|
||||
* @param {*} value
|
||||
*/
|
||||
static setSilently(obj, property, value) {
|
||||
if (!obj.hasOwnProperty(property)) {
|
||||
throw new Error(`Invalid argument: object does not have property "${property}"`);
|
||||
}
|
||||
if (this.isObserved(obj, property)) {
|
||||
obj._values[property] = value;
|
||||
} else {
|
||||
obj[property] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Observe object's property. On change call observer
|
||||
* @param {Object} obj
|
||||
@ -69,6 +97,9 @@ export default class uObserve {
|
||||
* @param {ObserveCallback} observer
|
||||
*/
|
||||
static observeProperty(obj, property, observer) {
|
||||
if (!obj.hasOwnProperty(property)) {
|
||||
throw new Error(`Invalid argument: object does not have property "${property}"`);
|
||||
}
|
||||
this.addObserver(obj, observer, property);
|
||||
if (!obj.hasOwnProperty('_values')) {
|
||||
Object.defineProperty(obj, '_values', { enumerable: false, configurable: false, value: {} });
|
||||
|
@ -334,6 +334,65 @@ describe('Observe tests', () => {
|
||||
expect(resultValue2).toEqual(undefined);// eslint-disable-line no-undefined
|
||||
expect(array).toEqual([ 1, 2, 3 ]);
|
||||
});
|
||||
|
||||
it('should throw error when observing non-existing property', () => {
|
||||
// given
|
||||
const nonExisting = '___non-existing___';
|
||||
|
||||
expect(object.hasOwnProperty(nonExisting)).toBe(false);
|
||||
// then
|
||||
expect(() => uObserve.observe(object, nonExisting, (value) => {
|
||||
result = true;
|
||||
resultValue = value;
|
||||
})).toThrow();
|
||||
|
||||
expect(object.hasOwnProperty(nonExisting)).toBe(false);
|
||||
});
|
||||
|
||||
it('should throw error when observing non-object', () => {
|
||||
// given
|
||||
const nonExisting = '___non-existing___';
|
||||
// then
|
||||
expect(() => uObserve.observe(nonExisting, (value) => {
|
||||
result = true;
|
||||
resultValue = value;
|
||||
})).toThrow();
|
||||
});
|
||||
|
||||
it('should throw error when observing null object', () => {
|
||||
// given
|
||||
const nullObject = null;
|
||||
// then
|
||||
expect(() => uObserve.observe(nullObject, (value) => {
|
||||
result = true;
|
||||
resultValue = value;
|
||||
})).toThrow();
|
||||
});
|
||||
|
||||
it('should not notify observers when observed property is silently changed', () => {
|
||||
// given
|
||||
uObserve.observe(object, 'observed', (value) => {
|
||||
result = true;
|
||||
resultValue = value;
|
||||
});
|
||||
// when
|
||||
expect(result).toBe(false);
|
||||
uObserve.setSilently(object, 'observed', 2);
|
||||
// then
|
||||
expect(result).toBe(false);
|
||||
// eslint-disable-next-line no-undefined
|
||||
expect(resultValue).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should return true if property is observed', () => {
|
||||
// when
|
||||
uObserve.observe(object, 'observed', (value) => {
|
||||
result = true;
|
||||
resultValue = value;
|
||||
});
|
||||
// then
|
||||
expect(uObserve.isObserved(object, 'observed')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when notify is called directly', () => {
|
||||
@ -351,5 +410,6 @@ describe('Observe tests', () => {
|
||||
expect(result).toBe(true);
|
||||
expect(result2).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user