[英]Selenium WebDriver: Wait for complex page with JavaScript to load
I have a web application to test with Selenium. There is a lot of JavaScript running on page load.我有一个 web 应用程序要用 Selenium 进行测试。页面加载时有很多 JavaScript 正在运行。
This JavaScript code is not so well written but I can't change anything.这段 JavaScript 代码写得不太好,但我无法更改任何内容。 So waiting for an element to appear in the DOM with
findElement()
method is not an option.因此,使用
findElement()
方法等待元素出现在 DOM 中不是一种选择。
I want to create a generic function in Java to wait for a page to load, a possible solution would be:我想在 Java 中创建一个通用的 function 来等待页面加载,一个可能的解决方案是:
document.body.innerHTML
in a string variable body
.document.body.innerHTML
的结果存储在字符串变量body
中。body
variable to the previous version of body
.body
变量与以前版本的body
进行比较。 if they are the same then set increment a counter notChangedCount
otherwise set notChangedCount
to zero.notChangedCount
否则将notChangedCount
设置为零。notChangedCount >= 10
then exit the loop otherwise loop to the first step.notChangedCount >= 10
然后退出循环,否则循环到第一步。 Do you think it's a valid solution?你认为这是一个有效的解决方案吗?
If anyone actually knew a general and always-applicable answer, it would have been implemented everywhere ages ago and would make our lives SO much easier.如果有人真的知道一个通用且始终适用的答案,那么很久以前它就会在任何地方实施,并且会让我们的生活变得更加轻松。
There are many things you can do, but every single one of them has a problem:你可以做很多事情,但每一件事都有一个问题:
As Ashwin Prabhu said, if you know the script well, you can observe its behaviour and track some of its variables on window
or document
etc. This solution, however, is not for everyone and can be used only by you and only on a limited set of pages.正如 Ashwin Prabhu 所说,如果你很了解这个脚本,你可以观察它的行为并在
window
或document
等上跟踪它的一些变量。但是,这个解决方案并不适合所有人,只能由你使用,并且只能在有限的情况下使用页集。
Your solution by observing the HTML code and whether it has or hasn't been changed for some time is not bad (also, there is a method to get the original and not-edited HTML directly by WebDriver
), but:通过观察 HTML 代码以及它是否在一段时间内没有更改,您的解决方案还不错(还有一种方法可以通过
WebDriver
直接获取原始且未编辑的 HTML),但是:
setTimeout()
) and work again and again and could possibly change the HTML every time they run.setTimeout()
)并一次又一次地工作,并且每次运行时都可能更改 HTML。 Seriously, every "Web 2.0" page does it.innerHTML
fun.innerHTML
乐趣。 There are tools to help you on this.有一些工具可以帮助您解决这个问题。 Namely Progress Listeners together with nsIWebProgressListener and some others.
即Progress Listeners与nsIWebProgressListener和其他一些。 The browser support for this, however, is horrible.
然而,浏览器对此的支持非常糟糕。 Firefox began to try to support it from FF4 onwards (still evolving), IE has basic support in IE9.
Firefox 从 FF4 开始尝试支持它(仍在发展中),IE 在 IE9 中有基本支持。
And I guess I could come up with another flawed solution soon.我想我很快就会想出另一个有缺陷的解决方案。 The fact is - there's no definite answer on when to say "now the page is complete" because of the everlasting scripts doing their work.
事实是 - 关于何时说“现在页面已完成”没有明确的答案,因为永恒的脚本在做他们的工作。 Pick the one that serves you best, but beware of its shortcomings.
选择最适合您的那个,但要注意它的缺点。
Thanks Ashwin !谢谢阿什温!
In my case I should need wait for a jquery plugin execution in some element.. specifically "qtip"在我的情况下,我应该等待某个元素中的 jquery 插件执行..特别是“qtip”
based in your hint, it worked perfectly for me :根据您的提示,它对我来说非常有效:
wait.until( new Predicate<WebDriver>() {
public boolean apply(WebDriver driver) {
return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
}
}
);
Note: I'm using Webdriver 2注意:我使用的是 Webdriver 2
You need to wait for Javascript and jQuery to finish loading.你需要等待Javascript和jQuery来完成加载。 Execute Javascript to check if
jQuery.active
is 0
and document.readyState
is complete
, which means the JS and jQuery load is complete.执行JavaScript,以检查是否
jQuery.active
是0
和document.readyState
是complete
的,这意味着所述JS和jQuery加载完成。
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);
}
Does the JS library define/initialize any well known variable on the window? JS 库是否在窗口上定义/初始化了任何众所周知的变量?
If so you could wait for the variable to appear.如果是这样你可以等待变量出现。 You can use
您可以使用
((JavascriptExecutor)driver).executeScript(String script, Object... args)
to test for this condition (something like: window.SomeClass && window.SomeClass.variable != null
) and return a boolean true
/ false
.以测试这种情况(是这样的:
window.SomeClass && window.SomeClass.variable != null
),并返回一个布尔true
/ false
。
Wrap this in a WebDriverWait
, and wait until the script returns true
.在包装这个
WebDriverWait
,并等待脚本返回true
。
If all you need to do is wait for the html on the page to become stable before trying to interact with elements, you can poll the DOM periodically and compare the results, if the DOMs are the same within the given poll time, you're golden.如果您需要做的就是在尝试与元素交互之前等待页面上的 html 变得稳定,您可以定期轮询 DOM 并比较结果,如果 DOM 在给定的轮询时间内相同,则您金的。 Something like this where you pass in the maximum wait time and the time between page polls before comparing.
类似这样的事情,您可以在比较之前传入最大等待时间和页面轮询之间的时间。 Simple and effective.
简单有效。
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;
}
}
}
I had a same issue.我有同样的问题。 This solution works for me from WebDriverDoku:
这个解决方案适用于 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 http://www.seleniumhq.org/docs/04_webdriver_advanced.jsp
The below code works perfectly in my case - my page contains complex java scripts以下代码在我的情况下完美运行 - 我的页面包含复杂的 java 脚本
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;
}
}
}
Source - How To Wait For Page To Load/Ready In Selenium WebDriver源 - 如何在 Selenium WebDriver 中等待页面加载/就绪
Two conditions can be used to check if the page is loaded before finding any element on the page:在找到页面上的任何元素之前,可以使用两个条件来检查页面是否已加载:
WebDriverWait wait = new WebDriverWait(driver, 50);
Using below readyState will wait till page load使用下面的 readyState 将等到页面加载
wait.until((ExpectedCondition<Boolean>) wd ->
((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete"));
Below JQuery will wait till data has not been loaded下面 JQuery 将等待数据尚未加载
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++;
}
}
After these JavaScriptCode try to findOut webElement.在这些 JavaScriptCode 之后尝试找出 webElement。
WebElement we = wait.until(ExpectedConditions.presenceOfElementLocated(by));
I asked my developers to create a JavaScript variable "isProcessing" that I can access (in the "ae" object) that they set when things start running and clear when things are done.我要求我的开发人员创建一个我可以访问的 JavaScript 变量“isProcessing”(在“ae”对象中),他们在事情开始运行时设置并在事情完成时清除。 I then run it in an accumulator that checks it every 100 ms until it gets five in a row for a total of 500 ms without any changes.
然后我在一个累加器中运行它,每 100 毫秒检查一次,直到它连续 5 次,总共 500 毫秒没有任何变化。 If 30 seconds pass, I throw an exception because something should have happened by then.
如果 30 秒过去了,我会抛出一个异常,因为那时应该发生了一些事情。 This is in C#.
这是在 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.");
}
To do it properly, you need to handle the exceptions.要正确执行此操作,您需要处理异常。
Here is how I do a wait for an iFrame.这是我等待 iFrame 的方法。 This requires that your JUnit test class pass the instance of RemoteWebDriver into the page object :
这要求您的 JUnit 测试类将 RemoteWebDriver 的实例传递到页面对象中:
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") ) );
}
....
NOTE: You can see my entire working example here .注意:您可以在此处查看我的整个工作示例。
For the nodejs
Selenium library, I used the following snippet.对于
nodejs
Selenium 库,我使用了以下代码段。 In my case, I was looking for two objects that are added to the window, which in this example are <SOME PROPERTY>
, 10000
is the timeout milliseconds, <NEXT STEP HERE>
is what happens after the properties are found on the window.就我而言,我正在寻找添加到窗口的两个对象,在本例中为
<SOME PROPERTY>
, 10000
是超时毫秒, <NEXT STEP HERE>
是在窗口上找到属性后发生的情况。
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);
});
This works for me well with dynamically rendered websites:对于动态呈现的网站,这对我很有效:
WebDriverWait wait = new WebDriverWait(driver, 50); wait.until((ExpectedCondition<Boolean>) wd -> ((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete"));
try { wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(text(),'" + "This text will always fail :)" + "')]"))); // condition you are certain won't be true } catch (TimeoutException te) { }
String script = "return document.getElementsByTagName(\\"html\\")[0].outerHTML;"; content = ((JavascriptExecutor) driver).executeScript(script).toString();
You can write some logic to handle this.您可以编写一些逻辑来处理此问题。 I have write a method that will return the
WebElement
and this method will be called three times or you can increase the time and add a null check for WebElement
Here is an example我编写了一个返回
WebElement
的方法,该方法将被调用 3 次,或者您可以增加时间并为WebElement
添加空检查这是一个示例
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;
}
}
Here's from my own code:这是我自己的代码:
Window.setTimeout executes only when browser is idle. Window.setTimeout 仅在浏览器空闲时执行。
So calling the function recursively (42 times) will take 100ms if there is no activity in the browser and much more if the browser is busy doing something else.因此,如果浏览器中没有活动,递归调用该函数(42 次)将需要 100 毫秒,如果浏览器忙于做其他事情,则需要更多时间。
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;
As a bonus the counter can be reset on document.readyState or on jQuery Ajax calls or if any jQuery animations are running (only if your app uses jQuery for ajax calls...)作为奖励,计数器可以在 document.readyState 或 jQuery Ajax 调用或任何 jQuery 动画正在运行时重置(仅当您的应用程序使用 jQuery 进行 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: I notice executeAsyncScript doesn't work well if a new page loads and the test might stop responding indefinetly, better to use this on instead.编辑:我注意到如果新页面加载并且测试可能会不确定地停止响应,我注意到 executeAsyncScript 不能正常工作,最好改用它。
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");
}
};
}
I like your idea of polling the HTML until it's stable.我喜欢你轮询 HTML 直到它稳定的想法。 I may add that to my own solution.
我可以将其添加到我自己的解决方案中。 The following approach is in C# and requires jQuery.
以下方法是在 C# 中,需要 jQuery。
I'm the developer for a SuccessFactors (SaaS) test project where we have no influence at all over the developers or the characteristics of the DOM behind the web page.我是 SuccessFactors (SaaS) 测试项目的开发人员,我们对开发人员或网页背后的 DOM 特性没有任何影响。 The SaaS product can potentially change its underlying DOM design 4 times a year, so the hunt is permanently on for robust, performant ways to test with Selenium (including NOT testing with Selenium where possi ble!)
SaaS 产品每年可能会更改其底层 DOM 设计 4 次,因此一直在寻找使用 Selenium 进行测试的稳健、高效的方法(包括在可能的情况下不使用 Selenium 进行测试!)
Here's what I use for "page ready".这是我用于“页面就绪”的内容。 It works in all my own tests currently.
它目前适用于我自己的所有测试。 The same approach also worked for a big in-house Java web app a couple of years ago, and had been robust for over a year at the time I left the project.
几年前,同样的方法也适用于一个大型的内部 Java Web 应用程序,并且在我离开该项目时已经运行了一年多。
Driver
is the WebDriver instance that communicates with the browser Driver
是与浏览器通信的 WebDriver 实例DefaultPageLoadTimeout
is a timeout value in ticks (100ns per tick) DefaultPageLoadTimeout
是以滴答为单位的超时值(每滴答 100ns)public IWebDriver Driver { get; private set; }
// ...
const int GlobalPageLoadTimeOutSecs = 10;
static readonly TimeSpan DefaultPageLoadTimeout =
new TimeSpan((long) (10_000_000 * GlobalPageLoadTimeOutSecs));
Driver = new FirefoxDriver();
In what follows, note the order of waits in method PageReady
(Selenium document ready, Ajax, animations), which makes sense if you think about it:在接下来的内容中,请注意方法
PageReady
的等待顺序(Selenium 文档就绪、Ajax、动画),如果您考虑一下,这很有意义:
Something like your DOM comparison approach could be used between 1 and 2 to add another layer of robustness.可以在 1 和 2 之间使用像您的 DOM 比较方法之类的东西来增加另一层稳健性。
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");
}
有没有人发现如何在React Application中获得活动的Ajax调用计数
Don't know how to do that but in my case, end of page load & rendering match with FAVICON displayed in Firefox tab.不知道该怎么做,但就我而言,页面加载结束和渲染与 Firefox 选项卡中显示的 FAVICON 匹配。
So if we can get the favicon image in the webbrowser, the web page is fully loaded.所以如果我们能在浏览器中获取到 favicon 图像,那么网页就完全加载了。
But how perform this ....但是如何执行这个......
Using implicit wait works for me.使用隐式等待对我有用。
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
Refer to this answer Selenium c# Webdriver: Wait Until Element is Present请参阅此答案Selenium c# Webdriver: Wait until Element is Present
In case of a complex/heavy webpage, it is always advisable to check for javascript and jQuery completion before performing any selenium test operations.对于复杂/繁重的网页,始终建议在执行任何 selenium 测试操作之前检查javascript和jQuery 是否完成。
When you test for jQuery completion do not forget to add a check for jQuery being undefined else you will end up with ReferenceError: jQuery is not defined
error .当您测试 jQuery 完成时,不要忘记添加对 jQuery 未定义的检查,否则您将以
ReferenceError: jQuery is not defined
错误结束。
So you need to add below 2 checks:所以你需要添加以下 2 个检查:
return ((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete")
(Boolean)((JavascriptExecutor) wd).executeScript("return window.jQuery.= undefined && jQuery.active == 0")
Now when you write method then I would suggest to use Fluent Wait in your selenium code rather than implicit or explicit wait.现在,当您编写方法时,我建议您在selenium 代码中使用Fluent Wait ,而不是隐式或显式等待。 Fluent wait method will help you do operation in between the polling interval wait unlike other waits and is very useful or rather powerful.
Fluent wait 方法将帮助您在轮询间隔等待之间进行操作,这与其他等待不同,非常有用或相当强大。
Below is the working method which you can directly use:以下是您可以直接使用的工作方法:
public static void pageJavaScriptAndJqueryLoad(WebDriver driver, Duration waitTimeout) { Wait<WebDriver> wait = new FluentWait<>(driver).withTimeout(waitTimeout).pollingEvery(Duration.ofMillis(500)).ignoring(NoSuchElementException.class); wait.until((ExpectedCondition<Boolean>) wd -> { log.info("Waiting for Page Javascript to load completely"); log.info("document.readyState value is: " + ((JavascriptExecutor) wd).executeScript("return document.readyState")); log.info("jQuery.active value is: " + ((JavascriptExecutor) wd).executeScript("return window.jQuery.= undefined && jQuery;active")). return ((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete") && (Boolean)((JavascriptExecutor) wd).executeScript("return window.jQuery;= undefined && jQuery;active == 0"); }); }
In the above method:在上面的方法中:
Here is a python version for those that need it这里有一个python版本给有需要的人
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def wait_for_js_to_load(driver):
wait = WebDriverWait(driver, 30)
# Wait for jQuery to load
jQuery_load = EC.presence_of_element_located((By.XPATH, "//script[contains(@src,'jquery')]"))
wait.until(jQuery_load)
# Wait for Javascript to load
js_load = EC.presence_of_element_located((By.XPATH, "//script[contains(@src,'javascript')]"))
wait.until(js_load)
Here's how I do it:这是我的方法:
new WebDriverWait(driver, 20).until(
ExpectedConditions.jsReturnsValue(
"return document.readyState === 'complete' ? true : false"));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.