-
Notifications
You must be signed in to change notification settings - Fork 74
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 cache for missing keys and empty collections #401
Changes from 2 commits
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 |
---|---|---|
|
@@ -6,6 +6,7 @@ import ViewWithText from '../components/ViewWithText'; | |
import ViewWithCollections from '../components/ViewWithCollections'; | ||
import waitForPromisesToResolve from '../utils/waitForPromisesToResolve'; | ||
import ViewWithObject from '../components/ViewWithObject'; | ||
import StorageMock from '../../lib/storage'; | ||
|
||
const ONYX_KEYS = { | ||
TEST_KEY: 'test', | ||
|
@@ -522,4 +523,112 @@ describe('withOnyxTest', () => { | |
expect(onRender.mock.calls[3][0].simple).toBe('long_string'); | ||
}); | ||
}); | ||
|
||
it('should render immediately when a onyx component is mounted a 2nd time', () => { | ||
const TestComponentWithOnyx = withOnyx({ | ||
text: { | ||
key: ONYX_KEYS.TEST_KEY, | ||
}, | ||
})(ViewWithText); | ||
const onRender = jest.fn(); | ||
let renderResult; | ||
|
||
// Set the value in storage, but not in cache. | ||
return StorageMock.setItem(ONYX_KEYS.TEST_KEY, 'test1') | ||
.then(() => { | ||
renderResult = render(<TestComponentWithOnyx onRender={onRender} />); | ||
|
||
// The component should not render initially since we have no data in cache. | ||
// Use `waitForPromisesToResolve` before making the assertions and make sure | ||
// onRender was not called. | ||
expect(onRender).not.toHaveBeenCalled(); | ||
return waitForPromisesToResolve(); | ||
}) | ||
.then(waitForPromisesToResolve) | ||
.then(() => { | ||
let textComponent = renderResult.getByText('test1'); | ||
expect(textComponent).not.toBeNull(); | ||
expect(onRender).toHaveBeenCalledTimes(1); | ||
|
||
// Unmount the component and mount it again. It should now render immediately. | ||
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. Is the only way to know that it wasn't rendered immediately because the test doesn't need to add a 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. Yes, if the assertion passes right away, before 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. +1 |
||
// Do not use `waitForPromisesToResolve` before making the assertions and make sure | ||
// onRender was called. | ||
renderResult.unmount(); | ||
renderResult = render(<TestComponentWithOnyx onRender={onRender} />); | ||
|
||
textComponent = renderResult.getByText('test1'); | ||
expect(textComponent).not.toBeNull(); | ||
expect(onRender).toHaveBeenCalledTimes(2); | ||
}); | ||
}); | ||
|
||
it('should cache missing keys', () => { | ||
const TestComponentWithOnyx = withOnyx({ | ||
text: { | ||
key: ONYX_KEYS.TEST_KEY, | ||
}, | ||
})(ViewWithText); | ||
const onRender = jest.fn(); | ||
|
||
// Render with a key that doesn't exist in cache or storage. | ||
let renderResult = render(<TestComponentWithOnyx onRender={onRender} />); | ||
|
||
// The component should not render initially since we have no data in cache. | ||
// Use `waitForPromisesToResolve` before making the assertions and make sure | ||
// onRender was not called. | ||
expect(onRender).not.toHaveBeenCalled(); | ||
return waitForPromisesToResolve().then(() => { | ||
let textComponent = renderResult.getByText('null'); | ||
expect(textComponent).not.toBeNull(); | ||
expect(onRender).toHaveBeenCalledTimes(1); | ||
|
||
// Unmount the component and mount it again. It should now render immediately. | ||
// Do not use `waitForPromisesToResolve` before making the assertions and make sure | ||
// onRender was called. | ||
renderResult.unmount(); | ||
renderResult = render(<TestComponentWithOnyx onRender={onRender} />); | ||
textComponent = renderResult.getByText('null'); | ||
expect(textComponent).not.toBeNull(); | ||
expect(onRender).toHaveBeenCalledTimes(2); | ||
}); | ||
}); | ||
|
||
it('should cache empty collections', () => { | ||
const TestComponentWithOnyx = withOnyx({ | ||
text: { | ||
key: ONYX_KEYS.COLLECTION.TEST_KEY, | ||
}, | ||
})(ViewWithCollections); | ||
const onRender = jest.fn(); | ||
let renderResult; | ||
|
||
// Set a random item in storage since Onyx will only think keys are loaded | ||
// in cache if there are at least one key. | ||
return StorageMock.setItem(ONYX_KEYS.SIMPLE_KEY, 'simple') | ||
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. Curious why do we need to add this key? is it just so there is something in the onyx storage? 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. Yea to know if all keys are in cache we currently check if the array length is > 0 so if the storage is empty the check never works. |
||
.then(() => { | ||
// Render with a collection that doesn't exist in cache or storage. | ||
renderResult = render(<TestComponentWithOnyx onRender={onRender} />); | ||
|
||
// The component should not render initially since we have no data in cache. | ||
// Use `waitForPromisesToResolve` before making the assertions and make sure | ||
// onRender was not called. | ||
expect(onRender).not.toHaveBeenCalled(); | ||
|
||
return waitForPromisesToResolve(); | ||
}) | ||
.then(() => { | ||
let textComponent = renderResult.getByText('empty'); | ||
expect(textComponent).not.toBeNull(); | ||
expect(onRender).toHaveBeenCalledTimes(1); | ||
|
||
// Unmount the component and mount it again. It should now render immediately. | ||
// Do not use `waitForPromisesToResolve` before making the assertions and make sure | ||
// onRender was called. | ||
renderResult.unmount(); | ||
renderResult = render(<TestComponentWithOnyx onRender={onRender} />); | ||
textComponent = renderResult.getByText('empty'); | ||
expect(textComponent).not.toBeNull(); | ||
expect(onRender).toHaveBeenCalledTimes(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.
How is it possible to not have all keys loaded yet (can you please add this to the code comment)?
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.
If we haven't called
getAllKeys
yet (from Onyx, not OnyxCache). Not sure if that can actually happen but to be safe this is prob better. I can clarify.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.
Ah, I did not notice the subtle difference between
getAllKeys
from Onyx vs OnyxCache.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.
Thinking a little more on this, can you please change
allKeys
to be renamed toallCacheKeys
?