Selenium - Page Wait for Angular using Protractor javascript code - java

I am testing a angularjs page and using selenium(java) to write automation scripts for the same.
The following is the code that I use for the page synchronization wait before proceeding to next screen action
public static boolean angularHasFinishedProcessing() {
ExpectedCondition<Boolean> pageLoadCondition = new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver driver) {
driver = GetDriver();//This is to get the driver in current action.
String hasAngularFinishedScript = "var callback = arguments[arguments.length - 1];\n" +
"var el = document.querySelector('html');\n" +
"if (!window.angular) {\n" +
"console.log('1'); \n" +
" callback('false')\n" +
"}\n" +
"if (angular.getTestability) {\n" +
" angular.getTestability(el).whenStable(function(){callback('true')});\n" +
"} else {\n" +
"console.log('hello3'); \n" +
" if (!angular.element(el).injector()) {\n" +
" callback('false')\n" +
" }\n" +
" var browser = angular.element(el).injector().get('$browser');\n" +
" browser.notifyWhenNoOutstandingRequests(function(){callback('true')});\n" +
"}";
JavascriptExecutor javascriptExecutor = (JavascriptExecutor) driver;
String isProcessingFinished = javascriptExecutor.executeAsyncScript(hasAngularFinishedScript).toString();
return Boolean.valueOf(isProcessingFinished);
}
};
WebDriverWait wait = new WebDriverWait(driver, 60);
boolean bRet = (wait.until(pageLoadCondition));
if (bRet) {
return bRet;
} else
return false;
}
The issue is isProcessingFinished is always false, the console always writes 1 (meaning window.angular always returns false).
Also, Since, there is no way I can debug the javascript snippet during the execution, I don't know if there is any other issue. Could someone help please?

1) For how to debug javascript
Add a breakpoint before this wait function, run script until stopped at this breakpoint, Open DevTool of browser and execute window.angular in console Tab to see it's true or false.
And you can continue to execute the rest code lines of your javascript snippet in console Tab to examine any code issue or work as expect.

Related

Selenium wait till page is fully load using JavascriptExecutor

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

how to handle alerts in selenium with phantomjs headless browser

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();

Synchronization with implicitwait() do not work, why?

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 perform drag and drop action even code executed without any error

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

Using WebDriver JS Executor to execute a .js file --> Null Pointer Exception

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);

Categories

Resources