From 2792b20e80af00727351d4ce22fdc2c4745cf1e3 Mon Sep 17 00:00:00 2001 From: Bartek Fabiszewski Date: Sat, 21 Dec 2019 14:48:59 +0100 Subject: [PATCH] Add method to check if property is observed by given observer --- js/src/observe.js | 22 +++++++++++++++---- js/test/observe.test.js | 47 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/js/src/observe.js b/js/src/observe.js index d0e2744..f766af9 100644 --- a/js/src/observe.js +++ b/js/src/observe.js @@ -61,12 +61,23 @@ export default class uObserve { } } - static isObserved(obj, property) { + /** + * Check if object property is observed; + * Optionally check if it is observed by given observer + * @param {Object} obj + * @param {string} property + * @param {Function=} observer + * @return {boolean} + */ + static isObserved(obj, property, observer) { if (typeof obj !== 'object' || obj === null || !obj.hasOwnProperty(property)) { return false; } - return obj.hasOwnProperty('_values') && obj._values.hasOwnProperty(property) && - !!Object.getOwnPropertyDescriptor(obj, property)['set']; + const isObserved = !!(obj._observers && obj._observers[property] && obj._observers[property].size > 0); + if (isObserved && observer) { + return obj._observers[property].has(observer); + } + return isObserved; } /** @@ -94,13 +105,16 @@ export default class uObserve { /** * Observe object's property. On change call observer * @param {Object} obj - * @param {?string} property + * @param {string} property * @param {ObserveCallback} observer */ static observeProperty(obj, property, observer) { if (!obj.hasOwnProperty(property)) { throw new Error(`Invalid argument: object does not have property "${property}"`); } + if (this.isObserved(obj, property, observer)) { + throw new Error(`Observer already registered for property ${property}`); + } this.addObserver(obj, observer, property); if (!obj.hasOwnProperty('_values')) { Object.defineProperty(obj, '_values', { enumerable: false, configurable: false, value: {} }); diff --git a/js/test/observe.test.js b/js/test/observe.test.js index 239fc8d..f105388 100644 --- a/js/test/observe.test.js +++ b/js/test/observe.test.js @@ -528,6 +528,53 @@ describe('Observe tests', () => { // then expect(uObserve.isObserved(object, 'observed')).toBe(true); }); + + it('should return false if property is not observed', () => { + // when + uObserve.observe(object, 'observed', (value) => { + result = true; + resultValue = value; + }); + // then + expect(uObserve.isObserved(object, 'nonObserved')).toBe(false); + }); + + it('should return true if array property is observed', () => { + // when + const array = [ 1, 2 ]; + object = { array: array }; + uObserve.observe(object, 'array', (value) => { + result = true; + resultValue = value; + }); + // then + expect(uObserve.isObserved(object, 'array')).toBe(true); + }); + + it('should return false if property is unobserved', () => { + // when + const observer = (value) => { + result = true; + resultValue = value; + }; + uObserve.observe(object, 'observed', observer); + uObserve.unobserve(object, 'observed', observer); + // then + expect(uObserve.isObserved(object, 'observed')).toBe(false); + }); + + it('should return true if property is observed by given observer', () => { + // when + const observer = (value) => { + result = true; + resultValue = value; + }; + const observer2 = () => {/* ignored */}; + uObserve.observe(object, 'observed', observer); + // then + expect(uObserve.isObserved(object, 'observed', observer)).toBe(true); + expect(uObserve.isObserved(object, 'observed', observer2)).toBe(false); + }); }); describe('when notify is called directly', () => {