DRY i hook beforeEach

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

Prezentacja

DRY i hook beforeEach

DRY i hook beforeEach

Dodatkowe materiały

Bazujemy na kodzie lekcji L05_rozwiazanie_aaa

Kod wynikowy tej lekcji znajduje się tu: L06_dry_hooks

Pamiętaj, aby po danej porcji pracy: uruchamiać test, commitować poprawnie działający kod 😉

Czym jest DRY

DRY (czyli Don’t Repeat Yourself) jest zasadą w programowaniu, która mówi, żeby nie powtarzać tego samego kodu w różnych częściach programu.

Zamiast powtarzać kod, można wydzielić powtarzające się części i umieścić je w jednym miejscu (pliku, funkcji, metodzie, etc.). Taka praktyka często ułatwia zrozumienie kodu, ułatwia wprowadzanie zmian oraz redukuje ryzyko popełnienia błędów.

Dzięki temu możemy zaoszczędzić czas i wysiłek, ponieważ nie musimy pisać tego samego kodu wielokrotnie 😉

Hook beforeEach

beforeEach() to hook, czyli funkcja wywoływana przed każdym testem. Występuje ona w wielu bibliotekach do testów w języku JavaScript/TypeScript.

beforeEach() służy do wykonania pewnych czynności przed testami, np. przygotowanie danych, logowanie, przygotowanie środowiska, etc. Dzięki temu możemy uniknąć powielania kodu w każdej funkcji testowej.

Wyciągnięcie url do hook beforeEach

beforeEach() w pliku login.spec.ts wyciągamy powtarzający się kod wspólny dla wszystkich testów:

  test.beforeEach(async ({ page }) => {
    const url = 'https://demo-bank.vercel.app/';
    await page.goto(url);
  });

Struktura pliku login.spec.ts będzie wyglądać tak:


test.describe('User login to Demobank', () => {
  test.beforeEach(async ({ page }) => {
    const url = 'https://demo-bank.vercel.app/';
    await page.goto(url);
  });

  test('successful login with correct credentials', async ({ page }) => {
	// Arrange
	const userId = 'testerLO';
	const userPassword = '10987654';

Pamiętamy o usunięciu kodu, który został wyciągnięty do beforeEach() ze wszystkich testów w ramach całego describe()

Uruchomienie testów dla danego pliku

Konsola bash w VSC na Windows:
Kliknij strzałkę w dół w prawym górnym menu konsoli i wybierz Git Bash.

Wprowadź polecenie npx playwright test

Zacznij wpisywać nazwy folderów lub plików, a następnie uzupełniać podpowiedzi klawiszem TAB.

Dla login.spec.ts będzie to polecenie:

npx playwright test tests/login.spec.ts

Implementacja DRY w w testach pulpitu

Możemy wyciągnąć kod przejścia do strony i zalogowania się:

	const url = 'https://demo-bank.vercel.app/';
	const userId = 'testerLO';
	const userPassword = '10987654';
	await page.goto(url);
	await page.getByTestId('login-input').fill(userId);
	await page.getByTestId('password-input').fill(userPassword);
	await page.getByTestId('login-button').click();

z testów do beforeEach():

test.beforeEach(async ({ page }) => {
	const userId = 'testerLO';
	const userPassword = '10987654';
	const url = 'https://demo-bank.vercel.app/';

	await page.goto(url);
	await page.getByTestId('login-input').fill(userId);
	await page.getByTestId('password-input').fill(userPassword);
	await page.getByTestId('login-button').click();
  });
TIP: Pamiętaj o zasadzie: jeśli używamy zmiennej w obrębie tylko jednego bloku kodu staramy się aby nie była ona dostępna dla innych.

Przykład: zmienna na poziomie describe jest dostępna we wszystkich testach a na poziomie beforeEach() tylko dla tego bloku. Jeśli zmienna nie jest używana w testach a tylko w beforeEach to powinna tylko tam się znaleźć.

Zawartość pliku pulpit.spec.ts:

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


test.describe('Pulpit tests', () => {
  test.beforeEach(async ({ page }) => {
    const userId = 'testerLO';
    const userPassword = '10987654';
    const url = 'https://demo-bank.vercel.app/';


    await page.goto(url);
    await page.getByTestId('login-input').fill(userId);
    await page.getByTestId('password-input').fill(userPassword);
    await page.getByTestId('login-button').click();
  });


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


    // Act
    await page.locator('#widget_1_transfer_receiver').selectOption(receiverId);
    await page.locator('#widget_1_transfer_amount').fill(transferAmount);
    await page.locator('#widget_1_transfer_title').fill(transferTitle);


    await page.getByRole('button', { name: 'wykonaj' }).click();
    await page.getByTestId('close-button').click();


    // Assert
    await expect(page.locator('#show_messages')).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 page.locator('#widget_1_topup_receiver').selectOption(topUpReceiver);
    await page.locator('#widget_1_topup_amount').fill(topUpAmount);
    await page.locator('#uniform-widget_1_topup_agreement span').click();
    await page.getByRole('button', { name: 'doładuj telefon' }).click();
    await page.getByTestId('close-button').click();


    // Assert
    await expect(page.locator('#show_messages')).toHaveText(expectedMessage);
  });
});

Wyciągnięcie zmiennej url do konfiguracji

Z beforeEach() w pliku login.spec.ts wyciągamy wartość zmiennej url:

   test.beforeEach(async ({ page }) => {
    const url = 'https://demo-bank.vercel.app/';
    await page.goto(url)
  });

I umieszczamy ją w pliku playwright.config.ts pod zmienną baseURL (wystarczy jej odkomentowanie):

  use: {
    /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
    actionTimeout: 0,
    /* Base URL to use in actions like `await page.goto('/')`. */
    baseURL: 'https://demo-bank.vercel.app',


    /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
    trace: 'retain-on-failure',
    video: 'retain-on-failure',
  },

Po takiej zmianie, w kodzie naszych testów logowania możemy zmienić:

const url = 'https://demo-bank.vercel.app/'; 
await page.goto(url);

na:

    await page.goto('/');

Również w testach pulpitu aplikujemy tę zmianę.

TIP: Zauważ:

Zmienna kod dla każdego testu, gdy jest on wydzielony do beforeEach() przebiega dużo szybciej.

Posiadanie globalnie ustawionego adresu url pozwala nam szybko zmienić go w obrębie wszystkich testów.

DRY – czy zawsze i wszędzie?

Nie zawsze warto stosować DRY. Dla przykładu w testach w pliku login.spec.ts mamy powtórzony kod userId ale nie we wszystkich testach.

Wyciąganie nadmiarowych danych powoduje ich dostępność w obrębie wszystkich testów, nawet takich, które danego rozwiązania nie potrzebują.

Dlatego warto się zastanowić jak zastosowanie DRY wpłynie na nasze bloki i czy nie idziemy w drugą stronę zbyt nadmiarowo wyciągając i współdzieląc dane.

32 komentarze

  1. Hej,

    to moja pierwsza styczność z Playwright i wstępem do automatyzacji i jestem mega wdzięczny za ten kurs.

    Bardzo mi odpowiada taka forma, gdzie pokazujecie jak się zmieniają testy na jednym projekcie.

    To duże ułatwienie dla mnie jako osoby, która nie koduje

  2. Hej, pytanie o AAA.
    Zgodnie z zasadą DRY wyniosłam do beforeEach zmienne user_id i user_pass i wykorzystałąm je w pierwszym teście, Ale w drugim teście też z nich korzystam i nie mam co wpisać pod ‘//Arrange’
. Jak do tego podejść, żeby to miało sens, zostawić puste arrange, zrezygnować z niego, czy jest może jeszcze jakies inne sensowne podejście?

    test.describe('Adding to the cart tests', () => {
      
      // Arrange
      test.beforeEach(async ({ page }) => {
        const userName = 'standard_user';
        const userPass = 'secret_sauce';
        await page.goto('/');
        await page.locator('#user-name').fill(userName);
        await page.locator('#password').fill(userPass);
      });
    
    // Act
      test('listing all items from the main page', async ({ page }) => {
        await page.locator('#login-button').click();
    
    // Assert
        await expect(page.locator('[data-test="inventory-item"]')).toHaveCount(6);
      });
    
    // Arrange
    // Act
      test('adding an item to the cart', async ({ page }) => {
        await page.locator('#login-button').click();
        await page.locator('#add-to-cart-sauce-labs-backpack').click();
        await page.locator('[data-test="shopping-cart-link"]').click();
    
    // Assert
        await expect(page.locator('[data-test="inventory-item"]')).toHaveCount(1)
      });
    
    Avatar Karolina Kozłowska
    1. Hej Karolina!
      Zdecydowanie można pominąć sekcję jeśli jej nie potrzebujemy i nie jest to zła praktyka.
      Czytający test będzie wtedy próbował odnaleźć sekcję Arrange gdzieś powyżej i w końcu trafi na odpowiednie miejsce.

      Jedynie w Twoim kodzie dałbym Act do wewnątrz testu gdyż tam rozgrywa się główny scenariusz i kroki.

      Pozdrawiam!

      Przemek Przemek
  3. Cześć,
    mam jakiś problem z dostępnością constów użytych w beforeEach:
    const amount = ‘150’;
    Test nie może ich znaleźć, trzeba je jakoś specjalnie przekazać tak jak page?

    Cannot find name ‘amount’ gdy próbuję wywołać stała w teście 🙁

    Avatar Jacek Kraś
      1. Chodzi o wykorzystanie amount (daem tą samą kwote w 2 testach dlatego tak)
        Nie znajduje go wtedy w expecedSuccessTransfer i przy wypełnianiu pola

        Można to naprawić przenosząc deklarację bespośrednio do test.describe, pytanie czy to dobra praktyka i jakie dane powinniśmy tam umieścić? (pomijając kwestię nadmiarowości danych w pozostałych testach)

        test.describe('Pulpit Tests', () => {
          
          test.beforeEach(async ({ page }) =>{
            const userLogin = 'tester11';
            const userPass = 'password';
            const amount = '150';
            
            await page.goto('/');
            
            await page.getByTestId('login-input').fill(userLogin);
            await page.getByTestId('password-input').fill(userPass);
            await page.getByTestId('login-button').click();
            
            
          })
          
          test('Quick payment - correct data', async ({ page }) => {
            //Arrange
            const receiver = '2';
            const title = 'pizza';
            const expectedReceiver = 'Chuck Demobankowy';
            const expecedSuccessTransfer = `Przelew wykonany! ${expectedReceiver} - ${amount},00PLN - ${title}`;
            
            //Act
            await page.locator('#widget_1_transfer_receiver').selectOption(receiver);
            await page.locator('#widget_1_transfer_amount').fill(amount);
            await page.locator('#widget_1_transfer_title').fill(title);
        
        Avatar Jacek Kraś
        1. Hej Jacek!
          Wystarczy daną zmienną ustawić pod describe:

          test.describe('Pulpit Tests', () => {
           const amount = '150'; 
          

          i można z niej korzystać w obrębie całego describe.

          Jeśli chciałbyś modyfikowalny obiekt ustawiany np w beforeEach i dostępny ze zmodyfikowaną wartością w testach to wyglądało by to tak:

          test.describe('Pulpit Tests', () => {
            let amount = string;
            
            test.beforeEach(async ({ page }) =>{
              amount = "150"; 
            })
            
            test('Quick payment - correct data', async ({ page }) => {
               await expect(page.amount).toHaveText(amount);
          

          To standardowa praktyka.

          Warto tu zwrócić uwagę, że te zmienne są dostępne w całym obszarze describe.
          Powinny być one wykorzystywane przez wszystkie testy gdyż nadmiarowe stałe/zmienne niepotrzebnie udostępniane (wyciekające) stanowią narzut przy czytaniu i zrozumieniu testów.

          Jeśli potrzebujesz zmiennych tylko do pewnej grupy testów należy wydzielić zagnieżdżone describe wyłącznie ze zmiennymi dotyczącymi danych testów.

          Oczywiście jest to rekomendacja i czasem są od niej odstępstwa.

          Mam nadzieję, że to w miarę rozjaśnia sytuację.
          Pozdro!

          Przemek Przemek
    1. Powiedziałbym, zę to zależy od przypadku.
      Gdy w hooku umieścimy tylko soft assert, który zakończy się niepowodzeniem, to test zostanie uruchomiony – i nawet jesli test zakończy sie powodzeniem, to przez hook zostanie oznaczony jako failed 🙂
      Dlatego trzebaby się zastanowić co chcemy osiągnąc i co da nam tego typu sprawdzenie 🙂 I najlepiej przygotować jakiś POC, czyli prosty kawałek kodu, na którym zobaczymy wynik 😉

      Krzysiek Kijas Krzysiek Kijas
      1. Hej hej,
        Dzięki za odpowiedź super czyli nie jest to całkowicie bad practice ale lepiej uważać na asercjowanie innych niż główne elementy – dzięki za odpowiedź,

        Pozdrawiam i spokojności życzę,
        Jakub K

        Avatar Jakub Kruszyński
  4. Hej hej,
    Mam pytanie – jest projekt na kilku środowiskach – z tego co kojarzę użycie globalnie url’a do projektu jest spoko jeśli podstawa adresu się nie zmienia a co z puszczaniem testów na różnych środowiskach, gdzie adres url na dane środo jest inny na każdym ze środowisk – czy wtedy używać base url tylko dodawać ifa w hook’u, czy duplikować pliki z kodem pod każde środowisko yżywając innego baseURL w zależności od np wybranej zmiennej w teście – przygotowane w playwright.config.json np baseURL, baseURL2 itd czy jest jakieś inne prostrze i nie wymagające duplikowania testów rozwiązanie które oferuje playwright??

    Pozdrawiam i dzięki z góry za odpowiedź,
    Jakub K

    Avatar Jakub Kruszyński
  5. Hej, mam pewien problem z uruchomieniem testów z poziomu konsoli:
    ‘npx playwright test tests/login.spec.ts’

    Przy każdej próbie otrzymuję błąd:
    “Error: page.goto: Protocol error (Page.navigate): Cannot navigate to invalid URL
    Call log:
    – navigating to “/”, waiting until “load””

    Ustawiłem zmienną baseURL w pliku playwright.config.ts podmieniając w beforeEach zmienną url w metodzie goto na: await page.goto('/');

    Powyższy problem nie występuje gdy uruchamiam testy z poziomu IDE przy użyciu wtyczki.

    Avatar Marek
    1. Hmm wygląda na to, że już działa.
      Nie wiem na ile to pomogło ale uruchomiłem testy poprzez skrypt:
      npm run test i wszystko przeszło.
      Od tamtej pory uruchamiam już testy: ‘npx playwright test tests/login.spec.ts’ i działa.
      Trochę martwi ta stabilność…

      Avatar Marek
      1. Hej,
        Może miałeś jakiś niezapisany plik?
        Również pytanie jak dokładnie wyglądał Twój kod, czy nie było tam dodatkowego “/” w adresie?
        Przy automatyzacji i konfiguracji trzeba kilka rzeczy przypilnować – jednak najważniejsze, że obecnie działa 🙂
        Daj prosze znać jakbyś miał jeszcze jakies problemy 🙂

        Krzysiek Kijas Krzysiek Kijas
  6. Hej

    Mam pytanie jak zrobi, żeby na moim trace viewer wydoczne były te znaczki “>” które dają opcje rozwinięcia danego kroku?

    Moment o którym mówię, występuje w tej lekcji w 22:41, gdy Przemek rozwija sobie hook beforeEach i ma podgląd na kod, ja nie mam takiej możliwości, i znak > mam tylko przy beforeEach ale jak go rozwijam to nie widze kodu 🙁

    P.S. Przydałaby się możliwość wklejania niewielkich screenów w komentarzach 🙂

    Avatar Franciszek Klocek
    1. Fajne pytanie – obecnie już nie ma możliwości bezpośrednio w raporcie podglądnąć kodu z danych akcji.
      Takie informacje są zawarte w podglądzie Trace Viewer (w obecnym kodzie pojawia się tylko w przypadku faila testu) lub z pomocą UI mode (otwieranego npx playwright test --ui)
      Tutaj przyznam, że twórcy wprowadzają wiele zmian, nie zawsze na plus🫡

      Co do obrazków w komentarzach to niestety nasza obecna platforma nie ma wsparcia ale śmiało przyjmie linki z dowolnego serwisu gdzie takie obrazki można bezkarnie wklejać.

      Przemek Przemek
      1. Hej, dzięki za odpowiedź. Tak się właśnie domyślałem, że przypuszczalnie brak podglądu to wynik zmian w Playwright, ale wolałem się upewnić 🙂

        fajny pomysł, na przyszłość, będę uploadował i podrzucał link 🙂

        Avatar Franciszek Klocek
  7. Cześć, czy możemy w jakiś prosty sposób wyłączyć użycie beforeEach dla jednego testu, który jest w zestawie. Jednocześnie chcemy, żeby ten test był zawarty w danym zestawie testów. W skrócie chodzi o to, że dla jednego testu chcielibyśmy użyć innych danych do logowania 🙂

    Avatar Paulina Gruca
    1. Hej,
      Są przynajmniej 2 sposoby 🙂
      Dużo zależy co dokładnie chcesz osiągnąć oraz jak wyglądają Twoje testy.

      Sposób pierwszy: odpowiednia hierarchia describe oraz test:

      import { test } from '@playwright/test';
      
      test.describe('🟦 Sample test suit', () => {
          test.beforeEach(async ({ page }) => {
              console.log('🟦 Before each');
          });
      
          test('test 1', async ({ page }) => {
              console.log('🟦 test 1');
          });
      
          test.describe('🟧 Inner sample test suit', () => {
              test.beforeEach(async ({ page }) => {
                  console.log('🟧 Before each');
              });
      
              test('test 2', async ({ page }) => {
                  console.log('🟧 test 2');
              });
          });
      });
      

      W rezultacie otrzymamy całość w takiej kolejności:

      [chromium-non-logged]  🟦 Sample test suit › 🟧 Inner sample test suit › test 2
      🟦 Before each
      🟧 Before each
      🟧 test 2
      [chromium-non-logged]  🟦 Sample test suit › test 1
      🟦 Before each
      🟦 test 1
        2 passed (2.5s)
      

      Sposób drugi: warunki w beforeEach. Poniżej pomijamy beforeEach przed testem o nazwie “test 2”:

      test.describe.only('🟦 Sample test suit', () => {
          test.beforeEach(async ({ page }, testInfo) => {
              if (testInfo.title === 'test 2') {
                  return;
              }
              console.log('🟦 Before each');
          });
      
          test('test 1', async ({ page }) => {
              console.log('🟦 test 1');
          });
      
          test('test 2', async ({ page }) => {
              console.log('🟧 test 2');
          });
      });
      

      A na konsoli otrzymamy:

      [chromium-non-logged]  🟦 Sample test suit › test 2
      🟧 test 2
      [chromium-non-logged]  🟦 Sample test suit › test 1
      🟦 Before each
      🟦 test 1
      
      Krzysiek Kijas Krzysiek Kijas
      1. Super, bardzo dziękuję za odpowiedź i gotowe rozwiązania. Ten drugi sposób już przetestowałam w praktyce i zadziałało od razu 🙂 nie wiem jeszcze na ile tego typu rozwiązania sprawdzają się w komercyjnych, dużych projekcie (w firmie jesteśmy na dość wczesnym etapie wdrażania testów automatycznych), ale na teraz bardzo się przydało. Jeszcze raz dzięki!

        Avatar Paulina Gruca
        1. Osobiście sugerowałbym pierwsze – pozwala dodatkowo na grupowanie testów w zagnieżdżone

           ;) 
          Co do rozwiązania z [js]if (testInfo.title === 'test 2') {

          – ma jeden poważny minus – opiera się na nazwie testów. Jednak można je wykorzystać, gdy w testach wprowadzimy tagi ( https://playwright.dev/docs/test-annotations#tag-tests ), czyli w nazwie testu dodamy np "@high" czy "@low" (np. w kontekście priorytetów). Wtedy w takim Before możemy zastosować daną akcję jedynie w kontekście testów z danym tagiem:
          if (testInfo.title.includes("@high")) {

          Jedno i drugie rozwiązanie ma swoje wady i zalety – wszystko zależy od kontekstu i potrzeb 😉

          Krzysiek Kijas Krzysiek Kijas
  8. 1) [chromium] › desktop.spec.ts:36:5 › successful mobile top-up ──────────────────────────────────

    Test timeout of 50000ms exceeded.

    Error: locator.selectOption: Target closed
    =========================== logs ===========================
    waiting for locator(‘#uniform-widget_1_topup_receiver’)

    prośba o wyjaśnienie 🙂 zminiłam timeout na 5000 ale pomimo tego jakoś długo szuka

    Avatar Karolina Zakrzewska
      1. import { test, expect } from '@playwright/test';
        
        test.describe('Desktop tests', () => {
          test.beforeEach(async ({ page }) => {
            const userId = 'testerLO';
            const userPassword = '10987654';
            const url = 'https://demo-bank.vercel.app/';
            await page.goto(url);
            await page.getByTestId('login-input').fill(userId);
            await page.getByTestId('password-input').fill(userPassword);
            await page.getByTestId('login-button').click();
          });
        
        
          test('quick payment with correct data', async ({ page }) => {
            // Arrange
            const receiverId = '2';
            const transferAmount = '150';
            const transferTitle = 'pizza';
            const expectedTransferReceiver = 'Chuck Demobankowy';
        
            // Act
            await page.locator('#widget_1_transfer_receiver').selectOption(receiverId);
            await page.locator('#widget_1_transfer_amount').fill(transferAmount);
            await page.locator('#widget_1_transfer_title').fill(transferTitle);
            await page.getByRole('button', { name: 'wykonaj' }).click();
            await page.getByTestId('close-button').click();
        
            // Assert
            await expect(page.locator('#show_messages')).toHaveText(
              `Przelew wykonany! ${expectedTransferReceiver} - ${transferAmount},00PLN - ${transferTitle}`,
            );
          });
        });
        
        test.only('successful mobile top-up', async ({ page }) => {
          // Arrange
          const topUpReceiver = '500 xxx xxx';
          const topUpAmount = '50';
          const exprectedMessage = `Doładowanie wykonane! ${topUpAmount},00PLN na numer ${topUpReceiver}`;
        
          // Act
          await page.locator('#widget_1_topup_receiver').selectOption(topUpReceiver);
          await page.locator('#widget_1_topup_amount').fill(topUpAmount);
          await page.locator('#uniform-widget_1_topup_agreement span').click();
          await page.getByRole('button', { name: 'doładuj telefon' }).click();
          await page.getByTestId('close-button').click();
        
          // Assert
          await expect(page.locator('#show_messages')).toHaveText(exprectedMessage);
        });
        

        Tu wynik z test viewera:

        successful mobile top-up
        desktop.spec.ts:36
        
        Test timeout of 30000ms exceeded.
        Error: locator.fill: Target closed
        =========================== logs ===========================
        waiting for locator('#widget_1_topup_amount')
        ============================================================
        
          43 |   await page.locator('#widget_1_topup_receiver').selectOption(topUpReceiver);
          44 |   await page.locator('#widget_1_topup_amount').fill(topUpAmount);
        > 45 |   await page.locator('#uniform-widget_1_topup_agreement span').click();
             |                                                ^
          46 |   await page.getByRole('button', { name: 'doładuj telefon' }).click();
          47 |   await page.getByTestId('close-button').click();
          48 |
        
            at C:\Projects\demo-bank-tests\tests\desktop.spec.ts:45:48
        Pending operations:
          - locator.fill at tests\desktop.spec.ts:45:48
        
        Test Steps
        1.0s OK Before Hooks
        29.8s X locator.fill(#widget_1_topup_amount)— desktop.spec.ts:45 
        3.2s OK After Hooks
        
        Avatar Karolina Zakrzewska
        1. video jest białe – przez 29 s trwania

          Trace:
          
          Call:
          locator.fill: Target closed
          =========================== logs ===========================
          waiting for locator('#widget_1_topup_amount')
          ============================================================
          
          Avatar Karolina Zakrzewska
        2. test ‘successful mobile top-up’ jest poza describe wiec beforeEach czyli nawigacja i logowanie sie nie wykonuje. Zastanawiajace jest jednak czemu sie nie sypie na linijce 43 tylko na linijce 44

          Avatar Tomasz Solarz
          1. Fakt, zastanawiające, chociaż u mnie na wersji Playwright 1.38.1 błąd leci właśnie na linii 43:

                  42 |   // Act
                > 43 |   await page.locator('#widget_1_topup_receiver').selectOption(topUpReceiver);
                     |                                                  ^
                  44 |   await page.locator('#widget_1_topup_amount').fill(topUpAmount);
                  45 |   await page.locator('#uniform-widget_1_topup_agreement span').click();
                  46 |   await page.getByRole('button', { name: 'doładuj telefon' }).click();
            

            Więc obstawiałbym, że może coś w tamtej wersji Playwrighta mogło być zepsute 🤔

            Krzysiek Kijas Krzysiek Kijas

Dodaj komentarz

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