Rayrun
← Back to Discord Forum

How to specifically wait for elements within the viewport to become visible and ignore that aren't?

cherry_picker_01posted in #help-playwright
Open in Discord
cherry_picker_01

Hi there!

I need to wait for elements with a specific selector to become visible. However, there are multiple elements on the page with the same selector(product cards), and I only want to wait for the elements that are currently within the viewport to become visible. I don't want to wait for the ones that are located further down the page. (the number of cards that are visible in the viewport will vary)

Any suggestions or code examples would be greatly appreciated.

mart.png

This thread is trying to answer question "How can I wait for elements with a specific selector that are currently within the viewport to become visible, while ignoring those that are located further down the page?"

13 replies
cherry_picker_01

I attempted the solution provided in this GitHub link (https://github.com/microsoft/playwright/issues/8740), but unfortunately, it didn't work for me. If someone has successfully implemented it, I'd greatly appreciate the opportunity to take a look. Thank you!

.aleksandaraleksandrov
.aleksandaraleksandrov

Try const element = page.locator("").nth(n) with that you can specify an exact number. If you want just the second one or the forth one. then await element .waitFor();

cherry_picker_01

This won't work because the number of elements visible within the viewport varies.

is there an attribute that visible items have that hidden don't?

.aleksandaraleksandrov
.aleksandaraleksandrov

You can nth(-1) to get the last one 🙂

Or get them with all() and then do a for loop for the array.

cherry_picker_01

@skorp32 The elements underneath aren't necessarily hidden; they're just out of view. But all the cards share the same common element name, so it waits for all the elements to become visible. However, this isn't necessary in my case. I only want to wait for the cards that are currently visible in the viewport, which could be four, five, or even just one, depending on the card size

cherry_picker_01

And I can't use .nth() because I don't know how many cards will be visible in the viewport; it's dynamic. One page might have only one card, while another page could have as many as 30.

Not sure what to suggest then :/ I have similar case where some content cards are rendeded but outside of viewport but then web framework sets a hidden attribute to them so I can query elements by that

cherry_picker_01

Appreciate it. I'll have a chat with the developers to explore it

cherry_picker_01

@skorp32 Just out of curiosity , how do you go about to ensure all elements with the same name is visible?

before I used locator.all() and looped each locator and used .toBeVisible() but recently changed to just assert element count because I know how many products should be visible at time of assertion

cherry_picker_01

Finally have a working solution in case anyone visits the thread

const elementCount = await page.evaluate((elementName) => {
        const viewport = {
          top: window.scrollY,
          bottom: window.scrollY + window.innerHeight,
          left: 0,
          right: window.innerWidth,
        };

        const elements = Array.from(document.querySelectorAll(`${elementName}`));

        const elementsInsideViewport = elements.filter((element) => {
          const elementRect = element.getBoundingClientRect();
          return (
            elementRect.top < viewport.bottom &&
            elementRect.bottom > viewport.top &&
            elementRect.left < viewport.right &&
            elementRect.right > viewport.left
          );
        });

        return elementsInsideViewport.length;
      }, elementName);

      console.log(`Number of elements with the name "${elementName}" in the viewport: ${elementCount}`);

Another way i've found is using a count(). While it sounds what you are doing has additional rules like "Is locator/element visible", so you will be force to iterate the elements matched and from here can create your specific rules... Nice thing got my stuff like this, i was able to talk my developers into adding specific attribute for different "groups" where i may need to "Do the hocky pocky..." Nice thing if you locator count returns 0 that can be useful, quick and handy at times too...

Related Discord Threads

TwitterGitHubLinkedIn
AboutQuestionsDiscord ForumBrowser ExtensionTagsQA Jobs

Rayrun is a community for QA engineers. I am constantly looking for new ways to add value to people learning Playwright and other browser automation frameworks. If you have feedback, email luc@ray.run.