diff --git a/API.md b/API.md index 62582f782..1fd4e6213 100644 --- a/API.md +++ b/API.md @@ -220,7 +220,7 @@ Insert API responses and lifecycle data into Onyx | Param | Type | Description | | --- | --- | --- | -| data | Array | An array of objects with shape {onyxMethod: oneOf('set', 'merge'), key: string, value: *} | +| data | Array | An array of objects with shape {onyxMethod: oneOf('set', 'merge', 'mergeCollection'), key: string, value: *} | diff --git a/lib/Onyx.js b/lib/Onyx.js index 1ed4db16e..1720367c0 100644 --- a/lib/Onyx.js +++ b/lib/Onyx.js @@ -812,12 +812,12 @@ 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'), key: string, value: *} + * @param {Array} data An array of objects with shape {onyxMethod: oneOf('set', 'merge', 'mergeCollection'), key: string, value: *} */ function update(data) { // First, validate the Onyx object is in the format we expect _.each(data, ({onyxMethod, key}) => { - if (!_.contains(['set', 'merge'], onyxMethod)) { + if (!_.contains(['set', 'merge', 'mergeCollection'], onyxMethod)) { throw new Error(`Invalid onyxMethod ${onyxMethod} in Onyx update.`); } if (!_.isString(key)) { @@ -833,6 +833,9 @@ function update(data) { case 'merge': merge(key, value); break; + case 'mergeCollection': + mergeCollection(key, value); + break; default: break; } diff --git a/tests/unit/onyxTest.js b/tests/unit/onyxTest.js index 670dafe95..48772a81f 100644 --- a/tests/unit/onyxTest.js +++ b/tests/unit/onyxTest.js @@ -358,6 +358,89 @@ describe('Onyx', () => { }); }); + it('should use update data object to merge a collection of keys', () => { + const valuesReceived = {}; + const mockCallback = jest.fn(data => valuesReceived[data.ID] = data.value); + connectionID = Onyx.connect({ + key: ONYX_KEYS.COLLECTION.TEST_KEY, + initWithStoredValues: false, + callback: mockCallback, + }); + + return waitForPromisesToResolve() + .then(() => { + // GIVEN the initial Onyx state: {test_1: {existingData: 'test',}, test_2: {existingData: 'test',}} + Onyx.multiSet({ + test_1: { + existingData: 'test', + }, + test_2: { + existingData: 'test', + }, + }); + return waitForPromisesToResolve(); + }) + .then(() => { + expect(mockCallback.mock.calls[0][0]).toEqual({existingData: 'test'}); + expect(mockCallback.mock.calls[0][1]).toEqual('test_1'); + + expect(mockCallback.mock.calls[1][0]).toEqual({existingData: 'test'}); + expect(mockCallback.mock.calls[1][1]).toEqual('test_2'); + + // WHEN we pass a mergeCollection data object to Onyx.update + Onyx.update([ + { + onyxMethod: 'mergeCollection', + key: ONYX_KEYS.COLLECTION.TEST_KEY, + value: { + test_1: { + ID: 123, + value: 'one', + }, + test_2: { + ID: 234, + value: 'two', + }, + test_3: { + ID: 345, + value: 'three', + }, + }, + }, + ]); + return waitForPromisesToResolve(); + }) + .then(() => { + /* THEN the final Onyx state should be: + { + test_1: { + existingData: 'test' + ID: 123, + value: 'one', + }, + test_2: { + existingData: 'test' + ID: 234, + value: 'two', + }, + test_3: { + ID: 345, + value: 'three', + }, + } + */ + + expect(mockCallback.mock.calls[2][0]).toEqual({ID: 123, value: 'one', existingData: 'test'}); + expect(mockCallback.mock.calls[2][1]).toEqual('test_1'); + + expect(mockCallback.mock.calls[3][0]).toEqual({ID: 234, value: 'two', existingData: 'test'}); + expect(mockCallback.mock.calls[3][1]).toEqual('test_2'); + + expect(mockCallback.mock.calls[4][0]).toEqual({ID: 345, value: 'three'}); + expect(mockCallback.mock.calls[4][1]).toEqual('test_3'); + }); + }); + it('should throw an error when the data object is incorrect in Onyx.update', () => { // GIVEN the invalid data object with onyxMethod='multiSet' const data = [