Looking for a way to test Alert.alert 'onPress' is that even possible?
sure, use jest.spyOn(Alert, 'alert')
But then the code coverage for onPress is going to be zero....
If you call fireEvent.press, the onPress handler should be called. And jest.spyOn doesn't change implementation by default, so all the code inside will be called
I couldn't get fireEvent.press to work for me. I ended up with this helper function for testing alerts (WARNING!! Not thoroughly tested yet):
/* global jest */
import {Alert, AlertButton} from 'react-native';
interface MockAlertActions {
pressAlertButton(text: string): Promise<void>;
}
type MockedCall = Readonly<[string, string, ReadonlyArray<AlertButton>]>;
export default function spyOnAlert(): MockAlertActions {
jest.spyOn(Alert, 'alert');
let dismissedCalls: ReadonlyArray<MockedCall> = [];
return {
async pressAlertButton(text: string): Promise<void> {
const unhandledCalls = Alert.alert.mock.calls.slice();
dismissedCalls.forEach(call => {
// Only want to remove the first instance in case there are multiple identical calls
const index = unhandledCalls.indexOf(call);
dismissedCalls = dismissedCalls.filter((_, i) => i !== index);
});
if (unhandledCalls.length === 0) {
throw new Error('No pending calls to alert');
}
const mostRecentCall = unhandledCalls[unhandledCalls.length - 1];
// TODO: Handle default button case, when no buttons provided
const targetButton = mostRecentCall[2].find(
(button: AlertButton) => button.text === text
);
if (!targetButton) {
throw new Error(`No button with text ${text}`);
}
if (targetButton.onPress) {
await targetButton.onPress();
}
dismissedCalls = [...dismissedCalls, mostRecentCall];
}
};
}
Which you would use like so:
const { pressAlertButton } = spyOnAlert();
const rendered = render(<MyComponent />);
await act(async () => {
await fireEvent.press(rendered.getByLabelText('DELETE'));
await pressAlertButton('Yes, delete this item');
});
@danielholmes nice workaround!
If you call
fireEvent.press, theonPresshandler should be called. Andjest.spyOndoesn't change implementation by default, so all the code inside will be called
@thymikee does this library provide a better way of simulating interaction with react-native alerts than what Daniel posted? I'm doing something like Alert.alert.mocks.call[0][2][1].onPress() which does not feel very friendly either
@sbalay Alert is a native module. fireEvent only supports native views/components that exist in a view hierarchy.
Most helpful comment
sure, use
jest.spyOn(Alert, 'alert')