I'm trying to test a hook that uses a context underneath
The hook looks like this
const useConfirmation = () => {
const { openDialog } = useContext(ConfirmationContext);
const getConfirmation = ({ ...options }: DialogParams) => new Promise((res) => {
openDialog({ actionCallback: res, ...options });
});
return { getConfirmation };
};
getConfirmation
returns a promise that is resolved if the dialog is confirmed or not.
export const ConfirmationProvider = ({ children }: PropsWithChildren<{}>) => {
const [dialogOpen, setDialogOpen] = useState(false);
const [dialogConfig, setDialogConfig] = useState<DialogConfig>(initialState);
const openDialog = (config: DialogConfig) => {
setDialogOpen(true);
setDialogConfig(config);
};
const resetDialog = () => {
setDialogOpen(false);
setDialogConfig(initialState);
};
const onConfirm = () => {
resetDialog();
dialogConfig.actionCallback(true);
};
const onDismiss = () => {
resetDialog();
dialogConfig.actionCallback(false);
};
const value = useMemo(() => ({ openDialog }), []);
...
};
When is going to be used it simply gets called like:
// Confirmed is a boolean
const connfirmed = await getConfirmation({...});
// confirmed ? 'Confirmed' : 'Canceled'
I'm able to test that the dialog closes or open but never the value of the state inside the context, how can I test this?
Currently my test looks like this:
it('should open a confirmation dialog', async () => {
const user = userEvent.setup();
const { result } = renderHook(() => useConfirmation(), {
wrapper: ({ children }) => (
<AllTheProviders>
<ConfirmationProvider>{children}</ConfirmationProvider>
</AllTheProviders>
),
});
const confirmed = act(() => {
result.current.getConfirmation({
title: 'Confirmation Message',
text: 'Confirmation Text',
confirmText: 'Confirm',
confirmColor: 'var(--quo-pink)',
});
});
const modal = getByRole(document.body, 'dialog');
expect(modal).toBeInTheDocument();
await user.click(getByRole(document.body, 'button', { name: 'Cancel' }));
expect(modal).not.toBeInTheDocument();
});
I want to be able to say that confirmed is expected toBeTruthy
or toBeFalsy
but as it is right now its always {"then": [Function then]}
.
Thank you in advance
Response was very straight forward. I simply needed to assign the return value to a variable outside.
...
let confirmed;
act(() => {
confirmed = result.current.getConfirmation({
title: 'Confirmation Message',
text: 'Confirmation Text',
confirmText: 'Confirm',
confirmColor: 'var(--quo-pink)',
});
});
expect(modal).toBeInTheDocument();
await user.click(getByRole(document.body, 'button', { name: 'Cancel' }));
await expect(confirmed).resolves.toBe(true);
...