简体   繁体   中英

Perform an integration test on a react component where the text input uses debounce (using react testing library)

I'm trying to test a react component that contains a list of results, and a text input that the user can type into in order to filter the results. A 100ms debounce is used to delay the filter as the user types. The debounce is causing the current test to break:

test('typing ', async () => {
        render(<PunkApi />);
        await userEvent.type(textInput, 'nothing should show');
        // * There is a delay here that I need to accommodate for
        // Get table component and check that there are 0 results:
        const table = await screen.findByRole('table');
        const [tableHeader, tableBody] = within(table).getAllByRole('rowgroup');
        expect(tableBody).toBeEmptyDOMElement(); // Error: received 15 results.
});

I can get the test to work by including a setTimeout/promise:

function delay(time: number): Promise<void> {
    return new Promise((resolve) => setTimeout(resolve, time));
}
// insert this line in the above test at the * location:
await act(() => delay(600)); 

So I know the issue is to do with an async issue with my test/code. I understand that the correct way to handle this involves jest.useFakeTimers() instead of the setTimeout/promise solution I've fudged. But when I try to implement I get an error before I even change the test:

beforeAll(() => {
    jest.useFakeTimers();
});

afterEach(() => {
    jest.clearAllTimers();
});

As soon as I include the jest.useFakeTimers(); line, I get this error when I run tests:

thrown: "Exceeded timeout of 5000 ms for a test.

Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

Can anyone help to show me how this is supposed to work?

Credit to Afsanefda for pointing me towards the testing-library.com/docs/dom-testing-library/api-async/#waitfor async documents.

test('typing ', async () => {
        render(<PunkApi />);
        const buzzRow = await screen.findByText(/buzz/i); // ADDED THIS LINE: Initially there is a result with the word 'buzz' in it.
        await userEvent.type(textInput, 'nothing should show');
        // * There is a delay here that I need to accommodate for
        // INSERT FOLLOWING LINE (waitForElementToBeRemoved, as per documentation):
        await waitForElementToBeRemoved(emptyResultsMessage)
        // Get table component and check that there are 0 results:
        const table = await screen.findByRole('table');
        const [tableHeader, tableBody] = within(table).getAllByRole('rowgroup');
        expect(tableBody).toBeEmptyDOMElement(); // THIS NOW PASSES CORRECTLY
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM