Zapisy otwarte! Dołącz do kursu Selenium w Javie lub Selenium w C#. Tylko do 23.09.2021 do godz. 21:00. Zapisz się tutaj.

Selenium 39. Zadanie: czekanie na warunki

Czas przećwiczyć to, co przerobiliśmy wspólnie w kilku ostatnich filmach. Przed Tobą zadanie, w którym użyjesz klasy WebDriverWait.

Na początku filmu tłumaczę polecenie, a następnie rozwiązanie. Będzie moment żeby zatrzymać film na czas wykonania zadania – dam znać w filmie kiedy.

Podpowiedź

Najlepiej jeżeli od początku ustawisz wielkość okna przeglądarki na 1295×760 za pomocą poniższej metody umieszczonej w setupie testu (metodzie z adnotacją @BeforeEach):

driver.manage().window().setSize(new Dimension(1295, 760));

Przy innych wielkościach test może zachowywać się trochę inaczej. Po więcej szczegółów sprawdź sekcję komentarzy pod tą lekcją.

Polecenie do zadania

Ukryta treść

Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.

Rozwiązanie

Lepiej nie podglądać przed rozwiązaniem zadania ⚠️

Ukryta treść

Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.

Wsparcie merytoryczne

Nie masz dostępu do wsparcia merytorycznego dla tego kursu. Wykup dostęp albo zaloguj się, by móc zadawać pytania.

  1. Hej 🙂
    Gdy próbuję odpalić test usuwania dodanego kuponu, to często rzuca mi na przemian błędami, że albo button do usuwania kuponu nie jest klikalny, albo że właśnie liczba elementów div.blockUI nie jest większa od 0.
    Jak obsłużyć sytuację, w której elementy div.blockUI pojawią się i znikną jeszcze zanim nasz test zacznie je zliczać? Bo mam wrażenie, że to szybkość działania testu albo łącza internetowego może być przyczyną tego problemu. Ale może jednak coś innego, na co jeszcze nie wpadłem 😛
    Wydaje mi się, że mam identyczną składnię kodu jak ta przedstawiona w filmie, nie znalazłem żadnych różnic.

    Odpowiedz
      • Cześć, ja mam właśnie taki problem, tj. rzuca mi ElementClickInterceptedException przy czekaniu na elementToBeClickable ;D. Ale nie zawsze, generalnie mam problem z ogarnięciem stabilności tych testów. Często też wywala się waitForProcessingEnd, bo nie może doczekać się aż liczba elementów .processing będzie > 0, tak jakby ładowanie kończyło się jeszcze zanim selenium policzy je poraz pierwszy.
        (skopiowałem Twój kod)

        Odpowiedz
  2. Hej 🙂 Dzięki za kod, myślę że to dobry pomysł, byśmy mogli mieć do niego wgląd, w razie potrzeby 🙂 Udało mi się chyba znaleźć przyczynę błędów. W filmiku poradziłaś, żeby wysokość okna była większa od 760, ale wydaje mi się, że dokładniej rzecz biorąc, kluczem jest zachowanie odpowiedniej proporcji między wysokością a szerokością okna. Bo w moim przypadku, testy przy rozmiarach okna 1295x760 i 1295x800 działały prawidłowo, ale już przy ustawieniu 1295x900 albo 1295x960 test na usuwanie kuponu się wysypywał 🙂

    Odpowiedz
  3. Hej! W sprawie tego podwójnego wpisywania kuponu i czekania aż 'kręciołek' zniknie.
    Tobie wyskoczył komunikat błędu z elementem i klasą, które mogłaś wykorzystać, ale mi cały czas wyskakuje komunikat: stale element reference: element is not attached to the page document , z którego nic wyciągnąć się nie da. Co w takiej sytuacji?

    Odpowiedz
  4. Hej, mam podobny kłopot do tego który ma Magdalena, lecz u mnie pojawia się on wcześniej - w odniesieniu do pola tekstowego do wpisania kuponu. Na zmianę (nie wiem dlaczego) rzuca mi następującymi wyjątkami:

    1) org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document, albo
    2) org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"input[name='coupon_code']"} (Session info: chrome=83.0.4103.61)

    Mój kod:

    package DriverMethods;
    import org.junit.jupiter.api.AfterEach;
    import org.junit.jupiter.api.Assertions;
    import org.junit.jupiter.api.BeforeEach;
    import org.junit.jupiter.api.Test;
    import org.openqa.selenium.*;
    import org.openqa.selenium.chrome.ChromeDriver;
    import org.openqa.selenium.support.ui.ExpectedConditions;
    import org.openqa.selenium.support.ui.WebDriverWait;
    import java.util.concurrent.TimeUnit; 
    
    public class WaitsExcercise {
        WebDriver driver;
        WebDriverWait wait; 
    
        By cookieConsentBar = By.cssSelector("a[class*='dismiss-link']");
        By windSurfingGroup = By.cssSelector("a[href*='windsurfing']");
        By productEgipt = By.xpath(".//h2[text()='Egipt – El Gouna']");
        By addToCartButton = By.cssSelector("button[name='add-to-cart']");
        By goToCartButton = By.cssSelector("a.cart-contents");
        By addCoupon = By.cssSelector("button[name='apply_coupon']");
        String validCoupon = "10procent";
        String invalidCoupon = "invalidCoupon"; 
    
        @BeforeEach
        public void driverSetup() {
            System.setProperty("webdriver.chrome.driver", "src/main/resources/chromedriver.exe");
            driver = new ChromeDriver();
            driver.manage().window().setSize(new Dimension(1295, 760));
            driver.manage().window().setPosition(new Point(10, 40));
            driver.manage().timeouts().pageLoadTimeout(50, TimeUnit.SECONDS);
            driver.navigate().to("https://fakestore.testelka.pl/"); 
    
            wait = new WebDriverWait(driver, 10); 
    
            driver.findElement(cookieConsentBar).click();
            driver.findElement(windSurfingGroup).click();
            driver.findElement(productEgipt).click();
            driver.findElement(addToCartButton).click();
            driver.findElement(goToCartButton).click();
        }
    
        @AfterEach
        public void driverQuit() {
            driver.close();
            driver.quit();
        } 
    
        @Test
        public void validCouponTest() {
            applyCoupon(validCoupon);
        }
    
        private void applyCoupon(String coupon) {
            By couponCodeField = By.cssSelector("input[name='coupon_code']");
            By applyCouponButton = By.cssSelector("button[name='apply_coupon']");
            driver.findElement(couponCodeField).sendKeys(coupon);
            driver.findElement(applyCouponButton).click();
        }
    }
    

    Natomiast gdy odpalam ten sam kod w debug'u krok po kroku, wtedy poprawnie znajduje couponCodeField i działa.
    Próbowałem skorzystać z Twojej rady by wrzucić to w pętle i po wykonaniu kodu wciąż rzuca którymś z wyjątków (w przypadku unable to locate element wrzucałem mu wtedy w pętli catch (NoSuchElementException e)).

    Poniżej screen ukazujący jak to wygląda w debug'u:
    https://snipboard.io/ExvDL7.jpg
    Na chwilę udało mi się to zmitygować wrzucając do metody applyCoupon thread.sleep, ale po paru godzinach przestało działać i jestem w punkcie wyjścia, dalej rzuca tymi samymi wyjątkami.

    Wszystkie opisane powyżej sytuacje również powtarzają się gdy odpalam Twój kod.

    Mam jeszcze 2 pytania:

    1) W odpowiedzi do komentarza Magdy napisałaś w odniesieniu do org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document, że trzeba wyciągnąć z konsoli informacje o elemencie którego to dotyczy. Czy masz na myśli przeszukanie internal calls, jak na screenie poniżej? Jeżeli tak, tu tej informacji nie ma :(. Przyczynę ustaliłem dopiero gdy odpalałem kod w debug'u krok po kroku i obserwowałem działanie chrome'a. Później dopiero IntelliJ zaczął rzucać wyjątkiem NoSuchElementException gdzie już wskazany jest css, który według niego nie mógł zostać znaleziony.

    2) Gdy uruchomię kod w debug'u tak jak na screenie pierwszym, wtedy tylko za pierwszym razem kod wykonywany jest krok po kroku tak jak bym chciał. Każdym następnym razem jak odpale debug validCouponTest() wówczas cały kod wykonuje się tak jakbym zrobił run test. Co robię źle?

    Odpowiedz