diff --git a/umap/static/umap/js/modules/sync/updaters.js b/umap/static/umap/js/modules/sync/updaters.js index 15bbf06b..e934434b 100644 --- a/umap/static/umap/js/modules/sync/updaters.js +++ b/umap/static/umap/js/modules/sync/updaters.js @@ -11,20 +11,23 @@ class BaseUpdater { } updateObjectValue(obj, key, value) { - // XXX refactor so it's cleaner - let path = key.split('.') - let what - for (var i = 0, l = path.length; i < l; i++) { - what = path[i] - if (what === path[l - 1]) { - if (typeof value === 'undefined') { - delete obj[what] - } else { - obj[what] = value - } - } else { - obj = obj[what] - } + const parts = key.split('.') + const lastKey = parts.pop() + + // Reduce the current list of attributes, + // to find the object to set the property onto + const objectToSet = parts.reduce((currentObj, part) => { + if (part in currentObj) return currentObj[part] + }, obj) + + // In case the given path doesn't exist, bail out + if (objectToSet === undefined) return + + // Set the value (or delete it) + if (typeof value === 'undefined') { + delete objectToSet[lastKey] + } else { + objectToSet[lastKey] = value } } @@ -54,7 +57,7 @@ export class MapUpdater extends BaseUpdater { } export class DataLayerUpdater extends BaseUpdater { - upsert({ key, metadata, value }) { + upsert({ value }) { // Inserts does not happen (we use multiple updates instead). this.map.createDataLayer(value, false) } diff --git a/umap/static/umap/unittests/updaters.js b/umap/static/umap/unittests/updaters.js new file mode 100644 index 00000000..7a60a544 --- /dev/null +++ b/umap/static/umap/unittests/updaters.js @@ -0,0 +1,68 @@ +import { describe, it } from 'mocha' + +import pkg from 'chai' +const { expect } = pkg + +import { + MapUpdater, + DataLayerUpdater, + FeatureUpdater, +} from '../js/modules/sync/updaters.js' + +describe('Updaters', () => { + describe('BaseUpdater', function () { + let updater + let map + let obj + + this.beforeEach(function () { + map = {} + updater = new MapUpdater(map) + obj = {} + }) + it('should be able to set object properties', function () { + let obj = {} + updater.updateObjectValue(obj, 'foo', 'foo') + expect(obj).deep.equal({ foo: 'foo' }) + }) + + it('should be able to set object properties recursively on existing objects', function () { + let obj = { foo: {} } + updater.updateObjectValue(obj, 'foo.bar', 'foo') + expect(obj).deep.equal({ foo: { bar: 'foo' } }) + }) + + it('should be able to set object properties recursively on deep objects', function () { + let obj = { foo: { bar: { baz: {} } } } + updater.updateObjectValue(obj, 'foo.bar.baz.test', 'value') + expect(obj).deep.equal({ foo: { bar: { baz: { test: 'value' } } } }) + }) + + it('should be able to replace object properties recursively on deep objects', function () { + let obj = { foo: { bar: { baz: { test: 'test' } } } } + updater.updateObjectValue(obj, 'foo.bar.baz.test', 'value') + expect(obj).deep.equal({ foo: { bar: { baz: { test: 'value' } } } }) + }) + + it('should not set object properties recursively on non-existing objects', function () { + let obj = { foo: {} } + updater.updateObjectValue(obj, 'bar.bar', 'value') + + expect(obj).deep.equal({ foo: {} }) + }) + + it('should delete keys for undefined values', function () { + let obj = { foo: 'foo' } + updater.updateObjectValue(obj, 'foo', undefined) + + expect(obj).deep.equal({}) + }) + + it('should delete keys for undefined values, recursively', function () { + let obj = { foo: { bar: 'bar' } } + updater.updateObjectValue(obj, 'foo.bar', undefined) + + expect(obj).deep.equal({ foo: {} }) + }) + }) +})