Operacje na listach lokatorów

Prezentacja

Różne sposoby wyszukiwania elementów i metody w lokatorach

Różne sposoby wyszukiwania elementów i metody w lokatorach

Różne sposoby wyszukiwania elementów i metody w lokatorach

Różne sposoby wyszukiwania elementów i metody w lokatorach

Różne sposoby wyszukiwania elementów i metody w lokatorach

Różne sposoby wyszukiwania elementów i metody w lokatorach

Różne sposoby wyszukiwania elementów i metody w lokatorach

Różne sposoby wyszukiwania elementów i metody w lokatorach

Różne sposoby wyszukiwania elementów i metody w lokatorach

TIP: Cały kod testów z poszczególnych lekcji znajdziesz w specjalnie przygotowanym repozytorium:
👉jaktestowac/playwright-elements-locators

TIP: Ta lekcja jest częścią rozwijanego Programu Testy Automatyczne z Playwright 🎭

Sprawdzenie liczby znalezionych elementów

Lokatory są potężnym narzędziem do znajdowania elementów na stronie.

Lokatory mogą znajdować jeden lub więcej elementów.

Aby sprawdzić liczbę znalezionych elementów możemy skorzystać z metody count():

await elementLocator.count();
await elementLocator.count();
await elementLocator.count();

Przykładowy kod testu, w którym sprawdzamy, czy na stronie jest 7 elementów typu button:

test("All buttons on page", async ({ page }) => {
// Arrange:
const elementRole = "button";
// we can define the locator for the element
const buttonLocator = page.getByRole(elementRole);
// print the count of buttons on the page
console.log("buttonLocator", await buttonLocator.count());
// Assert:
// check if number of buttons is 7
await expect(buttonLocator).toHaveCount(7);
});
test("All buttons on page", async ({ page }) => { // Arrange: const elementRole = "button"; // we can define the locator for the element const buttonLocator = page.getByRole(elementRole); // print the count of buttons on the page console.log("buttonLocator", await buttonLocator.count()); // Assert: // check if number of buttons is 7 await expect(buttonLocator).toHaveCount(7); });
  test("All buttons on page", async ({ page }) => {
    // Arrange:
    const elementRole = "button";


    // we can define the locator for the element
    const buttonLocator = page.getByRole(elementRole);


    // print the count of buttons on the page
    console.log("buttonLocator", await buttonLocator.count());


    // Assert:
    // check if number of buttons is 7
    await expect(buttonLocator).toHaveCount(7);
  });

Częsty błąd w testach

W przypadku jeśli lokator wskazuje na więcej elementów, a my chcemy wykonać akcję na jednym z nich, to musimy precyzyjnie określić na którym elemencie chcemy wykonać daną akcję.

Jeśli tego nie zrobimy, to metoda do interakcji z elementami na stronie (np. click()) zwróci nam taki błąd:

Error: locator.click: Error: strict mode violation: getByRole('button') resolved to 7 elements:
1) <button id="btnPractice" class="button-primary" data-testid="open-practice">Main Practice Page</button> aka getByTestId('open-practice')
2) <button class="my-button" onclick="buttonOnClick()">Click me!</button> aka getByRole('button', { name: 'Click me!' })
...
Error: locator.click: Error: strict mode violation: getByRole('button') resolved to 7 elements: 1) <button id="btnPractice" class="button-primary" data-testid="open-practice">Main Practice Page</button> aka getByTestId('open-practice') 2) <button class="my-button" onclick="buttonOnClick()">Click me!</button> aka getByRole('button', { name: 'Click me!' }) ...
Error: locator.click: Error: strict mode violation: getByRole('button') resolved to 7 elements:
    	1)  aka getByTestId('open-practice')
    	2)  aka getByRole('button', { name: 'Click me!' })
...

Zwróć uwagę, że w powyższym błędzie Playwright dokładnie określa ile elementów zostało znalezionych.

Również zauważ, że wypisana jest podpowiedź, jaki lokator/selektor zastosować, aby znaleźć dany pojedynczy element. Zwróć uwagę na ten fragment:

...aka getByTestId('open-practice')
...aka getByRole('button', { name: 'Click me!' })
...aka getByTestId('open-practice') ...aka getByRole('button', { name: 'Click me!' })
...aka getByTestId('open-practice')
...aka getByRole('button', { name: 'Click me!' })

Kod do lekcji

Początkowy kod

Początkowa zawartość pliku locator-lists.spec.ts:

import { test, expect } from "@playwright/test";
test.describe("Locator lists", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/practice/simple-multiple-elements-no-ids.html");
});
test("All buttons on page", async ({ page }) => {
// TODO:
});
test("action on nth button", async ({ page }) => {
// TODO:
});
test("action on multiple buttons", async ({ page }) => {
// TODO:
});
});
import { test, expect } from "@playwright/test"; test.describe("Locator lists", () => { test.beforeEach(async ({ page }) => { await page.goto("/practice/simple-multiple-elements-no-ids.html"); }); test("All buttons on page", async ({ page }) => { // TODO: }); test("action on nth button", async ({ page }) => { // TODO: }); test("action on multiple buttons", async ({ page }) => { // TODO: }); });

import { test, expect } from "@playwright/test";


test.describe("Locator lists", () => {
  test.beforeEach(async ({ page }) => {
    await page.goto("/practice/simple-multiple-elements-no-ids.html");
  });


  test("All buttons on page", async ({ page }) => {
    // TODO:
  });


  test("action on nth button", async ({ page }) => {
    // TODO:
  });


  test("action on multiple buttons", async ({ page }) => {
    // TODO:
  });
});






Finalny kod

Finalna zawartość pliku locator-lists.spec.ts:

import { test, expect } from "@playwright/test";
test.describe("Locator lists", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/practice/simple-multiple-elements-no-ids.html");
});
test("All buttons on page", async ({ page }) => {
// Arrange:
const elementRole = "button";
const expectedElementsCount = 7;
// we can define the locator for the element
const buttonLocator = page.getByRole(elementRole);
// print the count of buttons on the page
console.log("number of button elements:", await buttonLocator.count());
// Assert:
// check if number of buttons is 7
await expect(buttonLocator).toHaveCount(expectedElementsCount);
});
// unskip to see the error during test run
test.skip("❌ SHOULD FAIL ❌ - try clicking button (when multiple buttons are on page)", async ({
page,
}) => {
// Arrange:
const elementRole = "button";
// we can define the locator for the element
const buttonLocator = page.getByRole(elementRole);
// print the count of buttons on the page
console.log("number of button elements:", await buttonLocator.count());
// Assert:
// check if number of buttons is 7
await expect(buttonLocator).toHaveCount(7);
// ❌ because there are multiple buttons on the page
// ❌ following line will return an error:
await buttonLocator.click();
// ❌ with following error on console:
// Error: locator.click: Error: strict mode violation: getByRole('button') resolved to 7 elements:
// 1) <button id="btnPractice" class="button-primary" data-testid="open-practice">Main Practice Page</button> aka getByTestId('open-practice')
// 2) <button class="my-button" onclick="buttonOnClick()">Click me!</button> aka getByRole('button', { name: 'Click me!' })
// 3) <button class="my-button" onclick="buttonOnClick('(Second one!)')">Click me too!</button> aka getByRole('button', { name: 'Click me too!' })
// 4) <button class="my-button" onclick="buttonOnClick('(Third one!)')">Click here!</button> aka getByRole('button', { name: 'Click here!' })
// 5) <button class="my-button" onclick="buttonOnClick('(row 1)')">Click!</button> aka getByRole('row', { name: 'Row 1 X Click!' }).getByRole('button')
// 6) <button class="my-button" onclick="buttonOnClick('(row 2)')">Click!</button> aka getByRole('row', { name: 'Row 2 Y Click!' }).getByRole('button')
// 7) <button class="my-button" onclick="buttonOnClick('(row 3)')">Click!</button> aka getByRole('row', { name: 'Row 3 Z Click!' }).getByRole('button')
});
test("action on nth button", async ({ page }) => {
// Arrange:
const elementRole = "button";
const resultsTestId = "dti-results";
const expectedMessage = "You clicked the button! (Second one!)";
const buttonLocator = page.getByRole(elementRole);
const resultsLocator = page.getByTestId(resultsTestId);
// print the count of buttons on the page
console.log("number of button elements:", await buttonLocator.count());
// Act:
// click on the 3rd button (we count from 0)
await buttonLocator.nth(2).click();
// display the text content of the results element
// console.log("results text content:", await resultsLocator.textContent());
// Assert:
await expect(resultsLocator).toHaveText(expectedMessage);
});
test("action on multiple buttons", async ({ page }) => {
// Arrange:
const elementRole = "button";
const elementText = "Click!";
const resultsTestId = "dti-results";
const buttonLocator = page.getByRole(elementRole, { name: elementText });
const resultsLocator = page.getByTestId(resultsTestId);
// print the count of buttons on the page
console.log("number of button elements:", await buttonLocator.count());
// Act:
// await buttonLocator.nth(0).click();
// console.log(await resultsLocator.textContent());
// await buttonLocator.nth(1).click();
// console.log(await resultsLocator.textContent());
// await buttonLocator.nth(2).click();
// console.log(await resultsLocator.textContent());
// usage of count() method
const numberOfFoundButtons = await buttonLocator.count();
for (let i = 0; i < numberOfFoundButtons; i++) {
await buttonLocator.nth(i).click();
// display the text content of the results element
console.log("results text content:", await resultsLocator.textContent());
}
// usage of all() method
for (const button of await buttonLocator.all()) {
await button.click();
console.log("results text content:", await resultsLocator.textContent());
}
// TODO: add assertions
});
});
import { test, expect } from "@playwright/test"; test.describe("Locator lists", () => { test.beforeEach(async ({ page }) => { await page.goto("/practice/simple-multiple-elements-no-ids.html"); }); test("All buttons on page", async ({ page }) => { // Arrange: const elementRole = "button"; const expectedElementsCount = 7; // we can define the locator for the element const buttonLocator = page.getByRole(elementRole); // print the count of buttons on the page console.log("number of button elements:", await buttonLocator.count()); // Assert: // check if number of buttons is 7 await expect(buttonLocator).toHaveCount(expectedElementsCount); }); // unskip to see the error during test run test.skip("❌ SHOULD FAIL ❌ - try clicking button (when multiple buttons are on page)", async ({ page, }) => { // Arrange: const elementRole = "button"; // we can define the locator for the element const buttonLocator = page.getByRole(elementRole); // print the count of buttons on the page console.log("number of button elements:", await buttonLocator.count()); // Assert: // check if number of buttons is 7 await expect(buttonLocator).toHaveCount(7); // ❌ because there are multiple buttons on the page // ❌ following line will return an error: await buttonLocator.click(); // ❌ with following error on console: // Error: locator.click: Error: strict mode violation: getByRole('button') resolved to 7 elements: // 1) <button id="btnPractice" class="button-primary" data-testid="open-practice">Main Practice Page</button> aka getByTestId('open-practice') // 2) <button class="my-button" onclick="buttonOnClick()">Click me!</button> aka getByRole('button', { name: 'Click me!' }) // 3) <button class="my-button" onclick="buttonOnClick('(Second one!)')">Click me too!</button> aka getByRole('button', { name: 'Click me too!' }) // 4) <button class="my-button" onclick="buttonOnClick('(Third one!)')">Click here!</button> aka getByRole('button', { name: 'Click here!' }) // 5) <button class="my-button" onclick="buttonOnClick('(row 1)')">Click!</button> aka getByRole('row', { name: 'Row 1 X Click!' }).getByRole('button') // 6) <button class="my-button" onclick="buttonOnClick('(row 2)')">Click!</button> aka getByRole('row', { name: 'Row 2 Y Click!' }).getByRole('button') // 7) <button class="my-button" onclick="buttonOnClick('(row 3)')">Click!</button> aka getByRole('row', { name: 'Row 3 Z Click!' }).getByRole('button') }); test("action on nth button", async ({ page }) => { // Arrange: const elementRole = "button"; const resultsTestId = "dti-results"; const expectedMessage = "You clicked the button! (Second one!)"; const buttonLocator = page.getByRole(elementRole); const resultsLocator = page.getByTestId(resultsTestId); // print the count of buttons on the page console.log("number of button elements:", await buttonLocator.count()); // Act: // click on the 3rd button (we count from 0) await buttonLocator.nth(2).click(); // display the text content of the results element // console.log("results text content:", await resultsLocator.textContent()); // Assert: await expect(resultsLocator).toHaveText(expectedMessage); }); test("action on multiple buttons", async ({ page }) => { // Arrange: const elementRole = "button"; const elementText = "Click!"; const resultsTestId = "dti-results"; const buttonLocator = page.getByRole(elementRole, { name: elementText }); const resultsLocator = page.getByTestId(resultsTestId); // print the count of buttons on the page console.log("number of button elements:", await buttonLocator.count()); // Act: // await buttonLocator.nth(0).click(); // console.log(await resultsLocator.textContent()); // await buttonLocator.nth(1).click(); // console.log(await resultsLocator.textContent()); // await buttonLocator.nth(2).click(); // console.log(await resultsLocator.textContent()); // usage of count() method const numberOfFoundButtons = await buttonLocator.count(); for (let i = 0; i < numberOfFoundButtons; i++) { await buttonLocator.nth(i).click(); // display the text content of the results element console.log("results text content:", await resultsLocator.textContent()); } // usage of all() method for (const button of await buttonLocator.all()) { await button.click(); console.log("results text content:", await resultsLocator.textContent()); } // TODO: add assertions }); });
import { test, expect } from "@playwright/test";


test.describe("Locator lists", () => {
  test.beforeEach(async ({ page }) => {
    await page.goto("/practice/simple-multiple-elements-no-ids.html");
  });


  test("All buttons on page", async ({ page }) => {
    // Arrange:
    const elementRole = "button";
    const expectedElementsCount = 7;


    // we can define the locator for the element
    const buttonLocator = page.getByRole(elementRole);


    // print the count of buttons on the page
    console.log("number of button elements:", await buttonLocator.count());


    // Assert:
    // check if number of buttons is 7
    await expect(buttonLocator).toHaveCount(expectedElementsCount);
  });


  // unskip to see the error during test run
  test.skip("❌ SHOULD FAIL ❌ - try clicking button (when multiple buttons are on page)", async ({
    page,
  }) => {
    // Arrange:
    const elementRole = "button";


    // we can define the locator for the element
    const buttonLocator = page.getByRole(elementRole);


    // print the count of buttons on the page
    console.log("number of button elements:", await buttonLocator.count());


    // Assert:
    // check if number of buttons is 7
    await expect(buttonLocator).toHaveCount(7);


    // ❌ because there are multiple buttons on the page
    // ❌ following line will return an error:
    await buttonLocator.click();


    // ❌ with following error on console:
    // Error: locator.click: Error: strict mode violation: getByRole('button') resolved to 7 elements:
    // 1)  aka getByTestId('open-practice')
    // 2)  aka getByRole('button', { name: 'Click me!' })
    // 3)  aka getByRole('button', { name: 'Click me too!' })
    // 4)  aka getByRole('button', { name: 'Click here!' })
    // 5)  aka getByRole('row', { name: 'Row 1 X Click!' }).getByRole('button')
    // 6)  aka getByRole('row', { name: 'Row 2 Y Click!' }).getByRole('button')
    // 7)  aka getByRole('row', { name: 'Row 3 Z Click!' }).getByRole('button')
  });


  test("action on nth button", async ({ page }) => {
    // Arrange:
    const elementRole = "button";
    const resultsTestId = "dti-results";
    const expectedMessage = "You clicked the button! (Second one!)";


    const buttonLocator = page.getByRole(elementRole);
    const resultsLocator = page.getByTestId(resultsTestId);


    // print the count of buttons on the page
    console.log("number of button elements:", await buttonLocator.count());


    // Act:
    // click on the 3rd button (we count from 0)
    await buttonLocator.nth(2).click();


    // display the text content of the results element
    // console.log("results text content:", await resultsLocator.textContent());


    // Assert:
    await expect(resultsLocator).toHaveText(expectedMessage);
  });


  test("action on multiple buttons", async ({ page }) => {
    // Arrange:
    const elementRole = "button";
    const elementText = "Click!";
    const resultsTestId = "dti-results";


    const buttonLocator = page.getByRole(elementRole, { name: elementText });
    const resultsLocator = page.getByTestId(resultsTestId);


    // print the count of buttons on the page
    console.log("number of button elements:", await buttonLocator.count());


    // Act:
    // await buttonLocator.nth(0).click();
    // console.log(await resultsLocator.textContent());
    // await buttonLocator.nth(1).click();
    // console.log(await resultsLocator.textContent());
    // await buttonLocator.nth(2).click();
    // console.log(await resultsLocator.textContent());


    // usage of count() method
    const numberOfFoundButtons = await buttonLocator.count();
    for (let i = 0; i < numberOfFoundButtons; i++) {
      await buttonLocator.nth(i).click();


      // display the text content of the results element
      console.log("results text content:", await resultsLocator.textContent());
    }


    // usage of all() method
    for (const button of await buttonLocator.all()) {
      await button.click();
      console.log("results text content:", await resultsLocator.textContent());
    }


    // TODO: add assertions
  });
});


Zewnętrzne linki i zasoby

2 komentarze

  1. let numberOfFoundButtons = await buttonLocator.count();
    powinno być:
    const numberOfFoundButtons = await buttonLocator.count();
    let numberOfFoundButtons = await buttonLocator.count(); powinno być: const numberOfFoundButtons = await buttonLocator.count();
    let numberOfFoundButtons = await buttonLocator.count();
    powinno być:
    const numberOfFoundButtons = await buttonLocator.count();
    

    A czemu tak?
    Zmienne deklarowane jako const są stałe, co poprawia czytelność kodu i jasno pokazuje, że wartość nie powinna ulec zmianie.
    Używanie const jest dobrą praktyką wszę

    Avatar Radosław

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *