Dưới đâ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, gọi hàm đệ quy (42 lần) sẽ mất 100ms nếu không có hoạt động nào trong trình duyệt và nhiều hơn 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 quầy có thể được thiết lập lại trên document.readyState hoặc trên jQuery Ajax gọi hoặc nếu bất kỳ hình ảnh động jQuery đ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); " +
" } "+
...
EDIT: Tôi nhận thấy executeAsyncScript không hoạt động tốt nếu một tải trang mới và thử nghiệm có thể ngừng đáp ứng indefinetly, tốt hơn để sử dụng này trên để 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");
}
};
}
findElement() không chờ - bạn có ý gì với điều đó? –
'findElement' chờ 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à ExpectedCondition nó linh hoạt hơn. –