Formik useFormikContext testing with testing-library

1.3k Views Asked by At

I am trying to write some unit tests for my input components, most of them are connected to Formik and there are cases like my Autocomplete component where the form gets validated when the user presses special keys i.e ( "Enter", ",", " ", etc ), and a Tag is generated. I want my unit test to check this functionality.

I am using a helper function to render the component inside a Formik wrapper with some initial values using testing-library. I want to somehow get access to Formik values and the only way I have found to do so is with the helper function getFormProps in which I mock useFormikContext using renderHook from @testing-library/react-hooks,

export const getFormProps = () => {
    return renderHook(() => useFormikContext<typeof formInitialValues>());
};

I am not sure if there is a better way to do this or if I am missing something in the documentation, so far I haven't managed to get it to work. It always gives me the following error

Warning: Formik context is undefined, please verify you are calling useFormikContext() as child of a <Formik> component.

I've also tried the suggested solution from here but whenever I checked for updates on my form I was always getting the original initial data.

If anyone has experienced similar issues please share how you resolved them. Thank you in advance

it.only('add a tag', async () => {
    const tree = mountWithForm(<EmailsInput name="emails" label="Label" />);

    const { result } = getFormProps();
    const input = getEditable(tree);
    if (!input) return expect(input).toBe(null);

    expect(result.current.values.emails.length).toBe(0);

    await act(() => {
        fireEvent.change(input, { target: { textContent: newEmail } });
        fireEvent.keyPress(input, { key: 'Enter', code: 'Enter', charCode: 13 });
    });

    await waitFor(() => {
        expect(document.getSelection).toHaveBeenCalledTimes(1);
        expect(document.createRange).toHaveBeenCalledTimes(1);
        expect(input.textContent).toBeEmpty();
        // -----> expect(result.current.values.emails.length).toBe(1)
    });
});

I am using the following packages :

    "formik": "^2.2.9",
    "react": "^18.0.0",
    "react-dom": "^18.0.0",
    "jest": "^27.5.1",
    "jest-extended": "^2.0.0",
    "react-test-renderer": "^18.0.0",
    "@testing-library/react": "^13.0.1",
    "@testing-library/react-hooks": "^8.0.0",
    "@testing-library/jest-dom": "^5.16.4",
0

There are 0 best solutions below