Rozwiązanie – agregujemy akcje

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

Dodatkowe materiały

Rozwiązanie prezentowane w tej lekcji zajdziesz w naszym repozytorium: L11_pom_solution

Zawartość pulpit.page.ts:

import { Page } from '@playwright/test';
import { SideMenuComponent } from '../component/side-menu.component';


export class PulpitPage {
  constructor(private page: Page) {}


  sideMenuComponent = new SideMenuComponent(this.page);


  transferReceiverInput = this.page.locator('#widget_1_transfer_receiver');
  transferAmountInput = this.page.locator('#widget_1_transfer_amount');
  transferTitleInput = this.page.locator('#widget_1_transfer_title');


  transferButton = this.page.getByRole('button', { name: 'wykonaj' });
  actionCloseButton = this.page.getByTestId('close-button');


  messageText = this.page.locator('#show_messages');


  topUpReceiverInput = this.page.locator('#widget_1_topup_receiver');
  topUpAmountInput = this.page.locator('#widget_1_topup_amount');
  topUpAgreementCheckbox = this.page.locator(
    '#uniform-widget_1_topup_agreement span'
  );
  topUpExecuteButton = this.page.getByRole('button', {
    name: 'doładuj telefon',
  });


  moneyValueText = this.page.locator('#money_value');
  userNameText = this.page.getByTestId('user-name');


  async executeQuickPayment(
    receiverId: string,
    transferAmount: string,
    transferTitle: string
  ): Promise<void> {
    await this.transferReceiverInput.selectOption(receiverId);
    await this.transferAmountInput.fill(transferAmount);
    await this.transferTitleInput.fill(transferTitle);


    await this.transferButton.click();
    await this.actionCloseButton.click();
  }


  async executeMobileTopUp(
    topUpReceiver: string,
    topUpAmount: string
  ): Promise<void> {
    await this.topUpReceiverInput.selectOption(topUpReceiver);
    await this.topUpAmountInput.fill(topUpAmount);
    await this.topUpAgreementCheckbox.click();


    await this.topUpExecuteButton.click();
    await this.actionCloseButton.click();
  }
}

Zawartość pulpit.spec.ts:

import { test, expect } from '@playwright/test';
import { loginData } from '../test-data/login.data';
import { LoginPage } from '../pages/login.page';
import { PulpitPage } from '../pages/pulpit.page';


test.describe('Pulpit tests', () => {
  let pulpitPage: PulpitPage;


  test.beforeEach(async ({ page }) => {
    const userId = loginData.userId;
    const userPassword = loginData.userPassword;


    await page.goto('/');
    const loginPage = new LoginPage(page);
    await loginPage.login(userId, userPassword);
   
    pulpitPage = new PulpitPage(page);
  });


  test('quick payment with correct data', async ({ page }) => {
    // Arrange
    const receiverId = '2';
    const transferAmount = '150';
    const transferTitle = 'pizza';
    const expectedTransferReceiver = 'Chuck Demobankowy';


    // Act
    await pulpitPage.executeQuickPayment(
      receiverId,
      transferAmount,
      transferTitle
    );


    // Assert
    await expect(pulpitPage.messageText).toHaveText(
      `Przelew wykonany! ${expectedTransferReceiver} - ${transferAmount},00PLN - ${transferTitle}`
    );
  });


  test('successful mobile top-up', async ({ page }) => {
    // Arrange
    const topUpReceiver = '500 xxx xxx';
    const topUpAmount = '50';
    const expectedMessage = `Doładowanie wykonane! ${topUpAmount},00PLN na numer ${topUpReceiver}`;


    // Act
    await pulpitPage.executeMobileTopUp(topUpReceiver, topUpAmount);


    // Assert
    await expect(pulpitPage.messageText).toHaveText(expectedMessage);
  });


  test('correct balance after successful mobile top-up', async ({ page }) => {
    // Arrange
    const topUpReceiver = '500 xxx xxx';
    const topUpAmount = '50';
    const initialBalance = await pulpitPage.moneyValueText.innerText();
    const expectedBalance = Number(initialBalance) - Number(topUpAmount);


    // Act
    await pulpitPage.executeMobileTopUp(topUpReceiver, topUpAmount);


    // Assert
    await expect(pulpitPage.moneyValueText).toHaveText(`${expectedBalance}`);
  });
});


11 komentarzy

  1. Hej mam problem,

    Poniższy kod działa poprawnie

       test('quick payment with correct data', async ({ page }) => {
        // Arrange
        const expectedUserName = 'Jan Demobankowy';
        const reciverId = '2';
        const transferAmount = '120';
        const transferTitle = 'Zwrot środków';
        const expectedTransferReceiver = 'Chuck Demobankowy';
    
        // Act
    
         await pulpit.transferReceiver.selectOption(reciverId);
         await pulpit.transferAmount.fill(transferAmount);
         await pulpit.transferTitle.fill(transferTitle);
         await pulpit.transferButton.click();
         await pulpit.closeButton.click();
    
    
        // Assert
        await expect(pulpit.confirmationMessage).toHaveText(
          `Przelew wykonany! ${expectedTransferReceiver} - ${transferAmount},00PLN - ${transferTitle}`,
        );
      });

    Natomiast jak dodałem metodę
    pulpit.executeQuickPayment(reciverId,transferAmount,transferTitle)

    Która wygląda tak samo jak u Was

     async executeQuickPayment(
            receiverId: string,
            transferAmount: string,
            transferTitle: string
          ): Promise {
            await this.transferReceiver.selectOption(receiverId);
            await this.transferAmount.fill(transferAmount);
            await this.transferTitle.fill(transferTitle);
            await this.transferButton.click();
            await this.closeButton.click();
          }

    To nie chce kliknąć na closeButton i rzuca błąd:

    Error: locator.click: Target page, context or browser has been closed

    Głowie się co może to powodować, Z góry dzięki za pomoc!

    Avatar Patryk Kostrzewa
    1. Hej,
      Wszystko wskazuje na to, ze brakuje await przed wywołaniem metody (która jest asynchroniczna (słówko async)) 😉

      czyli:

      await pulpit.executeQuickPayment(reciverId,transferAmount,transferTitle)
      
      Krzysiek Kijas Krzysiek Kijas
        1. Ciesze się, że śmiga 😀
          PS. Z doświadczenia powiem, że await (albo jego brak) jest częstym powodem rożnych błędów w testach 😉 A że metoda/funkcja asynchroniczna jest poprawna (ale niekoniecznie w danym miejscu) bez await, to po naszej stronie jest jej przypilnowanie 😀

          Krzysiek Kijas Krzysiek Kijas
    1. Hej,
      Dobre pytanie 🙂
      Tu sporo zależy od konkretnych scenariuszów oraz testowanej aplikacji.

      Tu się pojawiają dwie kwestie – uruchomienie testów z różnymi użytkownikami i implementacja testów, logiki i POM 🙂

      Implementacja POM – tutaj można pójść prosto, czyli zaimplementować reprezentacje stron z punktu widzenia użytkownika, który może wykonać każdą operacje.
      Plusem tego rozwiązani jest – prostota implementacji i brak dodatkowej logiki i duplikacji kodu w obiektach stron.
      Minusem – my z poziomu testów musimy wiedzieć co dany użytkownik o danych uprawnieniach może wykonać, a czego nie może.

      Bardziej skomplikowaną wersją jest dodanie dziedziczenia, ze stronami pochodnymi implementującymi akcje,w zależności od roli. To rozwiązanie zdejmuje z nas potrzebę pamiętania w testach co dany użytkownik może wykonać, natomiast może bardzo skomplikować implementacje samych page objectów.

      Kwestia testów – inne testy będą dla użytkowników, którzy moga wejść na stronę X i zrobić Y, niz dla użytkowników, którzy nie mają dostępu do strony X.
      Mozna je pogrupować w katalogi, albo tagi, a później możemy uruchamiać nasze testy z różnymi zestawami danych 🙂

      Temat ten planujemy poruszyć w zaawansowanej części Programu o Playwright 🙂
      Natomiast testy na różnych środowiskach (z wykorzystaniem różnych danych) opisujemy ogólnie w naszym poście: https://playwright.info/playwright-testy-na-roznych-srodowiskach – pokazujemy tam wykorzystanie projects w Playwright i biblioteki dotenv (którą też dokładnie omawiamy w części zaawansowanej).

      Krzysiek Kijas Krzysiek Kijas
        1. To dokładnie pokrywa punkt Sposób 2 (rozszerzony) z tego posta 😀

          W dużym skrócie – możemy przygotować klika plików ze zmiennymi środowiskowymi, z których korzystamy w testach.
          Każdy plik będzie odpowiadał danemu środowisku.
          W kodzie dodajemy możliwość wyboru dowolnego pliku ze zmiennymi środowiskowymi 🙂

          Później możemy np. podczas uruchamiania testów podac parametr, który mówi z jakim plikiem/na jakim środowisku chcemy puszczać testy np.:

          $env:ENV="staging"; npx playwright test
          

          a zmienne w testach (adresy, dane użytkowników etc) będą automatycznie pobierane z podanego przez nas pliku 🙂

          Krzysiek Kijas Krzysiek Kijas

Dodaj komentarz

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