Skip to content

[Bug]: Generic timeout message (only on GitHub Actions) with lazy loaded images and .all() usage #31737

Open

Description

Scrolling to and waiting for lazy-loaded images with the following code is flaky (only fails on GitHub Actions, not locally) and leads to generic timeout messages if the elements are hidden by eg. JS that hides the images during loading:

const lazyImages = await page.locator('img[loading="lazy"]:visible').all();

for (const lazyImage of lazyImages) {
  await lazyImage.scrollIntoViewIfNeeded();
  await expect(lazyImage).not.toHaveJSProperty('naturalWidth', 0);
}

Version

1.45.2

Steps to reproduce

Reproduction repo: https://github.com/karlhorky/repro-playwright-next-js-lazy-images-all-timeout

  1. Review test code and React Client Component code
  2. View GitHub Actions test results below (original workflow run)
pnpm exec playwright test
  pnpm exec playwright test
  shell: /usr/bin/bash -e {0}
  
[WebServer]   ▲ Next.js 14.2.5
[WebServer]   - Local:        http://localhost:3000
 ✓ Starting...
[WebServer]  ✓ Ready in 290ms
Running 1 test using 1 worker
T
  1) [chromium] › lazyVisibleImages.spec.ts:3:5 › scroll to lazy visible images and wait for loading 
    Test timeout of 30000ms exceeded.
    Error: locator.scrollIntoViewIfNeeded: Test timeout of 30000ms exceeded.
    Call log:
      - waiting for locator('img[loading="lazy"]:visible').nth(36)
       6 |
       7 |   for (const lazyImage of lazyImages) {
    >  8 |     await lazyImage.scrollIntoViewIfNeeded();
         |                     ^
       9 |     await expect(lazyImage).not.toHaveJSProperty('naturalWidth', 0);
      10 |   }
      11 | });
        at /home/runner/work/repro-playwright-next-js-lazy-images-all-timeout/repro-playwright-next-js-lazy-images-all-timeout/tests/lazyVisibleImages.spec.ts:8:21
  Slow test file: [chromium] › lazyVisibleImages.spec.ts (30.0s)
  Consider splitting slow test files to speed up parallel execution
  1 failed
    [chromium] › lazyVisibleImages.spec.ts:3:5 › scroll to lazy visible images and wait for loading 
Error:   1) [chromium] › lazyVisibleImages.spec.ts:3:5 › scroll to lazy visible images and wait for loading 
    Test timeout of 30000ms exceeded.
Error:   1) [chromium] › lazyVisibleImages.spec.ts:3:5 › scroll to lazy visible images and wait for loading 
    Error: locator.scrollIntoViewIfNeeded: Test timeout of 30000ms exceeded.
    Call log:
      - waiting for locator('img[loading="lazy"]:visible').nth(36)


       6 |
       7 |   for (const lazyImage of lazyImages) {
    >  8 |     await lazyImage.scrollIntoViewIfNeeded();
         |                     ^
       9 |     await expect(lazyImage).not.toHaveJSProperty('naturalWidth', 0);
      10 |   }
      11 | });

        at /home/runner/work/repro-playwright-next-js-lazy-images-all-timeout/repro-playwright-next-js-lazy-images-all-timeout/tests/lazyVisibleImages.spec.ts:8:21
Warning: [chromium] › lazyVisibleImages.spec.ts took 30.0s
Notice:   1 failed
    [chromium] › lazyVisibleImages.spec.ts:3:5 › scroll to lazy visible images and wait for loading 
Error: Process completed with exit code 1.

Expected behavior

I was expecting that the error message would more clearly guide me towards what the issue is (that locator('img[loading="lazy"]:visible').nth(36) is no longer available, because it is now invisible, thanks to the useEffect())

I'm aware that usage docs of all() has a note, which is relevant here:

locator.all() does not wait for elements to match the locator, and instead immediately returns whatever is present in the page. When the list of elements changes dynamically, locator.all() will produce unpredictable and flaky results. When the list of elements is stable, but loaded dynamically, wait for the full list to finish loading before calling locator.all().

Concretely, this error message could be improved to say:

  1. 30s is the default test timeout (with docs link)
  2. make "waiting" in the message more expressive - maybe something about "endless"?
  3. list out some common errors that can cause endless waiting for elements (with docs links)

Actual behavior

The error message seemed to communicate:

  1. generic 30s timeout occurred
    1. user questions / thought process: why 30s? did I set this value? I don't remember setting it
  2. something about "waiting for" a locator
    1. user questions / thought process: what does waiting mean? what are common errors that could cause endless waiting for an element? what is the relevance of 36?

Additional context

No response

Environment

System:
    OS: Linux 6.5 Ubuntu 22.04.4 LTS 22.04.4 LTS (Jammy Jellyfish)
    CPU: (4) x64 AMD EPYC 7763 64-Core Processor
    Memory: 14.46 GB / 15.61 GB
    Container: Yes
  Binaries:
    Node: 20.15.1 - /opt/hostedtoolcache/node/20.15.1/x64/bin/node
    npm: 10.7.0 - /opt/hostedtoolcache/node/20.15.1/x64/bin/npm
    pnpm: 9.5.0 - /usr/local/bin/pnpm
  Languages:
    Bash: 5.1.16 - /usr/bin/bash
  npmPackages:
    @playwright/test: ^1.45.2 => 1.45.2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions