Powrót do: Playwright Elements – Kluczowe koncepcje automatyzacji testów
Operacje na listach lokatorów
Prezentacja
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 } ) => {
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 ( ) ) ;
// 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) Main Practice Page aka getByTestId('open-practice')
2) Click me! 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 } ) => {
test ( "action on nth button" , async ( { page } ) => {
test ( "action on multiple buttons" , async ( { page } ) => {
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 } ) => {
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 ( ) ) ;
// 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 ( { 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 ( ) ) ;
// 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 } ) => {
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 ( ) ) ;
// 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());
await expect ( resultsLocator ) . toHaveText ( expectedMessage ) ;
test ( "action on multiple buttons" , async ( { page } ) => {
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 ( ) ) ;
// 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 ( ) ) ;
for ( const button of await buttonLocator. all ( ) ) {
console . log ( "results text content:" , await resultsLocator. textContent ( ) ) ;
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) Main Practice Page aka getByTestId('open-practice')
// 2) Click me! aka getByRole('button', { name: 'Click me!' })
// 3) Click me too! aka getByRole('button', { name: 'Click me too!' })
// 4) Click here! aka getByRole('button', { name: 'Click here!' })
// 5) Click! aka getByRole('row', { name: 'Row 1 X Click!' }).getByRole('button')
// 6) Click! aka getByRole('row', { name: 'Row 2 Y Click!' }).getByRole('button')
// 7) Click! 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
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ę
Pełna zgoda!
Prawdopodobnie tutaj z rozpędu wykorzystałem
let