Given a site, AJAX components on the page and I need to wait till the whole page is fully loaded.
Here is my wait method using JavascriptExecutor checking document.readyState:
public void waitForLoading2() {
WebDriverWait wait = new WebDriverWait(driver, timeOut);
if(!driver.findElements(By.xpath("//*[#id='wait'][contains(#style, 'display: block')]")).isEmpty()) {
wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//*[#id='wait'][contains(#style, 'display: none')]")));
}
ExpectedCondition<Boolean> expectation = new
ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor) driver).executeScript("return document.readyState").toString().equalsIgnoreCase("complete");
}
};
wait.until(expectation);
}
Sometimes it's failing with the following Error msg:
org.openqa.selenium.JavascriptException: JavaScript error (WARNING:
The server did not provide any stacktrace information)
What did I miss here? My assumption is that document.readyState is common and always can be checked.
Thanks
There are more complex options, like this one
public static void waitForAjax(WebDriver driver, String action) {
driver.manage().timeouts().setScriptTimeout(5, TimeUnit.SECONDS);
((JavascriptExecutor) driver).executeAsyncScript(
"var callback = arguments[arguments.length - 1];" +
"var xhr = new XMLHttpRequest();" +
"xhr.open('POST', '/" + action + "', true);" +
"xhr.onreadystatechange = function() {" +
" if (xhr.readyState == 4) {" +
" callback(xhr.responseText);" +
" }" +
"};" +
"xhr.send();");
}
in order
to wait till the whole page is fully loaded
But the following did the trick for me - I check if there are ongoing AJAX calls and wait till those are done:
JavascriptExecutor js = (JavascriptExecutor) driverjs;
js.executeScript("return((window.jQuery != null) && (jQuery.active === 0))").equals("true");
Checking document.readyState will not help you with AJAX calls. Your best bet is to find an element in the area being loaded by AJAX and wait until it is visible. Then you'll know that the page is loaded. If there are multiple/separate areas loaded by AJAX calls, then you will want to pick an element from each area.
If you use jQuery to send AJAX request, you can get the value of jQuery.active. it's equivalent to all AJAX requests complete when jQuery.active=0.
Use executeScript("return jQuery.active==0"). For detail please read this artical
Selenium version : 3.4.0
phantomjs version : 2.1.1
java : 1.8.0_151
I have tried below things but it didnt work for me.
enter code here
1:
webDriver instanceof PhantomJSDriver){
JavascriptExecutor je = (JavascriptExecutor) driver;
je.executeScript("window.alert = function(){};");
je.executeScript("window.confirm = function(){return true;};");
System.out.println("Alert has been handled"); }
else {
Alert a1 = driver.switchTo().alert();
a1.accept();
}
2:
/*((PhantomJSDriver)driver).executeScript("window.alert = function(){}");
((PhantomJSDriver)driver).executeScript("window.confirm = function(){return true;}");*/
3:
PhantomJSDriver phantom = (PhantomJSDriver) driver;
phantom.executeScript("window.confirm = function(){return true;};");
4:
((JavascriptExecutor)driver).executeScript("window.alert = function(msg){};");
((JavascriptExecutor)driver).executeScript("window.confirm = function(msg){return true;};");
5 :
PhantomJSDriver phantom = (PhantomJSDriver)driver;
phantom.executePhantomJS("var page = this;" +
"page.onAlert = function(msg) {" +
"console.log('ALERT: ' + msg);" +
"};");
phantom.executePhantomJS("var page = this;" +
"page.onConfirm = function(msg) {" +
"console.log('CONFIRM: ' + msg);"+ "return true;" +"};");
Can you please suggest apart from above.
To handle alert in PhantomJS you have to wait for the alert to be present and then cast the WebDriver to JavascriptExecutor. You can use can use the following code block :
((JavascriptExecutor) driver).executeScript("window.alert = function(msg){};");
//or
((JavascriptExecutor) driver).executeScript("window.confirm = function(msg){return true;};");
driver.findElement(By.id("element_which_trigers_the_alert")).click();
I'm trying synchronization with selenium webdriver and something is not working with implicitlyWait().
The way I understand implicitlyWait(..) is that the code is waiting until the element is available for a max of time.
The code below crash with the error:
org.openqa.selenium.InvalidElementStateException: invalid element state: Element is not currently interactable and may not be manipulated
The System.out ist printing: -->> false true false (isDiplayed(), isEnabled(), is Selected())
private static WebDriver driver;
public static void main(String[] args) throws InterruptedException {
setupWebDriverChrome();
//Thread.sleep(1000);
final String cssSelectorFromAirport = "div.od-airportselector.airportselector_root input[tabindex='11']";
final By cssSelector = By.cssSelector(cssSelectorFromAirport);
WebElement fromAirportElement = driver.findElement(cssSelector);
System.out.println("-->> " + fromAirportElement.isDisplayed() + " " + fromAirportElement.isEnabled() + " " + fromAirportElement.isSelected());
fromAirportElement.clear();
fromAirportElement.sendKeys("MUC");
}
private static void setupWebDriverChrome() {
System.setProperty("webdriver.chrome.driver", "C:\\...\\chromedriver.exe");
setupLocation();
}
private static void setupLocation() {
driver.manage().timeouts().implicitlyWait(1000, TimeUnit.MILLISECONDS);
driver.get("https://www.opodo.de/");
}
I tried that also with the Geckodriver with the same result.
I have also increased the wait time but same result.
The only way to make it works, is to use Thread.sleep() (Commented above)
EDIT
Pls. note that I do not see any duplication with Selenium implicitwait not working.
You have to wait that your element is clickable. Try adding this:
WebElement element = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.elementToBeClickable(By.cssSelector(cssSelectorFromAirport)));
So:
setupWebDriverChrome();
//Thread.sleep(1000);
final String cssSelectorFromAirport = "div.od-airportselector.airportselector_root input[tabindex='11']";
WebElement element = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.elementToBeClickable(By.cssSelector(cssSelectorFromAirport)));
/*final By cssSelector = By.cssSelector(cssSelectorFromAirport);
WebElement fromAirportElement = driver.findElement(cssSelector);
System.out.println("-->> " + fromAirportElement.isDisplayed() + " " + fromAirportElement.isEnabled() + " " + fromAirportElement.isSelected());*/
element.clear();
element.sendKeys("MUC");
EDIT
From the documentation :
An implicit wait is to tell WebDriver to poll the DOM for a certain
amount of time when trying to find an element or elements if they are
not immediately available. The default setting is 0. Once set, the
implicit wait is set for the life of the WebDriver object instance.
This means, in your example, that selenium found the element but it isn't yet "clickable".
You can see this also in your test. If you take a look to:
System.out.println("-->> " + fromAirportElement.isDisplayed() + " " + fromAirportElement.isEnabled() + " " + fromAirportElement.isSelected() );
When it fails, the output is:
-->> false true false
While when it works:
-->> true true false
Unable to see element dragged in AnjularJS application even though drag and drop actions performed without any error.
Below is the code:
WebElement draggable = driver.findElement(By.xpath("//*[#id='page-content-wrapper']/div[2]/div[3]/div[4]/div/div[2]/div/div/div[2]/div/div[1]/ul/li/ul/li[2]/span/span[1]"));
WebElement droppable = driver.findElement(By.xpath(".//*[#id='page-content-wrapper']/div[2]/div[3]/div[3]/div[2]/div[1]/div[1]/div/div[6]/div[2]/div[1]"));
Below are different methods performed and executed without error:
1)
Actions builder = new Actions(driver);
builder.keyDown(Keys.CONTROL).click(draggable).click(droppable). keyUp(Keys.CONTROL).build().perform();
2)Method 2
Actions builder = new Actions(driver);
builder.clickAndHold(draggable).moveToElement(droppable).build();
builder.dragAndDrop(draggable, droppable).perform();
3)Method 3
Actions action = new Actions(driver);
Thread.sleep(1000);
action.clickAndHold(draggable2).build().perform();
action.moveToElement(droppable2).build().perform();
action.release(droppable2).build().perform();
4)
Method 4
Actions actions = new Actions(driver);
browser.actions()
.mouseDown(draggable2)
.mouseMove(draggable2)
.mouseUp(droppable2)
.perform();
Also performed JavaScript methods :But no luck it also executes without error but unable to perform drag and drop action in UIenter image description here
A) public static void DragAndDropJS2(WebElement source, WebElement destination, WebDriver driver) throws Exception
{
// JavascriptExecutor js = (JavascriptExecutor) driver;
String xto=Integer.toString(source.getLocation().x);
String yto=Integer.toString(destination.getLocation().y);
((JavascriptExecutor)driver).executeScript("function simulate(f,c,d,e){var b,a=null;for(b in eventMatchers)if(eventMatchers[b].test(c)){a=b;break}if(!a)return!1;document.createEvent?(b=document.createEvent(a),a==\"HTMLEvents\"?b.initEvent(c,!0,!0):b.initMouseEvent(c,!0,!0,document.defaultView,0,d,e,d,e,!1,!1,!1,!1,0,null),f.dispatchEvent(b)):(a=document.createEventObject(),a.detail=0,a.screenX=d,a.screenY=e,a.clientX=d,a.clientY=e,a.ctrlKey=!1,a.altKey=!1,a.shiftKey=!1,a.metaKey=!1,a.button=1,f.fireEvent(\"on\"+c,a));return!0} var eventMatchers={HTMLEvents:/^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/,MouseEvents:/^(?:click|dblclick|mouse(?:down|up|over|move|out))$/}; " +
"simulate(arguments[0],\"mousedown\",0,0); simulate(arguments[0],\"mousemove\",arguments[1],arguments[2]); simulate(arguments[0],\"mouseup\",arguments[1],arguments[2]); ",
source,xto,yto);
}
B) public static void DragAndDropJS(WebElement source, WebElement destination, WebDriver driver) throws Exception
{
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("function createEvent(typeOfEvent) {\n" +"var event =document.createEvent(\"CustomEvent\");\n" +"event.initCustomEvent(typeOfEvent,true, true, null);\n" +"event.dataTransfer = {\n" +"data: {},\n" +"setData: function (key, value) {\n" +"this.data[key] = value;\n" +"},\n" +"getData: function (key) {\n" +"return this.data[key];\n" +"}\n" +"};\n" +"return event;\n" +"}\n" +"\n" +"function dispatchEvent(element, event,transferData) {\n" +"if (transferData !== undefined) {\n" +"event.dataTransfer = transferData;\n" +"}\n" +"if (element.dispatchEvent) {\n" + "element.dispatchEvent(event);\n" +"} else if (element.fireEvent) {\n" +"element.fireEvent(\"on\" + event.type, event);\n" +"}\n" +"}\n" +"\n" +"function simulateHTML5DragAndDrop(element, destination) {\n" +"var dragStartEvent =createEvent('dragstart');\n" +"dispatchEvent(element, dragStartEvent);\n" +"var dropEvent = createEvent('drop');\n" +"dispatchEvent(destination, dropEvent,dragStartEvent.dataTransfer);\n" +"var dragEndEvent = createEvent('dragend');\n" +"dispatchEvent(element, dragEndEvent,dropEvent.dataTransfer);\n" +"}\n" +"\n" +"var source = arguments[0];\n" +"var destination = arguments[1];\n" +"simulateHTML5DragAndDrop(source,destination);",source, destination);
Thread.sleep(1500);
}
c) public static void DragAndDropJS1(WebElement source, WebElement destination, WebDriver driver) throws Exception
{
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("function createEvent(typeOfEvent) {\n" +"var event =document.createEvent(\"CustomEvent\");\n" +"event.initCustomEvent(typeOfEvent,true, true, null);\n" +"event.dataTransfer = {\n" +"data: {},\n" +"setData: function (key, value) {\n" +"this.data[key] = value;\n" +"},\n" +"getData: function (key) {\n" +"return this.data[key];\n" +"}\n" +"};\n" +"return event;\n" +"}\n" +"\n" +"function dispatchEvent(element, event,transferData) {\n" +"if (transferData !== undefined) {\n" +"event.dataTransfer = transferData;\n" +"}\n" +"if (element.dispatchEvent) {\n" + "element.dispatchEvent(event);\n" +"} else if (element.fireEvent) {\n" +"element.fireEvent(\"on\" + event.type, event);\n" +"}\n" +"}\n" +"\n" +"function simulateHTML5DragAndDrop(element, destination) {\n" +"var dragStartEvent =createEvent('dragstart');\n" +"dispatchEvent(element, dragStartEvent);\n" +"var dropEvent = createEvent('drop');\n" +"dispatchEvent(destination, dropEvent,dragStartEvent.dataTransfer);\n" +"}\n" +"\n" +"var source = arguments[0];\n" +"var destination = arguments[1];\n" +"simulateHTML5DragAndDrop(source,destination);",source, destination);
Thread.sleep(1500);
}
All the above mentioned methods and commands are compilled and executed without any error but unable to perform drag and drop operation in UI (PLEASE HELP).
Tried with all the possible combinations that I know can any one let me know am I missing some thing?
FYI am using Chrome 53 and Firefox 42 will that make any differnece?
Is there any other tool which satisfies my requirement?
Just make sure that the elements present in the webpage are not HTML5 web elements. Because selenium doesn't have support for performing actions on HTML5 elements.
Have look at http://elementalselenium.com/tips/39-drag-and-drop to know how to perform drag and drop operation on HTML5 elements using javascript.
This thread may also help you - Error when trying to execute drag and drop using javascript for Selenium WebDriver test
I am trying to implement a script I found online that automatically loads jQuery into sites that don't currently have them. I am using Selenium Webdriver's JS Executor function; however, it keeps returning a Null Pointer Exception. I tried to look everywhere for an answer, but can't seem to understand what's going on. What gives?
/** Browser automation driver for this test instance. */
private WebDriver driver;
/** JavaScript Executor for this test instance. */
private JavascriptExecutor js = (JavascriptExecutor) driver;
//...Firefox browser initialized here
public void JQuerify(final String Url){
ReporterNG.log("Opening a webpage at: " + Url);
driver.get(Url);
ReporterNG.log("Converting JS file to a String");
String jQueryLoader = getLoadJQuery();
// give jQuery time to load asynchronously
driver.manage().timeouts().setScriptTimeout(10, TimeUnit.SECONDS);
js.executeAsyncScript(jQueryLoader);
//THE PROBLEM ALWAYS OCCURS WITH THIS ^^^^^
ReporterNG.log("jQuery loaded!");
//THIS NEVER PRINTS OUT DUE TO THE ERROR ^^^^
}
/** dynamically load jQuery */
public static String getLoadJQuery(){
String LoadJQuery = "(function(jqueryUrl, callback) {\n" +
"if (typeof jqueryUrl != 'string') {" +
"jqueryUrl = 'https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js';\n" +
"}\n" +
"if (typeof jQuery == 'undefined') {\n" +
"var script = document.createElement('script');\n" +
"var head = document.getElementsByTagName('head')[0];\n" +
"var done = false;\n" +
"script.onload = script.onreadystatechange = (function() {\n" +
"if (!done && (!this.readyState || this.readyState == 'loaded'\n" +
"|| this.readyState == 'complete')) {\n" +
"done = true;\n" +
"script.onload = script.onreadystatechange = null;\n" +
"head.removeChild(script);\n" +
"callback();\n" +
"}\n" +
"});\n" +
"script.src = jqueryUrl;\n" +
"head.appendChild(script);\n" +
"}\n" +
"else {\n" +
"callback();\n" +
"}\n" +
"})(arguments[0], arguments[arguments.length - 1]);\n";
return LoadJQuery;
}
Any help would be greatly appreciated, as I am having the same problems with other similar applications of JS Executor. Thank you!
Make the JavascriptExecutor instance local to that method.
JavascriptExecutor js = (JavascriptExecutor) driver;
// give jQuery time to load asynchronously
driver.manage().timeouts().setScriptTimeout(10, TimeUnit.SECONDS);
js.executeAsyncScript(jQueryLoader);