Rozwiązanie – operacje na listach lokatorów

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 🎭

Przykładowe rozwiązanie

Rozwiązanie podstawowe
import { test, expect } from "@playwright/test";
test.describe("Multiple checkboxes", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/practice/simple-multiple-elements-no-ids.html");
});
test("action on multiple checkboxes", async ({ page }) => {
// Arrange:
const elementRole = "checkbox";
const resultsTestId = "dti-results";
const expectedNumberOfElements = 5;
const checkboxLocator = page.getByRole(elementRole);
const resultsLocator = page.getByTestId(resultsTestId);
// Assert:
await expect(checkboxLocator).toHaveCount(expectedNumberOfElements);
const numberOfFoundCheckboxes = await checkboxLocator.count();
for (let i = 0; i < numberOfFoundCheckboxes; i++) {
// Act:
await checkboxLocator.nth(i).check();
// display the text content of the results element
console.log("results text content:", await resultsLocator.textContent());
}
});
});
import { test, expect } from "@playwright/test"; test.describe("Multiple checkboxes", () => { test.beforeEach(async ({ page }) => { await page.goto("/practice/simple-multiple-elements-no-ids.html"); }); test("action on multiple checkboxes", async ({ page }) => { // Arrange: const elementRole = "checkbox"; const resultsTestId = "dti-results"; const expectedNumberOfElements = 5; const checkboxLocator = page.getByRole(elementRole); const resultsLocator = page.getByTestId(resultsTestId); // Assert: await expect(checkboxLocator).toHaveCount(expectedNumberOfElements); const numberOfFoundCheckboxes = await checkboxLocator.count(); for (let i = 0; i < numberOfFoundCheckboxes; i++) { // Act: await checkboxLocator.nth(i).check(); // display the text content of the results element console.log("results text content:", await resultsLocator.textContent()); } }); });
import { test, expect } from "@playwright/test";


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


  test("action on multiple checkboxes", async ({ page }) => {
    // Arrange:
    const elementRole = "checkbox";
    const resultsTestId = "dti-results";
    const expectedNumberOfElements = 5;


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


    // Assert:
    await expect(checkboxLocator).toHaveCount(expectedNumberOfElements);


    const numberOfFoundCheckboxes = await checkboxLocator.count();
    for (let i = 0; i < numberOfFoundCheckboxes; i++) {
      // Act:
      await checkboxLocator.nth(i).check();


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




Rozwiązanie trudniejsze, z asercją
import { test, expect } from "@playwright/test";
test.describe("Multiple locators", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/practice/simple-multiple-elements-no-ids.html");
});
test("action on multiple checkboxes (advanced, with assertion)", async ({
page,
}) => {
// Arrange:
const elementRole = "checkbox";
const resultsTestId = "dti-results";
const expectedMessages = {
0: "Checkbox is checked! (Opt 1!)",
1: "Checkbox is checked! (Opt 2!)",
2: "Checkbox is checked! (Opt 3!)",
3: "Checkbox is checked! (Opt 4!)",
4: "Checkbox is checked! (Opt 5!)",
};
const expectedNumberOfElements = 5;
const checkboxLocator = page.getByRole(elementRole);
const resultsLocator = page.getByTestId(resultsTestId);
// Assert:
await expect(checkboxLocator).toHaveCount(expectedNumberOfElements);
// Act & Assert:
const numberOfFoundCheckboxes = await checkboxLocator.count();
for (let i = 0; i < numberOfFoundCheckboxes; i++) {
// Act:
await checkboxLocator.nth(i).check();
console.log(await resultsLocator.innerText());
// Assert:
await expect.soft(resultsLocator).toHaveText(expectedMessages[i]);
}
});
});
import { test, expect } from "@playwright/test"; test.describe("Multiple locators", () => { test.beforeEach(async ({ page }) => { await page.goto("/practice/simple-multiple-elements-no-ids.html"); }); test("action on multiple checkboxes (advanced, with assertion)", async ({ page, }) => { // Arrange: const elementRole = "checkbox"; const resultsTestId = "dti-results"; const expectedMessages = { 0: "Checkbox is checked! (Opt 1!)", 1: "Checkbox is checked! (Opt 2!)", 2: "Checkbox is checked! (Opt 3!)", 3: "Checkbox is checked! (Opt 4!)", 4: "Checkbox is checked! (Opt 5!)", }; const expectedNumberOfElements = 5; const checkboxLocator = page.getByRole(elementRole); const resultsLocator = page.getByTestId(resultsTestId); // Assert: await expect(checkboxLocator).toHaveCount(expectedNumberOfElements); // Act & Assert: const numberOfFoundCheckboxes = await checkboxLocator.count(); for (let i = 0; i < numberOfFoundCheckboxes; i++) { // Act: await checkboxLocator.nth(i).check(); console.log(await resultsLocator.innerText()); // Assert: await expect.soft(resultsLocator).toHaveText(expectedMessages[i]); } }); });
import { test, expect } from "@playwright/test";


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


  test("action on multiple checkboxes (advanced, with assertion)", async ({
    page,
  }) => {
    // Arrange:
    const elementRole = "checkbox";
    const resultsTestId = "dti-results";
    const expectedMessages = {
      0: "Checkbox is checked! (Opt 1!)",
      1: "Checkbox is checked! (Opt 2!)",
      2: "Checkbox is checked! (Opt 3!)",
      3: "Checkbox is checked! (Opt 4!)",
      4: "Checkbox is checked! (Opt 5!)",
    };
    const expectedNumberOfElements = 5;


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


    // Assert:
    await expect(checkboxLocator).toHaveCount(expectedNumberOfElements);


    // Act & Assert:
    const numberOfFoundCheckboxes = await checkboxLocator.count();
    for (let i = 0; i < numberOfFoundCheckboxes; i++) {
      // Act:
      await checkboxLocator.nth(i).check();
      console.log(await resultsLocator.innerText());


      // Assert:
      await expect.soft(resultsLocator).toHaveText(expectedMessages[i]);
    }
  });


});



Zasoby i dokumentacja

12 komentarzy

  1. Cześć
    Miałam problem z użyciem obiektu expectedMessages:

    Element implicitly has an ‘any’ type because expression of type ‘number’ can’t be used to index type ‘{ 0: string; 1: string; 2: string; 3: string; 4: string; }’.
    No index signature with a parameter of type ‘number’ was found on type ‘{ 0: string; 1: string; 2: string; 3: string; 4: string; }’.

    Musiałam z tego obiektu robić array.

    Avatar Viktoriia
        1. Hmm błąd o którym wspominasz prawdopodobnie wynikał z konfiguracji projektu i ze TypeScript traktował klucze w obiekcie jako “0”, “1” itd.
          Gdy próbujesz użyć liczby do indeksowania (np. expectedMessages[2]), TypeScript nie znajduje dopasowania do indeksu typu number – oczekuje, że obiekt będzie miał sygnaturę indeksu zdefiniowaną np. jako

          [key: number]: string
          [key: number]: string.
          Rozwiązania są 2 – jedno to zamiana na listę (czyli Twoje rozwiązanie).
          Drugie to dodanie sygnatury indeksu do obiektu, czyli jawne określienie, że obiekt ten ma sygnaturę indeksu dla number np:

          const expectedMessages: { [key: number]: string } = {
          0: 'wiadomość0',
          1: 'wiadomość1',
          2: 'wiadomość2',
          3: 'wiadomość3',
          4: 'wiadomość4',
          };
          const expectedMessages: { [key: number]: string } = { 0: 'wiadomość0', 1: 'wiadomość1', 2: 'wiadomość2', 3: 'wiadomość3', 4: 'wiadomość4', };
          const expectedMessages: { [key: number]: string } = {
              0: 'wiadomość0',
              1: 'wiadomość1',
              2: 'wiadomość2',
              3: 'wiadomość3',
              4: 'wiadomość4',
          };
          
          Krzysiek Kijas Krzysiek
  2. A dla mnie nie przemawia ani tablica ani lista 😉

    await page.goto('/practice/simple-multiple-elements-no-ids.html');
    const checkboxLocator = page.getByRole('checkbox');
    console.log(await checkboxLocator.count());
    await expect(checkboxLocator).toHaveCount(5);
    const result = page.getByTestId('dti-results-container');
    for (const button of await checkboxLocator.all()) {
    await button.check();
    console.log(await result.textContent());
    }
    console.log('====================================');
    for (let i = 0; i < (await checkboxLocator.count()); i++) {
    await checkboxLocator.nth(i).check();
    await expect(result).toHaveText(`Checkbox is checked! (Opt ${i + 1}!)`);
    }
    await page.goto('/practice/simple-multiple-elements-no-ids.html'); const checkboxLocator = page.getByRole('checkbox'); console.log(await checkboxLocator.count()); await expect(checkboxLocator).toHaveCount(5); const result = page.getByTestId('dti-results-container'); for (const button of await checkboxLocator.all()) { await button.check(); console.log(await result.textContent()); } console.log('===================================='); for (let i = 0; i < (await checkboxLocator.count()); i++) { await checkboxLocator.nth(i).check(); await expect(result).toHaveText(`Checkbox is checked! (Opt ${i + 1}!)`); }
    await page.goto('/practice/simple-multiple-elements-no-ids.html');
    	const checkboxLocator = page.getByRole('checkbox');
    	console.log(await checkboxLocator.count());
    	await expect(checkboxLocator).toHaveCount(5);
    	const result = page.getByTestId('dti-results-container');
    
    	for (const button of await checkboxLocator.all()) {
    		await button.check();
    		console.log(await result.textContent());
    	}
    	console.log('====================================');
    
    	for (let i = 0; i < (await checkboxLocator.count()); i++) {
    		await checkboxLocator.nth(i).check();
    		await expect(result).toHaveText(`Checkbox is checked! (Opt ${i + 1}!)`);
    	}
    

    wystarczy spojrzeć, że ten wpis się powtarza "Checkbox is checked! (Opt)"
    Gdyby to pojawiło się dwa razy to jeszcze ok, ale w przypadku 5 razy to już jest DRY

    Można prościej 😉

    Avatar Radosław
    1. Zgadzam się, ze, ze to może być kolejny krok 🙂
      W tym przypadku rozwiązanie z listą pokazuje nam duplikacje, a tym samym możemy zrefaktoryzować rozwiązanie i wydzielić część wspólną.

      Rozwiązanie z listą ma na celu pokazanie jak można projektować struktury danych się przydać, gdy będziemy potrzebować odnosić się do oczekiwanych danych za pomocą klucza 😉

      Krzysiek Kijas Krzysiek
          1. export enum VerifyMessage {
            Option1 = "Checkbox is checked! (Opt 1!)",
            Option2 = "Checkbox is checked! (Opt 2!)",
            Option3 = "Checkbox is checked! (Opt 3!)",
            Option4 = "Checkbox is checked! (Opt 4!)",
            Option5 = "Checkbox is checked! (Opt 5!)"
            }
            import w teście: import { VerifyMessage } from './verifyMessages';
            test:
            await page.goto('/practice/simple-multiple-elements-no-ids.html');
            const checkboxLocator = page.getByRole('checkbox');
            console.log(await checkboxLocator.count());
            await expect(checkboxLocator).toHaveCount(5);
            const result = page.getByTestId('dti-results-container');
            for (let i = 0; i < (await checkboxLocator.count()); i++) {
            await checkboxLocator.nth(i).check();
            // Pobranie oczekiwanej wartości z enum
            const expectedMessage = VerifyMessage[`Option${i + 1}` as keyof typeof VerifyMessage];
            await expect(result).toHaveText(expectedMessage);
            }
            }
            export enum VerifyMessage { Option1 = "Checkbox is checked! (Opt 1!)", Option2 = "Checkbox is checked! (Opt 2!)", Option3 = "Checkbox is checked! (Opt 3!)", Option4 = "Checkbox is checked! (Opt 4!)", Option5 = "Checkbox is checked! (Opt 5!)" } import w teście: import { VerifyMessage } from './verifyMessages'; test: await page.goto('/practice/simple-multiple-elements-no-ids.html'); const checkboxLocator = page.getByRole('checkbox'); console.log(await checkboxLocator.count()); await expect(checkboxLocator).toHaveCount(5); const result = page.getByTestId('dti-results-container'); for (let i = 0; i < (await checkboxLocator.count()); i++) { await checkboxLocator.nth(i).check(); // Pobranie oczekiwanej wartości z enum const expectedMessage = VerifyMessage[`Option${i + 1}` as keyof typeof VerifyMessage]; await expect(result).toHaveText(expectedMessage); } }
            export enum VerifyMessage {
              Option1 = "Checkbox is checked! (Opt 1!)",
              Option2 = "Checkbox is checked! (Opt 2!)",
              Option3 = "Checkbox is checked! (Opt 3!)",
              Option4 = "Checkbox is checked! (Opt 4!)",
              Option5 = "Checkbox is checked! (Opt 5!)"
            }
            
            import w teście: import { VerifyMessage } from './verifyMessages';
            
            test:
            await page.goto('/practice/simple-multiple-elements-no-ids.html');
            const checkboxLocator = page.getByRole('checkbox');
            console.log(await checkboxLocator.count());
            await expect(checkboxLocator).toHaveCount(5);
            
            const result = page.getByTestId('dti-results-container');
            
            for (let i = 0; i < (await checkboxLocator.count()); i++) {
              await checkboxLocator.nth(i).check();
            
              // Pobranie oczekiwanej wartości z enum
              const expectedMessage = VerifyMessage[`Option${i + 1}` as keyof typeof VerifyMessage];
              await expect(result).toHaveText(expectedMessage);
            }
            
            }
            
            Avatar Radosław
  3. hej ja w dodatkowym zadaniu użyłem takiego zapisu

    const verifyMessage = [
    'Checkbox is checked! (Opt 1!)',
    'Checkbox is checked! (Opt 2!)',
    'Checkbox is checked! (Opt 3!)',
    'Checkbox is checked! (Opt 4!)',
    'Checkbox is checked! (Opt 5!)']
    const verifyMessage = [ 'Checkbox is checked! (Opt 1!)', 'Checkbox is checked! (Opt 2!)', 'Checkbox is checked! (Opt 3!)', 'Checkbox is checked! (Opt 4!)', 'Checkbox is checked! (Opt 5!)']
       
    const verifyMessage = [
        'Checkbox is checked! (Opt 1!)',
        'Checkbox is checked! (Opt 2!)',
        'Checkbox is checked! (Opt 3!)',
        'Checkbox is checked! (Opt 4!)', 
        'Checkbox is checked! (Opt 5!)'] 

    choć pokazany zapis obiektu bardziej do mnie przemawia 🙂 świetna lekcja i zadania które faktycznie wnoszą praktyczne umiejętności 😉

    Avatar Andrzej
    1. Dzięki wielkie!🙇‍♂️

      W tym przypadku tka lista też się sprawdzi, a lista obiektów daje więcej możliwości.
      A to moze się przydać w bardziej skomplikowanych przypadkach lub gdy potrzebujemy bardziej skomplikowanych danych testowych 🙂

      Krzysiek Kijas Krzysiek

Dodaj komentarz

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