Reputation: 1026
I have the following code:
const App = () => {
return (
<Provider store={store}>
<PersistGate persistor={persistor} loading={<Text>Loading!</Text>}>
<ConnectedRootComponent />
</PersistGate>
</Provider>
);
};
export default App;
which uses redux-persist to rehydrate state, and before this is complete, it will show what's sitting in the loading property. I have a Jest test (just the default one that comes with react native out of the box):
it('renders without crashing', () => {
const rendered = renderer.create(<App />).toJSON();
console.log("Rendering: " + JSON.stringify(rendered));
expect(rendered).toBeTruthy();
});
but although the test passes I see that the actions that persist/PERSIST
and persist/REHYDRATE
are still occurring, and the value printed to the console in the test (the rendered output) is:
{
"type": "Text",
"props": {
"accessible": true,
"allowFontScaling": true,
"ellipsizeMode": "tail"
},
"children": ["Loading!"]
}
What I want to do is wait until redux-persist has completed hydration, and then check the rendered value. How can I do this?
Upvotes: 17
Views: 6677
Reputation: 111
The other solutions work for me but here's what I ended up using.
In your <PersistGate />
add a loading component and wait for it to be removed in your tests
await waitForElementToBeRemoved(() => screen.getByText('Loading...'));
So in my code I have a <Text />
component that will be displayed while redux-persist is hydrating
<StoreProvider store={setupStore()}>
<PersistGate loading={<Text>Loading...</Text>} persistor={persistor}>
{children}
</PersistGate>
</StoreProvider>
now in my test suite, it will wait for the component to be removed before continuing
it('should render correctly', async () => {
render(<App />);
await waitForElementToBeRemoved(() => screen.getByText('Loading...'));
const headline = screen.getByText("Welcome to the App!");
expect(headline).toBeTruthy();
});
Upvotes: 0
Reputation: 11
You may ignore persist while testing with
jest.mock('redux-persist/integration/react', () => ({
PersistGate: props => props.children,
}))
jest.mock('redux-persist', () => ({
...jest.requireActual('redux-persist'),
persistReducer: jest.fn().mockImplementation((config, reducer) => reducer),
}));
Upvotes: 1
Reputation: 1918
import React from 'react';
import App, {persistor} from '../App';
import renderer from 'react-test-renderer';
it('renders without crashing', (done) => {
const appRendered = renderer.create(<App />);
persistor.subscribe(function(){
const rendered = appRendered.toJSON();
console.log("Rendering: " + JSON.stringify(rendered));
expect(rendered).toBeTruthy();
done();
});
});
you just need to export
the persistor
from App file and then use the above code to test. it works perfectly, i have tested.
You can notice that persistor
object can subscribe with a callback, which gets executed when the redux store has rehydrated.
Upvotes: 4
Reputation: 18674
You could mock PersistGate
to always return props.children
, then your test can check the rendered value.
Here's how to create the mock:
jest.mock('redux-persist/integration/react', () => ({
PersistGate: props => props.children,
}))
Upvotes: 3