-1

I need to choose опе book without a sale. On the page, I have 9 products, and some of them have the class hasDiscount.

I need to choose the first product without the class hasDiscount. But: I need to click on the button Buy, because if I click on all products, I can't add them to the basket.

My code:

for(const row of await page.locator('.note-item.card.h-100').all())
{
  if (row.not.toHaveClass('hasDiscount'))
  {
    await page.locator('.actionBuyProduct').first().click()
  }
}

In the first row of my code, I choose all 9 products, and if one of them doesn't have the class hasDiscount, then I click on the button "Buy".

But my code doesn't work. What is wrong with it?

Product with class "hasDiscount" button

How can I fix it?

3
  • 6
    Please explain what you mean by "doesn't work". You've explained what the code should do, please also explain what it is actually doing. Commented Oct 3 at 10:35
  • the product is not added to the cart. i need to add product without Discount into cart Commented Oct 3 at 12:23
  • 1
    Please share the site, runnable code as a minimal reproducible example and an explanation of what you're trying to accomplish at a high level. If these elements are added dynamically, .all() will not auto wait, and will return an empty array, so the loop won't run. If there ARE elements, then you should see a crash, because .not.toHaveClass looks made up. Thanks. Commented Oct 3 at 14:58

1 Answer 1

2

You are checking whether a row (more like a product card) does not have the class hasDiscount by calling row.not.toHaveClass('hasDiscount'). This won't work, as row is an instance of Locator, which doesn't have a not property.

You could try using row.getAttribute('class') instead:

for (const row of await page.locator('.note-item.card.h-100').all()) {
  const classes = (await row.getAttribute('class'))?.split(' ') ?? [];
  if (!classes.includes('hasDiscount'))) {
    await page.locator('.actionBuyProduct').first().click()
  }
}

Note that above code is still bugged:

  • It doesn't click on the buy button of the current row/card. Instead, it clicks on the first buy button on the page.
  • It performs multiple clicks, depending on how many products do not have a discount.

I'm thinking what you actually want to do is the following:

const firstProductWithoutDiscount = page.locator('.note-item:not(.hasDiscount)');
await firstProductWithoutDiscount.locator('.actionBuyProduct').click();
Sign up to request clarification or add additional context in comments.

5 Comments

Browsers have a .classList property and an API for handling the list of class names, there's no need to do your own string manipulation of the class attribute.
ok, and how i need to add item without discount into cart?
Playwright scripts do not run in a browser; they are executed by Node.js (or Python/Java/.NET) and remote-control a browser. You can only use the DOM API by doing page.evaluate. I would agree though that doing string manipulation of the class attribute is not necessary in this scenario.
oic, good to know!
test('Тест-кейс 2. Переход в корзину с 1 неакционным товаром.', async({ page }) => { await page.type('css = [placeholder="Логин клиента"]', 'test') await page.type('css = [placeholder="Пароль клиента"]', 'test') await page.locator('xpath = //button[text()="Вход"]').click() for(const row of await page.locator('.note-item.card.h-100').all()) { if (row.not.toHaveClass('hasDiscount')) { await page.locator('.actionBuyProduct').first().click() } } }) this whole test and first part is working, just for loop doesn't

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.