React-Native Use Jest to test the AppState
How can I trigger the AppState listener to check if it works correctly?
AppState.addEventListener('change', (nextAppState) => { console.log('test')});
Is there a way in Jest to trigger this listener?
Yes, you can mock react-native native modules if you know where they are located. An example below, where I test if an app state service dispatches a given action when the app state changes:
it('if a store is set dispatches an APP_STATE_CHANGE action with the new state on change', () => {
let capturedChangeCallback = null
const mockAddListener = jest.fn((event, callback) => {
if (event === 'change') {
capturedChangeCallback = callback
}
})
jest.resetModules()
jest.doMock('react-native/Libraries/AppState/AppState', () => ({
addEventListener: mockAddListener,
}))
const mockStore = { dispatch: jest.fn() }
const svc = require('@services/appState').default
svc.setStore(mockStore)
// change called
capturedChangeCallback('active')
expect(mockStore.dispatch).toHaveBeenCalledTimes(1)
expect(mockStore.dispatch).toHaveBeenCalledWith({
type: 'APP_STATE_CHANGE',
payload: 'active',
})
})
The key here is the jest.doMock
call passing the full AppState
module location, and calling resetModules
to make sure to isolate the test case.
I don't really understand how the first solutions works and I tried it but could not get it to work but there is a different way.
First to clarify, you are trying to invoke the function that is the second parameter of AppState.addEventListener('change', functionToInvokeOnChange) called on in the code. Luckily Jest gives a jest.spyOn method to any parameters that we call on AppState.addEventListener(...). If the second parameter is a function, there is no reason you can't call it in the jest environment.
Say you have,
useEffect(() => {
AppState.addEventListener('change', _handlerFunction);
/* ... */
}, []);
const _handlerFunction = async (nextAppState) => { /* ...*/ }
You can test this like this:
it('... on state change', async () => {
const appStateSpy = jest.spyOn(AppState, 'addEventListener');
rendered = render(<Component />);
await appStateSpy.mock.calls[0][1]('active');
//assert this or that happens ect.
});