Code is getting into an infinite search when executed via TestNG - java

The below code is getting into an infinite search when running via TestNG, otherwise giving correct results when executed directly in Main method via Java Application.
Boolean iselementpresent = driver.findElements(By.linkText("Foreign exchange1")).size()!= 0;
Infinite search-->
public boolean checkLinkPresence(String linkName){
Boolean iselementpresent = driver.findElements(By.linkText("Foreign exchange1")).size()!= 0;
if (iselementpresent == true)
return true;
else{
System.out.print("Element " + linkName + " not Present");
APP_LOGS.debug("Element " + linkName + " not Present");
return false;
}
}

You should not be using main method in TestNG as everything works with annotations. However make sure your implicit wait time is short so that the command findElements timeouts after that. If you have not given an implicit wait, try giving one and then try running your method. Here's an example -
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); //set this before you get the url using driver.get()
Once your implicit wait time is set, try running your method.
public boolean checkLinkPresence(String linkName){
List elements = driver.findElements(By.linkText("Foreign exchange1"));
if (elements.size() != 0)
return true;
else{
System.out.print("Element " + linkName + " not Present");
APP_LOGS.debug("Element " + linkName + " not Present");
return false;
}
}
Hope it helps.

This is how I would write this function...
public boolean checkLinkPresence(String linkName)
{
if (driver.findElements(By.linkText(linkName)).isEmpty())
{
System.out.print("Element " + linkName + " not Present");
APP_LOGS.debug("Element " + linkName + " not Present");
return false;
}
return true;
}
Your locator had a hard coded string in it By.linkText("Foreign exchange1"), so no matter what string you passed the function, it was always looking for that one string.

Related

Implement a global listener for Selenium tests

I use this code to click on a series of dialog windows with unique button ID. It was working fine till now because the order was strict:
clickConfirmWindow(driver, SURVEY_EXIT_BUTTON_ID_LOCATOR, "Survey exit window");
... and many mode windows with unique ID with random order
protected void clickConfirmWindow(WebDriver driver, String elementId, String name) {
// Check if warning window is displayed using button ID
System.out.println("Searching " + name + " using " + elementId);
if (isClickable(driver, elementId, 1)) {
System.out.println("Found " + name + " using " + elementId);
driver.findElement(By.id(elementId)).click();
}
}
protected void clickConfirmWindow(WebDriver driver, String elementId, String name) {
// Check if warning window is displayed using button ID
System.out.println("Searching " + name + " using " + elementId);
if (isClickable(driver, elementId, 1)) {
System.out.println("Found " + name + " using " + elementId);
driver.findElement(By.id(elementId)).click();
}
}
private Boolean isClickable(WebDriver driver, String elementId, int timeOut) {
try {
new WebDriverWait(driver, timeOut).until(ExpectedConditions.visibilityOfElementLocated(By.id(elementId)));
return true;
} catch (TimeoutException e) {
e.printStackTrace();
return false;
}
}
But now the order of the windows is random. Is it possible to implement some kind of global listener which listens for web element ID thru out the entire application and clicks it if it's present?
not sure about your specific situation but in vba I would write an if statement to see if it was true,
If driver.findelementsbyid("your Id").count > 0 then
driver.findelementbyid("your Id").click
Else
End if
Searching if the element exists should help you
WebElement elementName = driver.findElement(By.id("idElement"));
if(elementName != null){
//Loaded Element
}

Selenium - Determine whether web page is finished loading in Angular 2+

I have a Selenium test suite that is running Selenium integration tests against a number of web applications, some that are written in Angular 2+, and some that are written in AngularJS.
We use a custom ExpectedCondition with WebDriverWait that we use to make test cases wait until AngularJS apps have finished loading, in order to avoid waiting an arbitrary amount of time:
private static ExpectedCondition<Boolean> angularIsFinished() {
return new ExpectedCondition<Boolean>() {
public Boolean apply(final WebDriver driver) {
Object result = null;
while(result == null || result.toString().equals("undefined")) {
result = ((JavascriptExecutor)driver).executeScript("return typeof angular;");
try {
Thread.sleep(200L);
} catch (final InterruptedException ex) {
logger.error("Error while trying to sleep", ex);
}
}
final String script = " var el = document.querySelector(\"body\");\n" +
" var callback = arguments[arguments.length - 1];\n" +
" angular.element(el).injector().get('$browser').notifyWhenNoOutstandingRequests(callback);";
((JavascriptExecutor)driver).executeAsyncScript(script);
return true;
}
public String toString() {
return "Wait for AngularJS";
}
};
}
However, return typeof angular; will always return undefined for an Angular 2+ app. Is there a similar way to AngularJS's notifyWhenNoOutstandingRequests that you can use to determine when an Angular 2+ app has finished loading?
This question mentions using NgZone as a possible solution, but how would you get a handle on that via a script executed via JavascriptExecutor?
You can check it by calling e.g. document.querySelector('app-root')? or arbitrary component selector...
Or what about calling document.readyState? It should have result 'complete' after fully loaded wep page and it doesn't matter if web page is based on angular.
Thanks to #Ardesco's answer, I was able to do something similar to what Protractor does, using the window.getAllAngularTestabilities function. Here is the script that I run to determine if the Angular 2+ page loads:
var testability = window.getAllAngularTestabilities()[0];
var callback = arguments[arguments.length - 1];
testability.whenStable(callback);
And here is what the complete ExpectedCondition looks like that works for both AngularJS and Angular 2+:
private static ExpectedCondition<Boolean> angularIsFinished() {
return new ExpectedCondition<Boolean>() {
public Boolean apply(final WebDriver driver) {
Object result = null;
boolean isAngular2Plus = false;
while(result == null || result.toString().equals("undefined")) {
result = ((JavascriptExecutor)driver).executeScript("return typeof angular;");
if (result == null || result.toString().equals("undefined")) {
result = ((JavascriptExecutor)driver).executeScript("return typeof window.getAngularTestability;");
if (result != null && !result.toString().equals("undefined")) {
isAngular2Plus = true;
}
}
try {
Thread.sleep(200L);
} catch (final InterruptedException ex) {
logger.error("Error while trying to sleep", ex);
}
}
final String script;
if (isAngular2Plus) {
script =" var testability = window.getAllAngularTestabilities()[0];\n" +
" var callback = arguments[arguments.length - 1];\n" +
" testability.whenStable(callback);";
} else {
script =" var el = document.querySelector(\"body\");\n" +
" var callback = arguments[arguments.length - 1];\n" +
" angular.element(el).injector().get('$browser').notifyWhenNoOutstandingRequests(callback);";
}
((JavascriptExecutor) driver).executeAsyncScript(script);
return true;
}
public String toString() {
return "Wait for AngularJS";
}
};
}
Looking at the Protractor code I have come up with two possible solutions:
First of all we have an option where we find a list of testability's, then add a callback to all of them, and then wait for one of them to flag the site as testable (This does mean that your script will continue after any one testability has become testable, it will not wait for all of them to become testable).
private static ExpectedCondition angular2IsTestable() {
return (ExpectedCondition<Boolean>) driver -> {
JavascriptExecutor jsexec = ((JavascriptExecutor) driver);
Object result = jsexec.executeAsyncScript("window.seleniumCallback = arguments[arguments.length -1];\n" +
"if (window.getAllAngularTestabilities()) {\n" +
" window.getAllAngularTestabilities().forEach(function (testability) {\n" +
" testability.whenStable(window.seleniumCallback(true))\n" +
" }\n" +
" );\n" +
"} else {\n" +
" window.seleniumCallback(false)\n" +
"}"
);
return Boolean.parseBoolean(result.toString());
};
}
The second option is to specifically check an angular root elements testability state:
private static ExpectedCondition angular2ElementIsTestable(final WebElement element) {
return (ExpectedCondition<Boolean>) driver -> {
JavascriptExecutor jsexec = ((JavascriptExecutor) driver);
Object result = jsexec.executeAsyncScript(
"window.seleniumCallback = arguments[arguments.length -1];\n" +
"var element = arguments[0];\n" +
"if (window.getAngularTestability && window.getAngularTestability(element)) {\n" +
" window.getAngularTestability(element).whenStable(window.seleniumCallback(true));\n" +
"} else {\n" +
" window.seleniumCallback(false)\n" +
"}"
, element);
return Boolean.parseBoolean(result.toString());
};
}
The second option is more targeted and therefore more reliable if you want to test a specific area of the site.
A third option would be to write something a bit more complicated that tracks the state of all testability's and then only fires a true callback when all of them have become true. I don't have an implementation for this yet.

Java continue statement not allowed in anonymous inner class

I am threading a time consuming for-loop and executing them inside N number of threads. A continue statement is throwing error
Getting the error "Continue cannot be used outside of a loop"
for (final Message m : messagelistholder.getMessage()) {
Callable<Void> tasksToExecute = new Callable<Void>() {
public Void call() {
if (guidanceonly1 == true && !QuoteUtil.isECPQuote(list.get(0))) {
String msg = "Message From " + m.getSource() + " when retrieving Guidance values: "
+ m.getDescription();
String lcladdStatusMessages = CommonUtil.getLoclizedMsg(
"PRCE_LNE_ITM_MSG_FRM_WHN_RETRVNG_GUIDNCE_VAL",
new String[]{m.getSource(), m.getDescription()}, msg);
list.get(0).addStatusMessages("Info", lcladdStatusMessages);
} else if ("Error".equalsIgnoreCase(m.getSeverity())) {
if (m.getCode().indexOf("_NF") > 0) {
continue; // price not found due to private sku
}
if ("Eclipse".equalsIgnoreCase(m.getSource())) {
String msg1 = "Please check Sold To customer data. ";
String lcladdStatusMessages1 = CommonUtil
.getLoclizedMsg("PRCE_LNE_ITM_PLS_CHK_SLDTO_CUST_DTA", null, msg1);
String msg2 = "Discount information may not be returned from Optimus due to "
+ m.getSeverity() + " From " + m.getSource() + " " + m.getDescription();
String lcladdStatusMessages2 = CommonUtil.getLoclizedMsg(
"PRCE_LNE_ITM_DSCNT_INFO_MNT_RTRND_FRM_OPTMS_DUETO_FRM",
new String[]{m.getSeverity(), m.getSource(), m.getDescription()}, msg2);
list.get(0).addStatusMessages(m.getSeverity(),
(m.getDescription().contains("MDCP") ? lcladdStatusMessages1 : "")
+ lcladdStatusMessages2);
} else {
if (response1.getItems() == null) {
String lcladdStatusMessages = CommonUtil.getLoclizedMsg("PRCE_LNE_ITM_OPTMS_ERR",
new String[]{m.getSource(), m.getDescription()}, m.getDescription());
list.get(0).addStatusMessages("Error", lcladdStatusMessages);
list.get(0).setOptimusError(true);
} else {
if (!QuoteUtil.isECPQuote(list.get(0))) {
String lcladdStatusMessages = CommonUtil.getLoclizedMsg(
"PRCE_LNE_ITM_MSG_FRM_WHN_RETRVNG_GUIDNCE_VAL",
new String[]{m.getSource(), m.getDescription()},
"Message From " + m.getSource() + " " + m.getDescription());
list.get(0).addStatusMessages("Info", lcladdStatusMessages);
list.get(0).setOptimusError(true);
}
}
}
}
if (list.get(0).getFlags().get(QtFlagType.ESCALATIONFORPARTNER) != null) {
list.get(0).getFlags().get(QtFlagType.ESCALATIONFORPARTNER).setFlgVl(null);
}
if (m.getCode() != null) {
String pricingServiceMsgCode = m.getCode();
String pricingServiceSeverity = m.getSeverity();
Map<Integer, AutoEscalationScenario> categoryMap;
if (StringUtils.equals("ERROR", pricingServiceSeverity)) {
categoryMap = getScenario("SEVERITY", globalAccount1, null, true, null);
if (categoryMap.size() != 0) {
finalCategorylist.get(0).putAll(categoryMap);
}
}
if (partnerExclusivityAutoEscalation1) {
categoryMap = getScenario(pricingServiceMsgCode, globalAccount1, null, true, null);
if (categoryMap != null && categoryMap.size() != 0) {
finalCategorylist.get(0).putAll(categoryMap);
}
}
}
return null;
}
};
runnableTasks.add(tasksToExecute);
}
Can someone help me to skip the particular loop for the speicified condition but without using continue statement since it throws error.
What's happening is that you are actually calling continue outside of a loop because the call() function itself does not have a for loop, so it doesn't matter if are only calling call() from a loop.
What can you do to fix this is making the call function to return a boolean and replacing the continues with return true and return false if no return true has been reached.
Then replace the:
call()
on the loop(s) for
if(call()) continue
So the I'm not saying I fully understand you code, but it appears that you are using continue to break out of that thread. On a normal multi-threaded application, it looks like you are launching multiple threads from one one loop. The continue call is inside the new thread, not the loop. As soon as you start writing the call() method, you leave the loop to run it. Looking at the code, I would try replacing continue with return. Normally I would try running it myself before I suggest it, but without the rest of the code I cannot verify that it works.

try catch until success java

I get Stale Element Reference Exception.If I can single click.
I want to click on element until or 5 times find the object.
How can I have try catch block loop until click or element found?
I want it to attempt to click on element for 5 times before failing it.
I use below code but not working.
Click Method:
public void click1(WebDriver driver, WebElement element, String name) {
int attempts = 0;
while(attempts < 5) {
try {
element.click();
Add_Log.info("Successfully clicked on " + name);
Reporter.log("Successfully clicked on " + name);
break;
} catch (Exception e) {
try {
JavascriptExecutor executor = (JavascriptExecutor) driver;
executor.executeScript("arguments[0].click();", element);
Add_Log.info("Successfully clicked on " + name);
Reporter.log("Successfully clicked on " + name);
break;
} catch (Exception e2) {
Add_Log.info("Not able to click " + name);
Reporter.log("Not able to click " + name);
TestResultStatus.Testfail = true;
Assert.fail();
}
}
attempts++;
}
}
This is actually as easy as changing the loop condition from attempts < 5 to true and removing the attempts++; line. At least that's what I understood from your question. If that's not what you're looking for, try rephrasing the question more clearly.
I would write it more like the below. You attempt to do a normal click 5 times with a brief pause between attempts. If an exception is thrown, it's eaten and another attempt is made. If none of those 5 are successful, you make a single attempt to click on it using JS. If that fails, then log failures, etc.
public void click1(WebDriver driver, WebElement element, String name) {
int attempts = 0;
while(attempts < 5) {
try {
element.click();
Add_Log.info("Successfully clicked on " + name);
Reporter.log("Successfully clicked on " + name);
return;
} catch (Exception e) {
}
attempts++;
Thread.Sleep(500); // brief pause between attempts
}
try {
JavascriptExecutor executor = (JavascriptExecutor) driver;
executor.executeScript("arguments[0].click();", element);
Add_Log.info("Successfully clicked on " + name);
Reporter.log("Successfully clicked on " + name);
return;
} catch (Exception e2) {
Add_Log.info("Not able to click " + name);
Reporter.log("Not able to click " + name);
TestResultStatus.Testfail = true;
Assert.fail("Not able to click " + name);
}
}
NOTE: You probably would be better off waiting for the element to be clickable before attempting to click it. That would probably remedy most of your issues. You still may have an issue with some dialog/banner/spinner overlapping the element that you would need to deal with though... and you could deal with that with the 5 attempted clicks, etc.

Unable to load entire page using Selenium PhantomJs driver

I am using Selenium library in Java to scrap a site.I am using PhantomJsDriver as webdriver.This site has some urls present in list(li) tags which I am interested in.The problem is that the site has 64 (li) elements but I am receiving only 16 (li) elements.Here is my code:
DesiredCapabilities caps=new DesiredCapabilities();
caps.setJavascriptEnabled(true);
caps.setCapability(PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY , "Path");
WebDriver driver=new PhantomJSDriver(caps);
driver.get("Some Website");
WebDriverWait wait=new WebDriverWait(driver, 600);
wait.until(new ExpectedCondition<Boolean>() {
boolean resetCount=true;
int counter=5;
#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");
}
});
BufferedWriter bw=new BufferedWriter(new FileWriter(new File("C:\\abc.txt")));
bw.write(driver.getPageSource());
bw.close();
driver.quit();
I have reused the code in wait.until() from an answer.My question is that why is it returning only 16 elements? I assume that it should return none or all elements.Is there any limit on number of tags or document size?.What is the solution here?
try to add
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.
WebDriver driver=new PhantomJSDriver(caps);
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);

Categories

Resources