Rayrun
โ† Back to Discord Forum

Error: locator.click: Target closed when using saucedemo.com

joedefilippoposted in #help-playwright
Open in Discord

Hi All,

I'm using saucedemo.com and playwright + typescript. All I'm trying to do is log in, then add all the items to the cart.

Here's my code:

const products = await page.getByRole('button').filter({ hasText: 'Add to cart' }).all(); products.forEach(async (addToCart) => { await expect(addToCart).toBeVisible({timeout: 10000}); await addToCart.click(); });

There's 6 products on the products page, each one has an add to cart button, so I found all the buttons and put them in a list, then iterate on that list to click the button.

I'm getting the error mentioned in the title. The trace file is attached. Really stumped on this one, any help is appreciated!

This thread is trying to answer question "Why does the error 'locator.click: Target closed' occur when using a forEach loop with async/await in playwright and typescript on saucedemo.com, and how can it be resolved?"

18 replies
tphillips8117

Basically, don't use a forEach loop. When I paste the code in my editor I get this error (I have eslint configured):

image.png
tphillips8117

use just a regular for ... of ... loop:

const products = await page.getByRole('button').filter({ hasText: 'Add to cart' }).all();
  for (const addToCart of products) {
    await expect(addToCart).toBeVisible({timeout: 10000});
    await addToCart.click();
  }
tphillips8117

In general, you can't use await with a forEach loop, and there's almost never a reason to use forEach over a regular for ... of ... loop

joedefilippo
joedefilippo

Ah makes sense, coming from python and c#, trying to force a forEach when it's not necessary. for... x of y is great to know.

Unfortunately, I'm still having an issue...

There are 6 buttons total, but only the first 3 buttons are being successfully clicked. The rest are not able to be found. I'm wondering if because the button text is changing once clicked, that the original locator I used is no longer valid?

joedefilippo
joedefilippo

Sure enough, this is clicking all the buttons:

for (let i = 0; i < products.length; i++) { await products[0].click(); }

joedefilippo
joedefilippo

I expected the state of the buttons to have been saved in the products variable at the point it was assigned

tphillips8117

You know, I had that issue too. I was wondering what was going on

tphillips8117
image.png
tphillips8117

Very weird...

const productsLocator = page
    .getByRole('button')
    .filter({ hasText: 'Add to cart' });
  await expect(productsLocator).toHaveCount(6);
  for (const addToCart of await productsLocator.all()) {
    await expect(addToCart).toBeVisible();
    await addToCart.click();
  }
tphillips8117

Even that doesn't work

tphillips8117

I think something is happening because the .all() is being messed up when the locators are disappearing

tphillips8117

Yeah that must be it, changing the click() to hover() works fine, because the locators aren't disappearing

tphillips8117

interesting

tphillips8117
await page.goto('https://www.saucedemo.com/');
  await page.locator('[data-test="username"]').fill('standard_user');
  await page.locator('[data-test="password"]').fill('secret_sauce');
  await page.locator('[data-test="login-button"]').click();
  const productsLocator = page
    .getByRole('button')
    .filter({ hasText: 'Add to cart' });
  await expect(productsLocator).toHaveCount(6);
  let products = await productsLocator.all();
  while (products.length > 0) {
    await expect(products[0]).toBeVisible();
    await products[0].click();
    products = await productsLocator.all();
  }
tphillips8117

There you go, using a while loop and always clicking on the first one found, then getting the list again

tphillips8117

since the list being iterated over changes every time around the loop ๐Ÿ™‚

joedefilippo
joedefilippo

Nicely done!

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.