How to click a list item with Puppeteer?

I’m new to puppeteer and I’m trying to click on a selector from a dropdown menu the MR element here

I’ve tried using await page.click('.mat-option ng-star-inserted mat-active');

and also

await page.select('#mat-option-0');

here is my code, would anyone be able to help me fix this issue and understand how to resolve it in the future? I’m not to sure what methods to be using with each elelement, I think it’s every time I introduce a class with spaces in the name could that be the issue?

and does anyone have any best practices for when codings things like this?

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();
  await page.goto('https://www.game.co.uk/en/-2640058?cm_sp=NintendoFormatHub-_-Accessories-_-espot-_-PikaCase');
  await console.log('Users navigated to site :)');
  await page.waitFor(2300);
  await page.click('.cookiePolicy_inner--actions');
  await page.waitFor(1000);
  await page.click('.addToBasket');
  await page.waitFor(1300);
  await page.click('.secure-checkout');
  await page.waitFor(2350);
  await page.click('.cta-large');
  await page.waitFor(1200);
  await page.goto('https://checkout.game.co.uk/contact');
  await page.waitFor(500);
  await page.click('.mat-form-field-infix');
  await page.waitForSelector('.ng-tns-c17-1 ng-trigger ng-trigger-transformPanel mat-select-panel mat-primary');
  await page.click('.mat-option ng-star-inserted mat-active');
  

  
})();

Answer

There are a couple of issues with the script, let’s see them:

  • you are using waitFor() with a number of miliseconds, this is brittle because you never know if perhaps some action will take longer, and if it does not, you will waste time; you can substitute these waits with waitForSelector(); in fact, if you use VSCode (and perhaps other IDEs), it will notify you that this method is deprecated, don’t ignore these warnings:

enter image description here

  • when I use DevTools, no element is returned for .mat-option ng-star-inserted mat-active selector, but I can find the desired element with #mat-option-0 selector, or I can use the longer version, but have to use a dot (.) before each class and delete spaces between them like so .mat-option.ng-star-inserted.mat-active, you can see a CSS reference here, the point is that with spaces, it looks for descendants, which is not what you want

These two changes should give you what you need, this is a result when running on my side, you can see that Mr. has been selected:

enter image description here

I got there with this script:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();
  await page.goto('https://www.game.co.uk/en/-2640058?cm_sp=NintendoFormatHub-_-Accessories-_-espot-_-PikaCase');
  await console.log('Users navigated to site :)');
  await page.waitForSelector('.cookiePolicy_inner--actions');
  await page.click('.cookiePolicy_inner--actions');
  await page.waitForSelector('.addToBasket');
  await page.click('.addToBasket');
  await page.waitForSelector('.secure-checkout');
  await page.click('.secure-checkout');
  await page.waitForSelector('.cta-large');
  await page.click('.cta-large');
  await page.goto('https://checkout.game.co.uk/contact');
  await page.waitForSelector('.mat-form-field-infix');
  await page.click('.mat-form-field-infix');
  await page.waitForSelector('#mat-option-0');
  await page.click('#mat-option-0');
})();

However, this is still not ideal because:

  • you handle the cookie bar with clicks, try to find a way without clicking; perhaps injecting a cookie that disables the cookie bar (if possible)
  • the code is one big piece that is perhaps ok for now and this example but might become unmaintainable if you keep adding lines to it; try to reuse code in functions and methods