Search code examples
e2e-testingplaywright

Playwright: Is there a way to watch to see if element becomes visible


Is there a way to watch for the visibility of an element similar to how waitForRequest works - https://playwright.dev/docs/api/class-page#page-wait-for-request

The problem I'm trying to solve is a flaky test that checks that a loading spinner has been displayed. In some cases the loading spinner is displayed and hidden so quickly that the expect(element).toBeVisible() runs when the element has already hidden itself again.

I can see in the trace that immediately after the click the element is visible but has hidden by the time the expect runs.


Solution

  • Initially I did use unickq's answer but even this has failed on occassion. Here is the most robust solution I have found.

    Mock the route that the spinner is appearing for and only fufill the request when you have asserted if the spinner is visible. https://playwright.dev/docs/mock#modify-api-responses

    test('check spinner appears', () => {
        await page.route('*/**/api/v1/spinner-is-visible-until-i-resolve', async route => {
            expect(spinner).toBeVisible();
            await route.fulfill();
        });
        await makeApiRequestButton.click();
    });
    

    If you want more actions and assertions in your test you can add a promise so the test doesn't run on before the spinner has been checked.

    test('check spinner appears', () => {
        let gateResolve;
        const gatePromise = new Promise((resolve) => {
            gateResolve = resolve;
        });
        await page.route('*/**/api/v1/spinner-is-visible-until-i-resolve', async route => {
            expect(spinner).toBeVisible();
            await route.fulfill();
            gateResolve();
        });
        await makeApiRequestButton.click();
        await gatePromise;
        // do something else now the spinner has gone
    });