Poczekaj na załadowanie strony w Selenium

240

Jak sprawić, by Selenium 2.0 czekał na załadowanie strony?

Karthick Kumar
źródło
7
Dla mnie tylko odpowiedź Paula wygląda na poprawną, większość wysoko głosowanych odpowiedzi mówi o czekaniu na określony element.
xyz

Odpowiedzi:

138

Możesz także sprawdzić załadowany pagel za pomocą następującego kodu

IWait<IWebDriver> wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver, TimeSpan.FromSeconds(30.00));

 wait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));
Imran
źródło
22
Można by pomyśleć, że coś takiego byłoby wbudowane. Oczekiwanie na ładowanie strony to dość powszechna sprawa w Internecie.
PRMan
19
czy to naprawdę działa cały czas? Może brakuje mi czegoś w kodzie, ale czekasz na gotowość domeny. Należy jednak wziąć pod uwagę, że jeśli kod zostanie wykonany zbyt szybko, poprzednia strona może nie zostać jeszcze zwolniona i zwróci wartość true, nawet jeśli nadal znajdujesz się na starej stronie. Musisz tylko poczekać na rozładowanie bieżącej strony, a następnie wywołać powyższy kod. Sposobem wykrycia rozładowania strony jest uzyskanie elementu WWW na bieżącej stronie i poczekanie, aż stanie się nieaktualna. obeythetestinggoat.com/…
George
6
Do Twojej wiadomości - Nawet powyższe nie gwarantuje, że strona jest kompletna - po prostu, że dom jest gotowy. Każde dojo / jquery może nadal dynamicznie budować elementy na stronie, więc przed interakcją może być konieczne poczekanie na elementy dynamiczne.
George,
3
Należy pamiętać, że ta metoda sprawdza tylko DOM. Jeśli używasz Ajax lub AngularJS, to nie zadziała, ponieważ będą pewne wywołania asynchroniczne, które nie będą mogły zostać wykryte przez document.readyState.
Homewrecker
3
To jest kod C #. To nie działa z Javą i pytaniem o Javę .
Kingamere
89

Użyj klasy WebDriverWait

Zobacz także tutaj

Możesz spodziewać się pokazać jakiś element. coś jak w C #:

WebDriver _driver = new WebDriver();
WebDriverWait _wait = new WebDriverWait(_driver, new TimeSpan(0, 1, 0));

_wait.Until(d => d.FindElement(By.Id("Id_Your_UIElement"));
Artem
źródło
To działało świetnie. To bardzo fajny nowoczesny sposób na rozwiązanie problemu.
CrazyDart,
3
@ EmmanuelAngelo.R TimeSpan to struktura danych .Net.
rjzii
12
co jeśli nie wiem, który element będzie na stronie?
JustGoscha,
3
Będzie to działać w oczekiwaniu na załadowanie określonego elementu, a nie na całą stronę.
xyz
1
Nie gwarantuje to wcale, że element zostanie w pełni załadowany, ani nie odpowie na pytanie. Jak ktokolwiek może głosować na to?
Boris D. Teoharov,
36

Jeśli ustawisz ukryte oczekiwanie sterownika, a następnie wywołasz findElementmetodę na elemencie, który ma znajdować się na ładowanej stronie, WebDriver będzie sondował ten element, aż znajdzie element lub osiągnie wartość limitu czasu.

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

źródło: niejawne-czeka

Sam
źródło
3
Nie pomoże w oczekiwaniu na załadowanie strony.
xyz
Oznacza to, że spróbuje czegoś w ciągu 10 sekund, zanim zgłosi wyjątek. więc nie może upewnić się, że zajmie to 10 sekund opóźnienia.
skysign
1
@xyz - dlaczego to nie pomoże?
MasterJoe2,
@ testerjoe2 czeka, aż zostanie znaleziony określony element, pytanie dotyczy sposobu oczekiwania na załadowanie strony.
xyz
35

Ogólnie rzecz biorąc, w Selenium 2.0 sterownik sieci powinien zwracać kontrolę nad kodem wywołującym dopiero po stwierdzeniu, że strona została załadowana. Jeśli tak się nie stanie, możesz zadzwonić waitforelemement, który cyklicznie dzwoni findelementdo momentu znalezienia lub przekroczenia limitu czasu (można ustawić limit czasu).

Paul Hadfield
źródło
2
Dodanie do odpowiedzi Pawła. Proszę sprawdzić również stackoverflow.com/questions/5858743/... .
9ikhan
27
Niestety, Selenium 2 nie zawsze czeka na załadowanie strony. Na przykład WebElement: click () nie czeka i jest to wyraźnie powiedziane w należącym do Javadoc. Nie mówią jednak, jak mogę sprawdzić, czy można załadować nową stronę. If click() causes a new page to be loaded via an event or is done by sending a native event (which is a common case on Firefox, IE on Windows) then the method will not wait for it to be loaded and the caller should verify that a new page has been loaded.
Sebi
Z dokumentu ... a metoda będzie blokować, aż ładowanie się zakończy ...
xyz
2
@Karna: Tak, teoretycznie powinno tak być zawsze, aw praktyce tak było przez większość czasu. Używanie Selenium w tamtym czasie podkreśliło, że czasami zdawało się, że strona skończyła się ładować, ale tak się nie stało. Ostatnio nie używałem selenu, więc może tak być, ale nie musi tak być.
Paul Hadfield
3
Zgadzam się: szczególnie sterownik przeglądarki internetowej jest błędny i w niektórych przypadkach natychmiast zwraca kontrolę, nawet jeśli strona wciąż się ładuje. W moim przypadku dodałem opcję „czekaj” JavascriptExecutor, czekając, aż „document.readyState” będzie „kompletny”. Ze względu na podróż w obie strony z selenu do przeglądarki, wydaje mi się, że warunki wyścigu są złagodzone, a to „zawsze” działa dla mnie. Po „click ()”, kiedy oczekuję załadowania strony, jawnie czekam (za pomocą WebDriverWait) na readystate. ]
dmansfield
22

Implementacja Ruby:

wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until {
    @driver.execute_script("return document.readyState;") == "complete" 
}
allenhwkim
źródło
17
Odpowiednik w języku Python: WebDriverWait (sterownik, 10) .until (lambda d: d.execute_script ('return document.readyState') == 'complete')
blaze
2
Python używa powyższego kodu, ale nie zapomnij o tym wierszu ... | z selenium.webdriver.support.ui import WebDriverWait
t3dodson
Miałem problem z kliknięciem elementu, gdy strona nie została w pełni załadowana. W Pythonie próbowałem time.sleep (30). Zadziałało. Zawsze jednak będzie czekać maksymalnie 30 sekund. Następnie wypróbowałem następujący kod i jest on teraz bardziej wydajny, szybszy. WebDriverWait (sterownik, 10) .until (lambda d: driver.find_element_by_xpath ("// div [. = 'Administration']"). Click ())
Riaz Ladhani
20

Możesz usunąć System.outlinię. Jest dodawany do celów debugowania.

WebDriver driver_;

public void waitForPageLoad() {

    Wait<WebDriver> wait = new WebDriverWait(driver_, 30);
    wait.until(new Function<WebDriver, Boolean>() {
        public Boolean apply(WebDriver driver) {
            System.out.println("Current Window State       : "
                + String.valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState")));
            return String
                .valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState"))
                .equals("complete");
        }
    });
}
QIKHAN
źródło
Dzięki za te wskazówki. Dodaję to w moim SeleniumHelper; por. javabox
boly38
17

Wszystkie te rozwiązania są odpowiednie w określonych przypadkach, ale występują w nich co najmniej jeden z kilku możliwych problemów:

  1. Nie są wystarczająco ogólne - chcą, abyś wiedział z wyprzedzeniem, że jakiś konkretny warunek będzie spełniony na stronie, na której będziesz (np. Wyświetli się jakiś element)

  2. Są otwarci na warunki wyścigu, w których używasz elementu, który jest faktycznie obecny na starej stronie, a także na nowej stronie.

Oto moja próba ogólnego rozwiązania, które pozwala uniknąć tego problemu (w Pythonie):

Po pierwsze, ogólna funkcja „czekaj” (użyj WebDriverWait, jeśli chcesz, uważam je za brzydkie):

def wait_for(condition_function):
    start_time = time.time()
    while time.time() < start_time + 3:
        if condition_function():
            return True
        else:
            time.sleep(0.1)
    raise Exception('Timeout waiting for {}'.format(condition_function.__name__))

Następnie rozwiązanie polega na tym, że selen rejestruje (wewnętrzny) numer identyfikacyjny dla wszystkich elementów na stronie, w tym najwyższego poziomu <html> . Gdy strona się odświeża lub ładuje, otrzymuje nowy element HTML z nowym identyfikatorem.

Zakładając, że chcesz kliknąć link z tekstem „mój link”, na przykład:

old_page = browser.find_element_by_tag_name('html')

browser.find_element_by_link_text('my link').click()

def page_has_loaded():
    new_page = browser.find_element_by_tag_name('html')
    return new_page.id != old_page.id

wait_for(page_has_loaded)

Aby uzyskać więcej Pythonicznego, wielokrotnego użytku, ogólnego pomocnika, możesz utworzyć menedżera kontekstu:

from contextlib import contextmanager

@contextmanager
def wait_for_page_load(browser):
    old_page = browser.find_element_by_tag_name('html')

    yield

    def page_has_loaded():
        new_page = browser.find_element_by_tag_name('html')
        return new_page.id != old_page.id

    wait_for(page_has_loaded)

A potem możesz go używać do praktycznie każdej interakcji selenu:

with wait_for_page_load(browser):
    browser.find_element_by_link_text('my link').click()

Myślę, że to kuloodporne! Co myślisz?

Więcej informacji w poście na ten temat tutaj

hwjp
źródło
Przeczytałem twoją stronę, zanim ponownie szukałem kodu Java, który implementuje twoje rozwiązanie. Do tej pory nic ...
Andrew Lorien
11

Możesz także użyć klasy: ExpectedConditions aby jawnie poczekać, aż element pojawi się na stronie, zanim będziesz mógł podjąć jakiekolwiek działania dalsze działania

Możesz użyć tej ExpectedConditionsklasy do ustalenia, czy element jest widoczny:

WebElement element = (new WebDriverWait(getDriver(), 10)).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("input#houseName")));

Zobacz ExpectedConditions class Javadoclistę wszystkich warunków, które możesz sprawdzić.

TedEd
źródło
11

Odpowiedź Imrana zmieniona dla Java 7:

    WebDriverWait wait = new WebDriverWait(driver, 30);

    wait.until(new ExpectedCondition<Boolean>() {
        public Boolean apply(WebDriver wdriver) {
            return ((JavascriptExecutor) driver).executeScript(
                "return document.readyState"
            ).equals("complete");
        }
    });
Płetwa
źródło
10

To wydaje się być poważnym ograniczeniem WebDriver. Oczywiście oczekiwanie na element nie będzie oznaczało załadowania strony, w szczególności DOM może zostać w pełni zbudowany (stan już gotowy), w którym JS nadal działa, a CSS i obrazy są ładowane.

Uważam, że najprostszym rozwiązaniem jest ustawienie zmiennej JS na zdarzenie onload po zainicjowaniu wszystkiego i sprawdzenie i oczekiwanie na tę zmienną JS w Selenium.

sibidiba
źródło
To proste, jeśli witryna jest do zmodyfikowania!
reinierpost
Tak, wystarczy użyć JavascriptExecutor, aby uruchomić jQuery.js, a następnie masz dostęp do zdarzeń ładowania jQuery. Jest to rzadki przypadek, gdy jest to konieczne. Standardowy Webdriver ma wystarczającą moc, aby wykonać 98% prawidłowych oczekiwań.
djangofan
@djangofan byłby niesamowity, widząc przykład tego ... Jestem facetem z przodu, więc nie jestem pewien, gdzie i jak używany jest JavaScriptExecutor.
BradGreens
@BradGreens - Ok, spójrz na mój projekt tutaj: github.com/djangofan/jquery-growl-selenium-example . Jeśli masz przepustowość do ukończenia tego przykładu, nie mogłem do końca zmusić jGrowl do pracy w tym projekcie testowym, chociaż jQuery działa dobrze.
djangofan
1
@BradGreens Oprócz komentarza djangofana zobacz moją odpowiedź tutaj: stackoverflow.com/a/24638792/730326
jmathew
9

Jeśli chcesz poczekać na załadowanie określonego elementu, możesz użyć isDisplayed()metody na RenderedWebElement:

// Sleep until the div we want is visible or 5 seconds is over
long end = System.currentTimeMillis() + 5000;
while (System.currentTimeMillis() < end) {
    // Browsers which render content (such as Firefox and IE) return "RenderedWebElements"
    RenderedWebElement resultsDiv = (RenderedWebElement) driver.findElement(By.className("gac_m"));

    // If results have been returned, the results are displayed in a drop down.
    if (resultsDiv.isDisplayed()) {
      break;
    }
}

(Przykład z 5-minutowego przewodnika wprowadzającego )

Tristan
źródło
4
Rok później (obecna wersja Selenium 2.23.1) RenderedWebElementinterfejs API nie ma . Jednak isDisplayed()metoda jest teraz dostępna bezpośrednio na WebElement.
Petr Janeček,
1
Sondowanie jest okropne, gdy można tego uniknąć.
reinierpost
8

Jawnie czekaj lub warunkowo czekaj w tym oczekiwaniu, aż dany warunek zostanie spełniony.

WebDriverWait wait = new WebDriverWait(wb, 60);
wait.until(ExpectedConditions.elementToBeClickable(By.name("value")));

Będzie to czekać na każdy element sieciowy przez 60 sekund.

Użyj niejawnie czekaj na czekanie każdego elementu na stronie do tego czasu.

driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);

Będzie to czekać na każdy element sieciowy przez 60 sekund.

Anuj Teotia
źródło
5

Użyj niejawnie czekaj na czekanie każdego elementu na stronie do podanego czasu.

driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);

to czeka na każdy element na stronie przez 30 sekund.

Kolejne oczekiwanie to Jawne oczekiwanie lub warunkowe oczekiwanie w tym oczekiwaniu na spełnienie określonego warunku.

WebDriverWait wait = new WebDriverWait(driver, 40);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));

W id podaj identyfikator elementu statycznego, który jest wyświetlany w sposób widoczny na stronie, zaraz po załadowaniu strony.

Kuldeep Yadav
źródło
4

Dziwi mnie, że predykaty nie były pierwszym wyborem, ponieważ zazwyczaj wiesz, z którymi elementami wejdziesz w interakcję na stronie, którą chcesz załadować. Moje podejście zawsze polegało na tworzeniu predykatów / funkcji takich jak waitForElementByID(String id)iwaitForElemetVisibleByClass(String className) , itd., A następnie wykorzystywania i ponownego wykorzystywania ich tam, gdzie ich potrzebuję, czy to do ładowania strony czy zmiany treści strony, na którą czekam.

Na przykład,

W mojej klasie testowej:

driverWait.until(textIsPresent("expectedText");

W mojej klasie testowej rodzic:

protected Predicate<WebDriver> textIsPresent(String text){
    final String t = text;
    return new Predicate<WebDriver>(){
        public boolean apply(WebDriver driver){
            return isTextPresent(t);
        }
    };
}

protected boolean isTextPresent(String text){
    return driver.getPageSource().contains(text);
}

Chociaż wydaje się, że to dużo, zajmuje się to sprawdzaniem wielokrotnie, a przedział czasu, w jakim można to sprawdzić, można ustawić wraz z ostatecznym czasem oczekiwania przed przekroczeniem limitu czasu. Ponadto użyjesz takich metod.

W tym przykładzie klasa nadrzędna zdefiniowała i zainicjowała WebDriver driveroraz WebDriverWait driverWait.

Mam nadzieję, że to pomoże.

Jack Mason
źródło
To mi pomaga! Dzięki za tę doskonałą próbkę. Dodaję to w moim SeleniumHelper; por. javabox
boly38
4

Najlepszym sposobem oczekiwania na załadowanie strony podczas korzystania z powiązań Java dla WebDriver jest użycie wzorca projektu Obiekt strony z PageFactory. Pozwala to na użycie tego, AjaxElementLocatorFactoryco to po prostu działa, jako globalne oczekiwanie na wszystkie twoje elementy. Ma ograniczenia dotyczące takich elementów, jak drop-boxy lub złożone przejścia javascript, ale drastycznie zmniejszy ilość potrzebnego kodu i przyspieszy czas testowania. Dobry przykład można znaleźć w tym blogu. Zakłada się podstawową wiedzę na temat Core Java.

http://startingwithseleniumwebdriver.blogspot.ro/2015/02/wait-in-page-factory.html

sonhu
źródło
4

Rozwiązanie NodeJS:

W Nodejs możesz to zdobyć poprzez obietnice ...

Jeśli napiszesz ten kod, możesz być pewien, że strona jest w pełni załadowana, kiedy dojdziesz do ...

driver.get('www.sidanmor.com').then(()=> {
    // here the page is fully loaded!!!
    // do your stuff...
}).catch(console.log.bind(console));

Jeśli napiszesz ten kod, będziesz nawigować, a selen zaczeka 3 sekundy ...

driver.get('www.sidanmor.com');
driver.sleep(3000);
// you can't be sure that the page is fully loaded!!!
// do your stuff... hope it will be OK...

Z dokumentacji Selenium:

this.get (url) → Nie można

Zaplanuje polecenie przejścia do podanego adresu URL.

Zwraca obietnicę, która zostanie rozwiązana po zakończeniu ładowania dokumentu .

Dokumentacja selenu (Nodejs)

Sidanmor
źródło
4

Oto wersja Java 8 najpopularniejszej obecnie odpowiedzi :

WebDriverWait wait = new WebDriverWait(myDriver, 15);
wait.until(webDriver -> ((JavascriptExecutor) myDriver).executeScript("return document.readyState").toString().equals("complete"));

Gdzie myDriverjest WebDriverobiekt (zadeklarowany wcześniej).

Uwaga : należy pamiętać, że ta metoda ( document.readyState) sprawdza tylko DOM.

Umiłowany Głupiec
źródło
4

Wywołaj poniżej Funkcja w skrypcie, to poczeka, aż strona nie zostanie załadowana za pomocą javascript

public static boolean isloadComplete(WebDriver driver)
{
    return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("loaded")
            || ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
}
Shubham Jain
źródło
Zmieniłem wartość logiczną na pustkę, ale nie działa w Chrome
nosequeweaponer
3
/**
 * Call this method before an event that will change the page.
 */
private void beforePageLoad() {
    JavascriptExecutor js = (JavascriptExecutor) driver;
    js.executeScript("document.mpPageReloaded='notYet';");
}

/**
 * Call this method after an event that will change the page.
 * 
 * @see #beforePageLoad
 * 
 *      Waits for the previous page to disappear.
 */
private void afterPageLoad() throws Exception {
    (new WebDriverWait(driver, 10)).until(new Predicate<WebDriver>() {

        @Override
        public boolean apply(WebDriver driver) {
            JavascriptExecutor js = (JavascriptExecutor) driver;
            Object obj = js.executeScript("return document.mpPageReloaded;");
            if (obj == null) {
                return true;
            }
            String str = (String) obj;
            if (!str.equals("notYet")) {
                return true;
            }
            return false;
        }
    });
}

Możesz zmienić dokument na element, w przypadku gdy zmieniana jest tylko część dokumentu.

Technika ta została zainspirowana odpowiedzią firmy Sincebasic.

Marc
źródło
3

SeleniumWaiter :

import com.google.common.base.Function;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.WebDriverWait;

public class SeleniumWaiter {

      private WebDriver driver;

      public SeleniumWaiter(WebDriver driver) {
           this.driver = driver;
      }

      public WebElement waitForMe(By locatorname, int timeout){
           WebDriverWait wait = new WebDriverWait(driver, timeout);
           return wait.until(SeleniumWaiter.presenceOfElementLocated(locatorname));
      }

      public static Function<WebDriver, WebElement> presenceOfElementLocated(final By locator) {
            // TODO Auto-generated method stub
            return new Function<WebDriver, WebElement>() {
                 @Override
                 public WebElement apply(WebDriver driver) {
                      return driver.findElement(locator);
                 }
            };
      }
 }

I do ciebie użyj :

_waiter = new SeleniumWaiter(_driver);

try {
   _waiter.waitForMe(By.xpath("//..."), 10);
} 
catch (Exception e) {
   // Error
}
tux23
źródło
3

Możesz użyć poniższej istniejącej metody, aby ustawić czas dla pageeLoadTimeout w poniższym przykładzie, jeśli ładowanie strony trwa dłużej niż 20 sekund, spowoduje to wyjątek przeładowania strony

 WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().pageLoadTimeout(20, TimeUnit.SECONDS)
Arpan Saini
źródło
2

Możesz jawnie poczekać, aż element pojawi się na stronie, zanim podejmiesz jakąkolwiek akcję (np. Element.click ())

driver.get("http://somedomain/url_that_delays_loading");
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
  .until(new ExpectedCondition<WebElement>(){
        @Override
        public WebElement apply(WebDriver d) {
        return d.findElement(By.id("myDynamicElement"));
}});

Tego użyłem w podobnym scenariuszu i działa dobrze.

anirus
źródło
myślę, że sterownik.get czeka na zakończenie funkcji onload, zanim zwróci kontrolę nad kodem, chyba że na stronie jest dużo ajax
goh
2

Mój prosty sposób:

long timeOut = 5000;
    long end = System.currentTimeMillis() + timeOut;

        while (System.currentTimeMillis() < end) {

            if (String.valueOf(
                    ((JavascriptExecutor) driver)
                            .executeScript("return document.readyState"))
                    .equals("complete")) {
                break;
            }
        }
RichardK
źródło
2

Najlepszy sposób, jaki widziałem, to wykorzystać stalenessOf ExpectedCondition, aby poczekać, aż stara strona się zepsuje.

Przykład:

WebDriver driver = new FirefoxDriver();
WebDriverWait wait = new WebDriverWait(driver, 10);

WebElement oldHtml = driver.findElement(By.tagName("html"));
wait.until(ExpectedConditions.stalenessOf(oldHtml));

Poczeka dziesięć sekund, aż stary znacznik HTML przestanie być aktualny, a następnie wyrzuci wyjątek, jeśli tak się nie stanie.

forresthopkinsa
źródło
1
starzenie się WebElement nie oznacza, że ​​ładowanie nowej strony jest zakończone.
Corey Goldberg,
Jasne, ale oznacza to, że stara strona została zakończona rozładowywaniu. Z mojego doświadczenia wynika, że ​​równie ważne jest, aby wiedzieć, kiedy stara strona została rozładowana lub czy z jakiegoś powodu została zatrzymana.
forresthopkinsa
Oczywiście zazwyczaj używam stagnacji w połączeniu z innymi testami, aby uzyskać pełny proces rozładowywania / ładowania.
forresthopkinsa
2

Używam węzła + selenium-webdriver (która wersja to teraz 3.5.0). robię to:

var webdriver = require('selenium-webdriver'),
    driver = new webdriver.Builder().forBrowser('chrome').build();
;
driver.wait(driver.executeScript("return document.readyState").then(state => {
  return state === 'complete';
}))
Yuwanlin
źródło
2

Możesz użyć czekania. w zasadzie są dwa rodzaje oczekiwania w selenie

  • Niejawne czekanie
  • Jawne czekanie

- Niejawne czekanie

Jest to bardzo proste, zobacz składnię poniżej:

driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);

- Jawne czekanie

Jawnie poczekaj lub warunkowo poczekaj, aż wystąpi podany warunek.

WebDriverWait wait = new WebDriverWait(driver, 40);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));

Można stosować inne właściwości, takie jak visblityOf(),visblityOfElement()

iamsankalp89
źródło
2

W moim przypadku wykorzystałem następujące informacje, aby poznać stan ładowania strony. W naszej aplikacji są ładowane pliki gif i słucham ich w następujący sposób, aby wyeliminować niechciany czas oczekiwania w skrypcie.

public static void processing(){ 
    WebDriverWait wait = new WebDriverWait(driver, 30);
    wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[@id='Msgpanel']/div/div/img")));
    wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//div[@id='Msgpanel']/div/div/img")));
}

Gdzie xpath lokalizuje gif w DOM HTML. Następnie możesz również wdrożyć metody działania Kliknij.

public static void click(WebElement elementToBeClicked){
    WebDriverWait wait = new WebDriverWait(driver, 45);
    wait.until(ExpectedConditions.visibilityOf(element));
    wait.until(ExpectedConditions.elementToBeClickable(element)); 
    wait.ignoring(NoSuchElementException.class).ignoring(StaleElementReferenceException.class); elementToBeClicked.click(); 
 }
Praveen
źródło
2

Człowieku, wszystkie te odpowiedzi wymagają zbyt dużo kodu. To powinno być proste, ponieważ jest dość powszechne.

Dlaczego po prostu nie wstrzyknąć prostego javascript z webdriver i sprawdzić. Jest to metoda, której używam w mojej klasie webscraper. JavaScript jest dość prosty, nawet jeśli nie znasz js.

    def js_get_page_state(self):        
    """
    Javascript for getting document.readyState
    :return: Pages state.

    More Info: https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState
    """
    ready_state = self.driver.execute_script('return document.readyState')
    if ready_state == 'loading':
        self.logger.info("Loading Page...")
    elif ready_state == 'interactive':
        self.logger.info("Page is interactive")
    elif ready_state == 'complete':
        self.logger.info("The page is fully loaded!")
    return ready_state
Bruce Wayne
źródło
1

Jak sprawić, by Selenium czekał na ładowanie strony po kliknięciu, oferuje następujące interesujące podejście:

  1. Zapisz odniesienie do WebElementze starej strony.
  2. Kliknij w link.
  3. Kontynuuj wywoływanie operacji do WebElementmomentu StaleElementReferenceExceptionwyrzucenia.

Przykładowy kod:

WebElement link = ...;
link.click();
new WebDriverWait(webDriver, timeout).until((org.openqa.selenium.WebDriver input) ->
{
    try
    {
        link.isDisplayed();
        return false;
    }
    catch (StaleElementReferenceException unused)
    {
        return true;
    }
});
Gili
źródło
Dobry pomysł! Nigdy nie myślałem o rozwiązaniu tej sytuacji, sprawdzając przeciwieństwo udanego ładowania strony, udanego rozładowania strony (z powodu braku lepszego terminu). To, czy jest to najlepsza opcja, zależy od tego, czy wyjątek StaleElementReferenceException zajmuje mniej czasu itp. Niż oczekiwanie na pomyślne załadowanie. Niemniej jednak kolejny dobry sposób na zrobienie tego.
Joseph Orlando,
4
To nie powie ci, czy bieżąca strona jest załadowana, ale powie ci, czy ostatnia strona (konkretnie jeden element) jest rozładowana . Nadal będziesz musiał czekać na załadowanie bieżącej strony. BTW, możesz zamienić swój kod powyżej na new WebDriverWait(driver, 10).until(ExpectedConditions.stalenessOf(element)).
JeffC