Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing-Library React don't trigger click after an async

I'm trying to write a test in Jest. When the fireEvent.click comes after an async it it doesn't trigger the function.

This is the exact case where few lines of code are better than hundreds of words that describes the issue. In the snippet below, the second and third test are exactly the same (copy-and-pasted) except for the name of the test itself of course.

import {render, screen, waitFor, fireEvent} from '@testing-library/react';
import React from 'react';

const Component = ({asyncClick, syncClick}) => {
    function onClick(){
        console.log('clicked');
        syncClick();
        setTimeout(() => {
            asyncClick();
        }, 50);
    }
    return <div data-testid="toBeClick" onClick={onClick}>

    </div>;
}

describe('a test', function(){
    it('element exists', function(){
        render(<Component/>);
        let el = screen.getByTestId('toBeClick');
        expect(el).toBeInTheDocument();
    });

    it('element Click', async function(){
        let syncClick = jest.fn();
        let asyncClick = jest.fn();
        render(<Component asyncClick={asyncClick} syncClick={syncClick} />);
        let el = screen.getByTestId('toBeClick');
        fireEvent.click(el);
        expect(syncClick).toHaveBeenCalledTimes(1);
        await waitFor(() => {
            expect(asyncClick).toHaveBeenCalledTimes(1);
        });

    });

    it('element Click / 2', async function(){
        let syncClick = jest.fn();
        let asyncClick = jest.fn();
        render(<Component asyncClick={asyncClick} syncClick={syncClick} />);
        let el = screen.getByTestId('toBeClick');
        fireEvent.click(el);
        expect(syncClick).toHaveBeenCalledTimes(1);
        await waitFor(() => {
            expect(asyncClick).toHaveBeenCalledTimes(1);
        });

    });

})

The second test pass. The third test fails. Why?

As a side note, removing async/await and the waitFor from the second test, even the third test starts to pass.

-- UPDATE Looks like the failure is due to an import in jest-setup.js:

require('ionic/js/ionic.js');

I'm importing Ionic v1 and it breaks the tests.

like image 319
alessandro308 Avatar asked Jul 02 '21 09:07

alessandro308


Video Answer


1 Answers

Wrap async actions that trigger something in act.

act(() => {
  fireEvent.click()
});

Can try to use jest.useFakeTimers() and jest.runAllTimers().

In begin of test jest.useFakeTimers() and after click dispatched jest.runAllTimers()

If nothing works can try

await new Promise(resolve => setTimeout(resolve, 0));
like image 195
Aleksandr Smyshliaev Avatar answered Nov 15 '22 04:11

Aleksandr Smyshliaev