question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Feature] waitForSelector hidden with debounce

See original GitHub issue

Hello, is it possible to perform a waitForSelector until something is hidden even if it rapidly appears and disappears multiple times? This would be similar to a debounce feature or very much like the waitForLoadState with networkidle selected. I would want to set the debounce to something like 500 milliseconds but have it configurable.

I have looked in the issues and couldn’t find anything like this but this would help with loading divs and animations that popup multiple times to ensure that we don’t execute the next statement until the threshold has been met.

Thoughts?

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:2
  • Comments:9 (2 by maintainers)

github_iconTop GitHub Comments

4reactions
mattduffieldcommented, Nov 12, 2020

Hi @yury-s thanks for the sample! I tried it out and it worked exactly as I expected. I made a slight modification so that I could pass in the timeout:

const waitForHiddenDebounce = async (selector, timeout = 500) => {
  await page.$eval(selector, (element, timeout) => {
    const isVisible = () => {
      const style = element.ownerDocument.defaultView.getComputedStyle(element);
      if (!style || style.visibility === 'hidden')
        return false;
      const rect = element.getBoundingClientRect();
      return rect.width > 0 && rect.height > 0;
    };

    let fulfill;
    const result = new Promise(f => fulfill = f);

    let lastState = isVisible();
    let startTime = Date.now();

    const pollState = () => {
      const visible = isVisible();
      if (lastState === visible) {
        if (Date.now() - startTime > timeout) {
          fulfill();
          return;
        }
      } else {
        lastState = visible;
        startTime = Date.now();
      }
      requestAnimationFrame(pollState);
    };
    requestAnimationFrame(pollState);
    return result;
  }, timeout);
};

Thanks again for your help! Having debounce with multiple busy indicators displaying rapidly makes it so much nicer to test.

2reactions
DJ-Glockcommented, Nov 12, 2020

@mattduffield Apologies for posting bad example. I can see that Yury already provided you working code, but let me also finish my try 😃

Tested it with static elements (not appearing many times), but should work for you.

  /** Returns true if element disappeared after provided timeout. */
  async function waitForSelectorToCompletelyDisappear(selector, timeout = 500, pollingTimeout = 100) {
    const startTime = Date.now();
    let duration = 0;
    let isDisappeared = false;

    async function endTime() {
      let now = await page.waitForSelector(selector, { timeout, state: 'hidden' })
        .then(async () => {
          console.log(`disappeared`);
          isDisappeared = true;
          return Date.now();
        })
        .catch(async () => {
          console.log(`visible`);
          isDisappeared = false;
          return Date.now();
        })
      return now;
    }
    
    duration = (await endTime()) - startTime;  
    while (duration < timeout) {
      duration = (await endTime()) - startTime;
      await page.waitForTimeout(pollingTimeout);
    }
    console.log(`Disappeared finally: ${isDisappeared}`);
    return isDisappeared;
  }
Read more comments on GitHub >

github_iconTop Results From Across the Web

How to make puppeteer wait for page to load - Urlbox
waitForSelector () to wait for an element to be present, visible, ... observers callback function, we can use a debounced function that will ......
Read more >
puppeteer: how to wait until an element is visible?
I think you can use page.waitForSelector(selector[, options]) function for that purpose. const puppeteer = require('puppeteer'); ...
Read more >
Debounce JavaScript – How to Make your JS Wait Up
The debounce method here takes in two arguments, callback & wait . callback is the function you want to execute, while wait is...
Read more >
What's new in Gutenberg 13.1? (27 April) - Make WordPress
Categories: Added new option to show or hide empty categories. ... Add a debounce to the custom color onChange event.
Read more >
mozilla-central: changeset 603618 ...
waitForSelector should wait for visible recursively (waittask.spec.ts)": [ @@ -2080 ... version of Chrome using the latest JavaScript and browser features.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found