Search code examples
javascriptnode.jspopuppuppeteer

How to click on popup contents in Puppeteer?


I open the 'deliver to' popup but am not able to click on the input field and enter information.

(async () => {
    const browser = await puppeteer.launch({headless: false});
    const page = await browser.newPage();
    const url = 'https://www.tntsupermarket.com/eng/store-flyer';
    await page.goto(url, {waitUntil: 'networkidle0'});

    const newPagePromise = new Promise(x => browser.once('targetcreated', target => x(target.page())));
    await page.evaluate(()=> {
        document.querySelector('span[class="deliverCss-city-FJJ"]').click();
    });
    const popup = await newPagePromise;
    await popup.waitForSelector('input[aria-label="Enter your Postal Code"]');
    await popup.focus('input[aria-label="Enter your Postal Code"]');
    await popup.click('input[aria-label="Enter your Postal Code"]');
    await popup.keyboard.type('a2b');

})();

Solution

  • The pop-up isn't a new page, just a modal element that's shown with JS and without navigation. Removing the navigation promise gives a pretty clear result:

    const puppeteer = require("puppeteer"); // ^13.5.1
    
    let browser;
    (async () => {
      browser = await puppeteer.launch({headless: false});
      const [page] = await browser.pages();
      const url = "https://www.tntsupermarket.com/eng/store-flyer";
      await page.goto(url, {waitUntil: "networkidle0", timeout: 90000});
      const cityEl = await page.waitForSelector('span[class="deliverCss-city-FJJ"]');
      await cityEl.evaluate(el => el.click());
      const postalSel = 'input[aria-label="Enter your Postal Code"]';
      const postalEl = await page.waitForSelector(postalSel);
      await postalEl.type("a2b");
      await page.waitForTimeout(30000); // just to show that the state is as we wish
    })()
      .catch(err => console.error(err))
      .finally(() => browser?.close())
    ;
    

    This is a bit slow; there's an annoying pop-up you might wish to click off instead of using "networkidle0":

    // ... same code
      await page.goto(url, {waitUntil: "domcontentloaded", timeout: 90000});
      const closeEl = await page.waitForSelector("#closeActivityPop");
      await closeEl.click();
      const cityEl = await page.waitForSelector('span[class="deliverCss-city-FJJ"]');
    // same code ...
    

    On quick glance, if the page is cached, the pop-up might not show, so you might want to abort page.waitForSelector("#closeActivityPop"); after 30 seconds or so and continue with the code without clicking on it, depending on how flexible you want the script to be.