Selenium WebDriver: Chờ tải trang phức tạp với JavaScript


102

Tôi có một ứng dụng web để kiểm tra với Selenium. Có rất nhiều JavaScript chạy khi tải trang.
Mã JavaScript này không được viết tốt lắm nhưng tôi không thể thay đổi bất cứ điều gì. Vì vậy, chờ đợi một phần tử xuất hiện trong DOM với findElement()phương thức không phải là một tùy chọn.
Tôi muốn tạo một hàm chung trong Java để chờ tải trang, một giải pháp khả thi sẽ là:

  • chạy một biểu mẫu tập lệnh JavaScript WebDriver và lưu trữ kết quả của document.body.innerHTMLtrong một biến chuỗi body.
  • so sánh bodybiến với phiên bản trước của body. nếu chúng giống nhau thì hãy đặt số tăng một bộ đếm, ngược lại notChangedCountthì đặt notChangedCountbằng 0.
  • đợi một chút thời gian (50 ms chẳng hạn).
  • nếu trang không thay đổi trong một thời gian (ví dụ: 500 mili giây) notChangedCount >= 10thì hãy thoát khỏi vòng lặp, ngược lại, hãy lặp lại bước đầu tiên.

Bạn có nghĩ rằng đó là một giải pháp hợp lệ?


findElement () không chờ đợi - bạn có nghĩa là gì với điều đó?
Rostislav Matl

1
findElementđợi một phần tử có sẵn, nhưng đôi khi phần tử có sẵn trước khi mã javascript được khởi tạo hoàn toàn, đó là lý do tại sao nó không phải là một tùy chọn.
psadac

Tôi đã quên nó - Tôi đã quen với việc sử dụng WebDriverWait và mong đợi, nó linh hoạt hơn.
Rostislav Matl

Câu trả lời:


73

Nếu ai đó thực sự biết một câu trả lời chung và luôn có thể áp dụng được, thì câu trả lời đó sẽ được thực hiện ở khắp mọi nơi từ lâu và sẽ khiến cuộc sống của chúng ta trở nên dễ dàng hơn nhiều.

Có rất nhiều điều bạn có thể làm, nhưng mọi thứ trong số chúng đều có vấn đề:

  1. Như Ashwin Prabhu đã nói, nếu bạn biết rõ về script, bạn có thể quan sát hành vi của nó và theo dõi một số biến của nó trên windowhoặc documentv.v. Tuy nhiên, giải pháp này không dành cho tất cả mọi người và chỉ bạn mới có thể sử dụng và chỉ trên một số các trang.

  2. Giải pháp của bạn bằng cách quan sát mã HTML và xem nó có bị thay đổi hay không trong một thời gian không phải là xấu (ngoài ra, có một phương pháp để lấy HTML gốc và chưa được chỉnh sửa trực tiếp bằng cách WebDriver), nhưng:

    • Phải mất nhiều thời gian để thực sự xác nhận một trang và có thể kéo dài thời gian kiểm tra đáng kể.
    • Bạn không bao giờ biết khoảng thời gian phù hợp là gì. Tập lệnh có thể đang tải xuống thứ gì đó lớn mất hơn 500 mili giây. Có một số tập lệnh trên trang nội bộ của công ty chúng tôi mất vài giây trong IE. Máy tính của bạn có thể tạm thời thiếu tài nguyên - giả sử rằng phần mềm chống vi-rút sẽ làm cho CPU của bạn hoạt động đầy đủ, thì 500 mili giây có thể là quá ngắn ngay cả đối với các tập lệnh không đơn giản.
    • Một số kịch bản không bao giờ được thực hiện. Chúng tự gọi mình với một số độ trễ ( setTimeout()) và làm việc lặp đi lặp lại và có thể thay đổi HTML mỗi khi chúng chạy. Nghiêm túc mà nói, mọi trang "Web 2.0" đều làm được điều đó. Ngay cả Stack Overflow. Bạn có thể ghi đè các phương thức phổ biến nhất được sử dụng và coi các tập lệnh sử dụng chúng là hoàn thành, nhưng ... bạn không thể chắc chắn.
    • Điều gì sẽ xảy ra nếu tập lệnh làm điều gì đó khác ngoài việc thay đổi HTML? Nó có thể làm hàng nghìn thứ, không chỉ là một vài innerHTMLtrò vui.
  3. Có những công cụ để giúp bạn về điều này. Cụ thể là Trình nghe Tiến trình cùng với nsIWebProgressListener và một số người khác. Tuy nhiên, trình duyệt hỗ trợ cho điều này là rất kinh khủng. Firefox bắt đầu cố gắng hỗ trợ nó từ FF4 trở đi (vẫn đang tiếp tục phát triển), IE đã hỗ trợ cơ bản trên IE9.

Và tôi đoán tôi có thể sớm đưa ra một giải pháp thiếu sót khác. Thực tế là - không có câu trả lời chắc chắn về thời điểm nói "bây giờ trang đã hoàn thành" bởi vì các tập lệnh vĩnh cửu đang thực hiện công việc của chúng. Chọn một trong những phục vụ bạn tốt nhất, nhưng hãy cẩn thận với những thiếu sót của nó.


31

Cảm ơn Ashwin!

Trong trường hợp của tôi, tôi nên đợi thực thi plugin jquery trong một số phần tử .. cụ thể là "qtip"

dựa trên gợi ý của bạn, nó hoạt động hoàn hảo cho tôi:

wait.until( new Predicate<WebDriver>() {
            public boolean apply(WebDriver driver) {
                return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
            }
        }
    );

Lưu ý: Tôi đang sử dụng Webdriver 2


2
Nó cũng hoạt động rất tốt cho tôi. Trong trường hợp của tôi, một phần tử đã được sửa đổi bởi Javascript ngay sau khi trang tải xong và Selenium không mặc nhiên chờ đợi điều đó.
Noxxys

2
Predicate đến từ đâu? nhập khẩu nào ??
Amado Saladino,

@AmadoSaladino "nhập com.google.common.base.Predicate;" từ liên kết google lib ổi-15.0: mvnrepository.com/artifact/com.google.guava/guava/15.0 có phiên bản 27.0 mới hơn, bạn có thể thử nó!
Eduardo Fabricio

26

Bạn cần đợi Javascript và jQuery tải xong. Thực thi Javascript để kiểm tra xem jQuery.active0document.readyStatecomplete, có nghĩa là tải JS và jQuery là hoàn tất.

public boolean waitForJStoLoad() {

    WebDriverWait wait = new WebDriverWait(driver, 30);

    // wait for jQuery to load
    ExpectedCondition<Boolean> jQueryLoad = new ExpectedCondition<Boolean>() {
      @Override
      public Boolean apply(WebDriver driver) {
        try {
          return ((Long)executeJavaScript("return jQuery.active") == 0);
        }
        catch (Exception e) {
          return true;
        }
      }
    };

    // wait for Javascript to load
    ExpectedCondition<Boolean> jsLoad = new ExpectedCondition<Boolean>() {
      @Override
      public Boolean apply(WebDriver driver) {
        return executeJavaScript("return document.readyState")
            .toString().equals("complete");
      }
    };

  return wait.until(jQueryLoad) && wait.until(jsLoad);
}

2
Bạn không chắc chắn nếu điều này sẽ làm việc trong mỗi hoàn cảnh, nhưng nó hoạt động một điều trị đối với trường hợp sử dụng của tôi
DaveH

1
Nó cũng hoạt động với tôi nhưng có một phần khó khăn: Giả sử trang của bạn đã được tải. Nếu bạn tương tác với một phần tử [ví dụ: gửi .click () hoặc .send một số phím vào nó] và sau đó bạn muốn kiểm tra khi trang của mình xử lý xong, bạn cần thêm thời gian trễ: ví dụ: click (), sleep (0,5 giây ), đợi cho đến khi (readyState = 'hoàn thành' & jQuery.active == 0). Nếu bạn không thêm sleep, iQuery sẽ không hoạt động tại thời điểm thử nghiệm! (nó đã cho tôi một số giờ để tìm hiểu, vì vậy tôi nghĩ để chia sẻ nó)
Fivos Vilanakis

document.readyState == 'complete' && jQuery.active == 0hoạt động tuyệt vời nhưng có cái gì đó tương tự cho React không? Vì những lần kiểm tra đó sẽ không bắt vẫn tải dữ liệu / thành phần phản ứng?
Rain9333

10

Thư viện JS có định nghĩa / khởi tạo bất kỳ biến nổi tiếng nào trên cửa sổ không?

Nếu vậy, bạn có thể đợi biến xuất hiện. Bạn có thể dùng

((JavascriptExecutor)driver).executeScript(String script, Object... args)

để kiểm tra điều kiện này (giống như window.SomeClass && window.SomeClass.variable != null:) và trả về một boolean true/ false.

Kết thúc điều này trong một WebDriverWaitvà đợi cho đến khi tập lệnh trả về true.


7

Tôi đã có một vấn đề tương tự. Giải pháp này phù hợp với tôi từ WebDriverDoku:

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

http://www.seleniumhq.org/docs/04_webdriver_advanced.jsp


cảm ơn bạn. Mã có trong liên kết phù hợp với tôi,
ecamur

7

Nếu tất cả những gì bạn cần làm là đợi html trên trang trở nên ổn định trước khi cố gắng tương tác với các phần tử, bạn có thể thăm dò ý kiến ​​DOM theo định kỳ và so sánh kết quả, nếu các DOM giống nhau trong thời gian thăm dò nhất định, bạn vàng. Một cái gì đó như thế này trong đó bạn vượt qua thời gian chờ tối đa và thời gian giữa các cuộc thăm dò trang trước khi so sánh. Đơn giản và hiệu quả.

public void waitForJavascript(int maxWaitMillis, int pollDelimiter) {
    double startTime = System.currentTimeMillis();
    while (System.currentTimeMillis() < startTime + maxWaitMillis) {
        String prevState = webDriver.getPageSource();
        Thread.sleep(pollDelimiter); // <-- would need to wrap in a try catch
        if (prevState.equals(webDriver.getPageSource())) {
            return;
        }
    }
}

1
Tôi muốn lưu ý ở đây rằng tôi đã ghi nhật ký thời gian để thăm dò ý kiến ​​một trang kích thước trung bình hai lần, sau đó so sánh các chuỗi đó trong java và mất hơn 20ms một chút.
TheFreddyKilo

2
Lúc đầu, tôi thấy đây là một giải pháp bẩn, nhưng nó có vẻ hoạt động tốt và nó không liên quan đến việc thiết lập các biến phía máy khách. Một lưu ý có thể là một trang liên tục được thay đổi bởi javascript (tức là đồng hồ javascript) nhưng tôi không có điều đó để nó hoạt động!
Peter

4

Đoạn mã dưới đây hoạt động hoàn hảo trong trường hợp của tôi - trang của tôi chứa các tập lệnh java phức tạp

public void checkPageIsReady() {

  JavascriptExecutor js = (JavascriptExecutor)driver;


  //Initially bellow given if condition will check ready state of page.
  if (js.executeScript("return document.readyState").toString().equals("complete")){ 
   System.out.println("Page Is loaded.");
   return; 
  } 

  //This loop will rotate for 25 times to check If page Is ready after every 1 second.
  //You can replace your value with 25 If you wants to Increase or decrease wait time.
  for (int i=0; i<25; i++){ 
   try {
    Thread.sleep(1000);
    }catch (InterruptedException e) {} 
   //To check page ready state.
   if (js.executeScript("return document.readyState").toString().equals("complete")){ 
    break; 
   }   
  }
 }

Nguồn - Cách chờ trang tải / sẵn sàng trong Selenium WebDriver


2
Bạn nên sử dụng chờ đợi selen thay vì những vòng
cocorossello

4

Hai điều kiện có thể được sử dụng để kiểm tra xem trang có được tải hay không trước khi tìm thấy bất kỳ phần tử nào trên trang:

WebDriverWait wait = new WebDriverWait(driver, 50);

Sử dụng dưới đây readyState sẽ đợi cho đến khi tải trang

wait.until((ExpectedCondition<Boolean>) wd ->
   ((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete"));

Bên dưới JQuery sẽ đợi cho đến khi dữ liệu chưa được tải

  int count =0;
            if((Boolean) executor.executeScript("return window.jQuery != undefined")){
                while(!(Boolean) executor.executeScript("return jQuery.active == 0")){
                    Thread.sleep(4000);
                    if(count>4)
                        break;
                    count++;
                }
            }

Sau những JavaScriptCode này, hãy thử tìm kiếm trên webElement.

WebElement we = wait.until(ExpectedConditions.presenceOfElementLocated(by));

1
Selenium cũng thực hiện điều này theo mặc định, điều này sẽ chỉ bổ sung thêm một thời gian thực thi mã kịch bản của bạn (có thể có đủ thời gian cho những thứ khác để tải, nhưng sau đó một lần nữa có thể không)
Ardesco

2

Tôi đã yêu cầu các nhà phát triển của mình tạo một biến JavaScript "isProcessing" mà tôi có thể truy cập (trong đối tượng "ae") mà họ đặt khi mọi thứ bắt đầu chạy và xóa khi mọi thứ hoàn tất. Sau đó, tôi chạy nó trong một bộ tích lũy kiểm tra nó sau mỗi 100 mili giây cho đến khi nó đạt được năm liên tiếp với tổng cộng 500 mili giây mà không có bất kỳ thay đổi nào. Nếu 30 giây trôi qua, tôi ném ra một ngoại lệ bởi vì điều gì đó đáng lẽ đã xảy ra vào lúc đó. Đây là trong C #.

public static void WaitForDocumentReady(this IWebDriver driver)
{
    Console.WriteLine("Waiting for five instances of document.readyState returning 'complete' at 100ms intervals.");
    IJavaScriptExecutor jse = (IJavaScriptExecutor)driver;
    int i = 0; // Count of (document.readyState === complete) && (ae.isProcessing === false)
    int j = 0; // Count of iterations in the while() loop.
    int k = 0; // Count of times i was reset to 0.
    bool readyState = false;
    while (i < 5)
    {
        System.Threading.Thread.Sleep(100);
        readyState = (bool)jse.ExecuteScript("return ((document.readyState === 'complete') && (ae.isProcessing === false))");
        if (readyState) { i++; }
        else
        {
            i = 0;
            k++;
        }
        j++;
        if (j > 300) { throw new TimeoutException("Timeout waiting for document.readyState to be complete."); }
    }
    j *= 100;
    Console.WriteLine("Waited " + j.ToString() + " milliseconds. There were " + k + " resets.");
}

1

Để thực hiện đúng cách, bạn cần xử lý các trường hợp ngoại lệ.

Đây là cách tôi thực hiện chờ iFrame. Điều này yêu cầu lớp kiểm tra JUnit của bạn phải chuyển phiên bản của RemoteWebDriver vào đối tượng trang:

public class IFrame1 extends LoadableComponent<IFrame1> {

    private RemoteWebDriver driver;

    @FindBy(id = "iFrame1TextFieldTestInputControlID" )
    public WebElement iFrame1TextFieldInput;

    @FindBy(id = "iFrame1TextFieldTestProcessButtonID" )
    public WebElement copyButton;

    public IFrame1( RemoteWebDriver drv ) {
        super();
        this.driver = drv;
        this.driver.switchTo().defaultContent();
        waitTimer(1, 1000);
        this.driver.switchTo().frame("BodyFrame1");
        LOGGER.info("IFrame1 constructor...");
    }

    @Override
    protected void isLoaded() throws Error {        
        LOGGER.info("IFrame1.isLoaded()...");
        PageFactory.initElements( driver, this );
        try {
            assertTrue( "Page visible title is not yet available.", driver
     .findElementByCssSelector("body form#webDriverUnitiFrame1TestFormID h1")
                    .getText().equals("iFrame1 Test") );
        } catch ( NoSuchElementException e) {
            LOGGER.info("No such element." );
            assertTrue("No such element.", false);
        }
    }

    @Override
    protected void load() {
        LOGGER.info("IFrame1.load()...");
        Wait<WebDriver> wait = new FluentWait<WebDriver>( driver )
                .withTimeout(30, TimeUnit.SECONDS)
                .pollingEvery(5, TimeUnit.SECONDS)
                .ignoring( NoSuchElementException.class ) 
                .ignoring( StaleElementReferenceException.class ) ;
            wait.until( ExpectedConditions.presenceOfElementLocated( 
            By.cssSelector("body form#webDriverUnitiFrame1TestFormID h1") ) );
    }
....

LƯU Ý: Bạn có thể xem toàn bộ ví dụ làm việc của tôi tại đây .


1

Đối với nodejsthư viện Selenium, tôi đã sử dụng đoạn mã sau. Trong trường hợp của tôi, tôi đang tìm kiếm hai đối tượng được bổ sung vào cửa sổ, mà trong ví dụ này là <SOME PROPERTY>, 10000là mili giây thời gian chờ, <NEXT STEP HERE>là những gì xảy ra sau khi các thuộc tính được tìm thấy trên cửa sổ.

driver.wait( driver => {
    return driver.executeScript( 'if(window.hasOwnProperty(<SOME PROPERTY>) && window.hasOwnProperty(<SOME PROPERTY>)) return true;' ); }, 10000).then( ()=>{
        <NEXT STEP HERE>
}).catch(err => { 
    console.log("looking for window properties", err);
});

0

Bạn có thể viết một số logic để xử lý điều này. Tôi đã viết một phương thức sẽ trả về WebElementvà phương thức này sẽ được gọi ba lần hoặc bạn có thể tăng thời gian và thêm kiểm tra null cho WebElementĐây là một ví dụ

public static void main(String[] args) {
        WebDriver driver = new FirefoxDriver();
        driver.get("https://www.crowdanalytix.com/#home");
        WebElement webElement = getWebElement(driver, "homekkkkkkkkkkkk");
        int i = 1;
        while (webElement == null && i < 4) {
            webElement = getWebElement(driver, "homessssssssssss");
            System.out.println("calling");
            i++;
        }
        System.out.println(webElement.getTagName());
        System.out.println("End");
        driver.close();
    }

    public static WebElement getWebElement(WebDriver driver, String id) {
        WebElement myDynamicElement = null;
        try {
            myDynamicElement = (new WebDriverWait(driver, 10))
                    .until(ExpectedConditions.presenceOfElementLocated(By
                            .id(id)));
            return myDynamicElement;
        } catch (TimeoutException ex) {
            return null;
        }
    }

0

Đây là từ mã của riêng tôi:
Window.setTimeout chỉ thực thi khi trình duyệt không hoạt động.
Vì vậy, việc gọi hàm một cách đệ quy (42 lần) sẽ mất 100ms nếu không có hoạt động nào trong trình duyệt và hơn thế nữa nếu trình duyệt đang bận làm việc khác.

    ExpectedCondition<Boolean> javascriptDone = new ExpectedCondition<Boolean>() {
        public Boolean apply(WebDriver d) {
            try{//window.setTimeout executes only when browser is idle,
                //introduces needed wait time when javascript is running in browser
                return  ((Boolean) ((JavascriptExecutor) d).executeAsyncScript( 

                        " var callback =arguments[arguments.length - 1]; " +
                        " var count=42; " +
                        " setTimeout( collect, 0);" +
                        " function collect() { " +
                            " if(count-->0) { "+
                                " setTimeout( collect, 0); " +
                            " } "+
                            " else {callback(" +
                            "    true" +                            
                            " );}"+                             
                        " } "
                    ));
            }catch (Exception e) {
                return Boolean.FALSE;
            }
        }
    };
    WebDriverWait w = new WebDriverWait(driver,timeOut);  
    w.until(javascriptDone);
    w=null;

Như một phần thưởng, bộ đếm có thể được đặt lại trên document.readyState hoặc trên các lệnh gọi jQuery Ajax hoặc nếu bất kỳ hoạt ảnh jQuery nào đang chạy (chỉ khi ứng dụng của bạn sử dụng jQuery cho các cuộc gọi ajax ...)
...

" function collect() { " +
                            " if(!((typeof jQuery === 'undefined') || ((jQuery.active === 0) && ($(\":animated\").length === 0))) && (document.readyState === 'complete')){" +
                            "    count=42;" +
                            "    setTimeout( collect, 0); " +
                            " }" +
                            " else if(count-->0) { "+
                                " setTimeout( collect, 0); " +
                            " } "+ 

...

CHỈNH SỬA: Tôi nhận thấy executeAsyncScript không hoạt động tốt nếu một trang mới tải và kiểm tra có thể ngừng phản hồi không liên tục, tốt hơn nên sử dụng điều này thay thế.

public static ExpectedCondition<Boolean> documentNotActive(final int counter){ 
    return new ExpectedCondition<Boolean>() {
        boolean resetCount=true;
        @Override
        public Boolean apply(WebDriver d) {

            if(resetCount){
                ((JavascriptExecutor) d).executeScript(
                        "   window.mssCount="+counter+";\r\n" + 
                        "   window.mssJSDelay=function mssJSDelay(){\r\n" + 
                        "       if((typeof jQuery != 'undefined') && (jQuery.active !== 0 || $(\":animated\").length !== 0))\r\n" + 
                        "           window.mssCount="+counter+";\r\n" + 
                        "       window.mssCount-->0 &&\r\n" + 
                        "       setTimeout(window.mssJSDelay,window.mssCount+1);\r\n" + 
                        "   }\r\n" + 
                        "   window.mssJSDelay();");
                resetCount=false;
            }

            boolean ready=false;
            try{
                ready=-1==((Long) ((JavascriptExecutor) d).executeScript(
                        "if(typeof window.mssJSDelay!=\"function\"){\r\n" + 
                        "   window.mssCount="+counter+";\r\n" + 
                        "   window.mssJSDelay=function mssJSDelay(){\r\n" + 
                        "       if((typeof jQuery != 'undefined') && (jQuery.active !== 0 || $(\":animated\").length !== 0))\r\n" + 
                        "           window.mssCount="+counter+";\r\n" + 
                        "       window.mssCount-->0 &&\r\n" + 
                        "       setTimeout(window.mssJSDelay,window.mssCount+1);\r\n" + 
                        "   }\r\n" + 
                        "   window.mssJSDelay();\r\n" + 
                        "}\r\n" + 
                        "return window.mssCount;"));
            }
            catch (NoSuchWindowException a){
                a.printStackTrace();
                return true;
            }
            catch (Exception e) {
                e.printStackTrace();
                return false;
            }
            return ready;
        }
        @Override
        public String toString() {
            return String.format("Timeout waiting for documentNotActive script");
        }
    };
}

0

Không biết làm thế nào để làm điều đó nhưng trong trường hợp của tôi, tải trang cuối và hiển thị phù hợp với FAVICON được hiển thị trong tab Firefox.

Vì vậy, nếu chúng ta có thể tải hình ảnh biểu tượng yêu thích trong trình duyệt web, thì trang web đã được tải đầy đủ.

Nhưng làm thế nào để thực hiện điều này ....



-1

Đây là cách tôi làm điều đó:

new WebDriverWait(driver, 20).until(
       ExpectedConditions.jsReturnsValue(
                   "return document.readyState === 'complete' ? true : false"));

Selenium cũng thực hiện điều này theo mặc định, điều này sẽ chỉ bổ sung thêm một thời gian thực thi mã kịch bản của bạn (có thể có đủ thời gian cho những thứ khác để tải, nhưng sau đó một lần nữa có thể không)
Ardesco

-1

Tôi thích ý tưởng của bạn về việc thăm dò HTML cho đến khi nó ổn định. Tôi có thể thêm điều đó vào giải pháp của riêng tôi. Cách tiếp cận sau đây là trong C # và yêu cầu jQuery.

Tôi là nhà phát triển cho dự án thử nghiệm SuccessFactors (SaaS), nơi chúng tôi không có ảnh hưởng nào đối với các nhà phát triển hoặc các đặc điểm của DOM đằng sau trang web. Sản phẩm SaaS có khả năng thay đổi thiết kế DOM cơ bản của nó 4 lần một năm, vì vậy, cuộc săn lùng sẽ diễn ra vĩnh viễn để tìm ra những cách hiệu quả và hiệu quả để kiểm tra với Selenium (bao gồm KHÔNG thử nghiệm với Selenium khi có thể!)

Đây là những gì tôi sử dụng cho "trang đã sẵn sàng". Nó hoạt động trong tất cả các thử nghiệm của riêng tôi hiện tại. Cách tiếp cận tương tự cũng đã hoạt động đối với một ứng dụng web Java nội bộ lớn cách đây vài năm và đã hoạt động mạnh mẽ trong hơn một năm tại thời điểm tôi rời dự án.

  • Driver là phiên bản WebDriver giao tiếp với trình duyệt
  • DefaultPageLoadTimeout là một giá trị thời gian chờ tính bằng tick (100ns mỗi tick)

public IWebDriver Driver { get; private set; }

// ...

const int GlobalPageLoadTimeOutSecs = 10;
static readonly TimeSpan DefaultPageLoadTimeout =
    new TimeSpan((long) (10_000_000 * GlobalPageLoadTimeOutSecs));
Driver = new FirefoxDriver();

Trong phần tiếp theo, hãy lưu ý thứ tự của các lần đợi trong phương thức PageReady(tài liệu Selenium đã sẵn sàng, Ajax, hoạt ảnh), điều này có ý nghĩa nếu bạn nghĩ về nó:

  1. tải trang chứa mã
  2. sử dụng mã để tải dữ liệu từ một nơi nào đó thông qua Ajax
  3. trình bày dữ liệu, có thể bằng hình ảnh động

Một cái gì đó giống như phương pháp so sánh DOM của bạn có thể được sử dụng từ 1 đến 2 để thêm một lớp mạnh mẽ khác.


public void PageReady()
{
    DocumentReady();
    AjaxReady();
    AnimationsReady();
}


private void DocumentReady()
{
    WaitForJavascript(script: "return document.readyState", result: "complete");
}

private void WaitForJavascript(string script, string result)
{
    new WebDriverWait(Driver, DefaultPageLoadTimeout).Until(
        d => ((IJavaScriptExecutor) d).ExecuteScript(script).Equals(result));
}

private void AjaxReady()
{
    WaitForJavascript(script: "return jQuery.active.toString()", result: "0");
}

private void AnimationsReady()
{
    WaitForJavascript(script: "return $(\"animated\").length.toString()", result: "0");
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.