-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix mergeCollection bug #66
Changes from all commits
53d964e
141bda7
fed0198
c56b745
cb8e408
45b6bda
4aecf38
38d484b
8870f26
b2ef2d5
3397189
a8ab34e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,9 +42,7 @@ describe('withOnyx', () => { | |
expect(result).toHaveBeenCalledTimes(999); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('withOnyx', () => { | ||
it('should update withOnyx subscriber multiple times when merge is used', () => { | ||
const TestComponentWithOnyx = withOnyx({ | ||
text: { | ||
|
@@ -62,9 +60,7 @@ describe('withOnyx', () => { | |
expect(onRender.mock.calls.length).toBe(4); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('withOnyx', () => { | ||
it('should update withOnyx subscriber just once when mergeCollection is used', () => { | ||
const TestComponentWithOnyx = withOnyx({ | ||
text: { | ||
|
@@ -80,9 +76,7 @@ describe('withOnyx', () => { | |
expect(onRender.mock.calls.length).toBe(2); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('withOnyx', () => { | ||
it('should update withOnyx subscribing to individual key if mergeCollection is used', () => { | ||
const collectionItemID = 1; | ||
const TestComponentWithOnyx = withOnyx({ | ||
|
@@ -99,9 +93,7 @@ describe('withOnyx', () => { | |
expect(onRender.mock.calls.length).toBe(2); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('withOnyx', () => { | ||
it('should update withOnyx subscribing to individual key with merged value if mergeCollection is used', () => { | ||
const collectionItemID = 4; | ||
const TestComponentWithOnyx = withOnyx({ | ||
|
@@ -123,9 +115,7 @@ describe('withOnyx', () => { | |
expect(onRender.mock.instances[2].text).toEqual({ID: 456, Name: 'Test4'}); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('withOnyx', () => { | ||
it('should pass a prop from one connected component to another', () => { | ||
const collectionItemID = 1; | ||
const onRender = jest.fn(); | ||
|
@@ -152,4 +142,111 @@ describe('withOnyx', () => { | |
expect(onRender.mock.instances[0].testThing).toBe('Test'); | ||
}); | ||
}); | ||
|
||
it('using mergeCollection to modify one item should only effect one component', () => { | ||
const onRender1 = jest.fn(); | ||
const onRender2 = jest.fn(); | ||
const onRender3 = jest.fn(); | ||
|
||
// GIVEN there is a collection with three simple items in it | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NAB: I REALLY appreciate the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I love that format for testing comments. @nkuoch was the one that originally showed it to me! |
||
Onyx.mergeCollection(ONYX_KEYS.COLLECTION.TEST_KEY, { | ||
test_1: {ID: 1}, | ||
test_2: {ID: 2}, | ||
test_3: {ID: 3}, | ||
}); | ||
|
||
return waitForPromisesToResolve() | ||
.then(() => { | ||
// WHEN three components subscribe to each of the items in that collection | ||
const TestComponentWithOnyx1 = compose( | ||
withOnyx({ | ||
testObject: { | ||
key: `${ONYX_KEYS.COLLECTION.TEST_KEY}1`, | ||
}, | ||
}), | ||
)(ViewWithCollections); | ||
render(<TestComponentWithOnyx1 onRender={onRender1} />); | ||
|
||
const TestComponentWithOnyx2 = compose( | ||
withOnyx({ | ||
testObject: { | ||
key: `${ONYX_KEYS.COLLECTION.TEST_KEY}2`, | ||
}, | ||
}), | ||
)(ViewWithCollections); | ||
render(<TestComponentWithOnyx2 onRender={onRender2} />); | ||
|
||
const TestComponentWithOnyx3 = compose( | ||
withOnyx({ | ||
testObject: { | ||
key: `${ONYX_KEYS.COLLECTION.TEST_KEY}3`, | ||
}, | ||
}), | ||
)(ViewWithCollections); | ||
render(<TestComponentWithOnyx3 onRender={onRender3} />); | ||
|
||
return waitForPromisesToResolve(); | ||
}) | ||
.then(() => { | ||
// WHEN a single item in the collection is updated with mergeCollect() | ||
Onyx.mergeCollection(ONYX_KEYS.COLLECTION.TEST_KEY, { | ||
test_1: {ID: 1, newProperty: 'yay'}, | ||
}); | ||
return waitForPromisesToResolve(); | ||
}) | ||
.then(() => { | ||
// THEN the component subscribed to the modified item should have the new version of the item | ||
// and all other components should be unchanged. | ||
// Note: each component is rendered twice. Once when it is initially rendered, and then again | ||
// when the collection is updated. That's why there are two checks here for each component. | ||
expect(onRender1).toHaveBeenCalledTimes(2); | ||
expect(onRender1.mock.calls[0][0].testObject).toStrictEqual({ID: 1}); | ||
expect(onRender1.mock.calls[1][0].testObject).toStrictEqual({ID: 1, newProperty: 'yay'}); | ||
|
||
expect(onRender2).toHaveBeenCalledTimes(1); | ||
expect(onRender2.mock.calls[0][0].testObject).toStrictEqual({ID: 2}); | ||
|
||
expect(onRender3).toHaveBeenCalledTimes(1); | ||
expect(onRender3.mock.calls[0][0].testObject).toStrictEqual({ID: 3}); | ||
}); | ||
}); | ||
|
||
it('mergeCollection should merge previous props correctly to the new state', () => { | ||
const onRender = jest.fn(); | ||
|
||
// GIVEN there is a collection with a simple item in it that has a `number` property set to 1 | ||
Onyx.mergeCollection(ONYX_KEYS.COLLECTION.TEST_KEY, { | ||
test_1: {ID: 1, number: 1}, | ||
}); | ||
|
||
return waitForPromisesToResolve() | ||
.then(() => { | ||
// WHEN a component subscribes to the one item in that collection | ||
const TestComponentWithOnyx = compose( | ||
withOnyx({ | ||
testObject: { | ||
key: `${ONYX_KEYS.COLLECTION.TEST_KEY}1`, | ||
}, | ||
}), | ||
)(ViewWithCollections); | ||
render(<TestComponentWithOnyx onRender={onRender} />); | ||
|
||
return waitForPromisesToResolve(); | ||
}) | ||
.then(() => { | ||
// WHEN the `number` property is updated using mergeCollection to be 2 | ||
Onyx.mergeCollection(ONYX_KEYS.COLLECTION.TEST_KEY, { | ||
test_1: {number: 2}, | ||
}); | ||
return waitForPromisesToResolve(); | ||
}) | ||
.then(() => { | ||
// THEN the component subscribed to the modified item should be rendered twice. | ||
// The first time it will render with number === 1 | ||
// The second time it will render with number === 2 | ||
expect(onRender).toHaveBeenCalledTimes(2); | ||
expect(onRender.mock.calls[0][0].testObject).toStrictEqual({ID: 1, number: 1}); | ||
expect(onRender.mock.calls[1][0].testObject).toStrictEqual({ID: 1, number: 2}); | ||
}); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems potentially dangerous as it assumes we will always have at least an empty object for
prevState[subscriber.statePropertyName]
if we are dealing with object shaped data. If we try to spread something likeundefined
ornull
then we get 💥.Maybe some combination of
lodash.merge()
could still be helpful here to help guard against that?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe there's no problem with that actually. I could just have made that up in my head.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think spreading
undefined
in objects works OK but arrays doesn't.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess the small difference between this and using
lodashMerge()
is that the spread is not going to recursively merge the data. So depending on how complicated that data is we could get some weird results. But we can address that if it becomes a problem.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, thanks Marc. I think it'll be OK for now. Seeing as how everyone has approved this, I'm going to go ahead and merge it.