diff --git a/lib/Onyx.js b/lib/Onyx.js index 55ea0c276..27f49aec2 100644 --- a/lib/Onyx.js +++ b/lib/Onyx.js @@ -14,6 +14,7 @@ const METHOD = { SET: 'set', MERGE: 'merge', MERGE_COLLECTION: 'mergecollection', + MULTI_SET: 'multiset', CLEAR: 'clear', }; @@ -1285,16 +1286,21 @@ function mergeCollection(collectionKey, collection) { /** * Insert API responses and lifecycle data into Onyx * - * @param {Array} data An array of objects with shape {onyxMethod: oneOf('set', 'merge', 'mergeCollection'), key: string, value: *} + * @param {Array} data An array of objects with shape {onyxMethod: oneOf('set', 'merge', 'mergeCollection', 'multiSet', 'clear'), key: string, value: *} * @returns {Promise} resolves when all operations are complete */ function update(data) { // First, validate the Onyx object is in the format we expect - _.each(data, ({onyxMethod, key}) => { - if (!_.contains([METHOD.CLEAR, METHOD.SET, METHOD.MERGE, METHOD.MERGE_COLLECTION], onyxMethod)) { + _.each(data, ({onyxMethod, key, value}) => { + if (!_.contains([METHOD.CLEAR, METHOD.SET, METHOD.MERGE, METHOD.MERGE_COLLECTION, METHOD.MULTI_SET], onyxMethod)) { throw new Error(`Invalid onyxMethod ${onyxMethod} in Onyx update.`); } - if (onyxMethod !== METHOD.CLEAR && !_.isString(key)) { + if (onyxMethod === METHOD.MULTI_SET) { + // For multiset, we just expect the value to be an object + if (!_.isObject(value) || _.isArray(value) || _.isFunction(value)) { + throw new Error('Invalid value provided in Onyx multiSet. Onyx multiSet value must be of type object.'); + } + } else if (onyxMethod !== METHOD.CLEAR && !_.isString(key)) { throw new Error(`Invalid ${typeof key} key provided in Onyx update. Onyx key must be of type string.`); } }); @@ -1313,6 +1319,9 @@ function update(data) { case METHOD.MERGE_COLLECTION: promises.push(() => mergeCollection(key, value)); break; + case METHOD.MULTI_SET: + promises.push(() => multiSet(value)); + break; case METHOD.CLEAR: clearPromise = clear(); break; diff --git a/tests/unit/onyxTest.js b/tests/unit/onyxTest.js index 6f5ef2f2c..5b10e2589 100644 --- a/tests/unit/onyxTest.js +++ b/tests/unit/onyxTest.js @@ -494,7 +494,7 @@ describe('Onyx', () => { // Given the invalid data object with onyxMethod='multiSet' const data = [ {onyxMethod: 'set', key: ONYX_KEYS.TEST_KEY, value: 'four'}, - {onyxMethod: 'multiSet', key: ONYX_KEYS.OTHER_TEST, value: {test2: 'test2'}}, + {onyxMethod: 'murge', key: ONYX_KEYS.OTHER_TEST, value: {test2: 'test2'}}, ]; try { @@ -502,7 +502,7 @@ describe('Onyx', () => { Onyx.update(data); } catch (error) { // Then we should expect the error message below - expect(error.message).toEqual('Invalid onyxMethod multiSet in Onyx update.'); + expect(error.message).toEqual('Invalid onyxMethod murge in Onyx update.'); } try { @@ -517,6 +517,74 @@ describe('Onyx', () => { } }); + it('should properly set all keys provided in a multiSet called via update', () => { + const valuesReceived = {}; + connectionID = Onyx.connect({ + key: ONYX_KEYS.COLLECTION.TEST_KEY, + initWithStoredValues: false, + callback: (data, key) => valuesReceived[key] = data, + }); + + return Onyx.multiSet({ + test_1: { + existingData: 'test', + }, + test_2: { + existingData: 'test', + }, + }) + .then(() => Onyx.update([ + { + onyxMethod: 'multiset', + value: { + test_1: { + ID: 123, + value: 'one', + }, + test_2: { + ID: 234, + value: 'two', + }, + }, + }, + ])) + .then(() => { + expect(valuesReceived).toEqual({ + test_1: { + ID: 123, + value: 'one', + }, + test_2: { + ID: 234, + value: 'two', + }, + }); + }); + }); + + it('should reject an improperly formatted multiset operation called via update', () => { + try { + Onyx.update([ + { + onyxMethod: 'multiset', + value: [ + { + ID: 123, + value: 'one', + }, + { + ID: 234, + value: 'two', + }, + ], + }, + ]); + } catch (error) { + expect(error.message) + .toEqual('Invalid value provided in Onyx multiSet. Onyx multiSet value must be of type object.'); + } + }); + it('should return all collection keys as a single object when waitForCollectionCallback = true', () => { const mockCallback = jest.fn();