Cannot get innerHTML from WebElement which is confirmed to be present - java

I am trying to get the innerHTML value from this HTML, using Selenium WebDriver.
<div class="map-overlay-network">Newham : NSG Designated Streets (Type 1/2)</div>
This piece of code should confirm that the element is present:
public boolean isMapOverlayNetworkPresent() {
By byExpression = By.className(mapOverlayNetworkClassName);
return isWebElementPresent(byExpression);
}
My elements are defined at the top of the class:
private static final String mapOverlayNetworkClassName = "map-overlay-network";
#FindBy(className=mapOverlayNetworkClassName) private WebElement mapOverlayNetwork;
This is the code for function isMapOverlayNetworkPresent:
public boolean isWebElementPresent(By byExpression) {
WebDriverWait wait = new WebDriverWait(driver, 60);
try {
wait.until(ExpectedConditions.presenceOfElementLocated(byExpression));
return true;
} catch (TimeoutException e) {
System.out.println("Timeout waiting for presence of element " + byExpression);
return false;
}
}
Here is where I try to get the innerHTML:
public String returnDefaultNetwork() {
String defaultNetwork = mapOverlayNetwork.getAttribute("innerHTML");
System.out.println("Default network = " + defaultNetwork);
return defaultNetwork;
}
This is the report from my console:
Is default network shown on map: true
Default network =
If I load the page in Firefox and use Developer Tools, I can see the element using the inspector. If I right click on the element in the Inspector & select Copy InnerHTML, I get this value:
Newham : NSG Designated Streets (Type 1/2)
This is the value I want.
This does not work in any of the browsers I am testing, i.e. Firefox, Chrome or Edge.
Any suggestions?
A previous element on the screen works fine. This is how it looks in HTML:
<div class="map-overlay-customer">Newham</div>
This is how it is defined in my PageObject class:
public static final String mapOverlayCustomerClassName = "map-overlay-customer";
#FindBy(className=mapOverlayCustomerClassName) private WebElement mapOverlayCustomer;
This is me returning the InnerHTML:
public String returnDefaultCustomer() {
return mapOverlayCustomer.getAttribute("innerHTML");
}
This is the response from the console:
Default customer: Newham
Update 21/12/2017
Following a suggestion below, I added a wait for visibility after detecting the presence of my element.
private void waitForVisibility(WebElement element) throws Error {
// time out in seconds
try {
new WebDriverWait(driver, 60).until(ExpectedConditions.visibilityOf(element));
} catch (TimeoutException e) {
System.out.println("Timeout waiting for presence of element " + element);
}
}
public boolean isMapOverlayNetworkVisible() {
waitForVisibility(mapOverlayNetwork);
return mapOverlayNetwork.isDisplayed();
}
In my Test class:
reportAssert("Is default network present on map", alloyLoggedInPage.isMapOverlayNetworkPresent());
reportAssert("Is default network visible on map", alloyLoggedInPage.isMapOverlayNetworkVisible());
System.out.println("Default network: " + alloyLoggedInPage.returnDefaultNetwork());
My result:
Is default network present on map: true
Is default network visible on map: true
Get default network.
Default network = Newham : NSG Designated Streets (Type 1/2)
Default network: Newham : NSG Designated Streets (Type 1/2)

Try to use .getAttribute("value") or .getText() for your web element.
PS: But it's really strange that .getAttribute("innerHTML") does not work.
PSS: Also try to check the value of element in Console of browser by running JavaScript:
document.querySelector(".map-overlay-network").innerHTML;
PSSS: Also, I want to recommend to add one more wait with ExpectedConditions.visibilityOfElementLocated(By.id<locator>‌​) after your wait, because after your wait element just in DOM, but not visible.

Related

How to handle script failure due to server response time in Selenium Webdriver?

I am a beginner for Selenium Webdriver, I have written a script in Java to test a functionality, and it is working fine. Sometimes I faces an issue.
Suppose I just click on create button to create something (let suppose customer) and after this I need to do some work with a screen which comes after create successfully customer. Sometimes due to slow response from server, my script get failed due to search a DOM element which comes after create customer.
If response come with in predefined time in my code, no issue, if not come then script failed (it search a element which has not rendered yet).
1) click on button
try{
// let suppose creatButtonElement is the web element of Create Button.
createButtonElement.click();
}catch(Exception e){
throw new Exception("Unable To Click on element [ " + element + " ] , plz see screenshot [ UnableToClick_" + element);
}
Expecting: after click on create button my script is expecting success message for assertion.
I had faced this issue once but I had handled this manually. This will work if after click button loader is appearing. It waits for one minute.
Please use the following code to wait manually to get response of server. It check the visibility of loader to know the response each second.
public static void loading_wait() throws Throwable {
int i = 0;
int maxloopDependOnBrowser = 60;
int totalSecond=0;
boolean loadinImageTakingMuchTime=false;
try{
while (true) {
i++;
if( !(loaderDisplayed(APP_LoadingImage_xpath)) ){
totalSecond+=i;
break;
}
if (i > maxloopDependOnBrowser) {
totalSecond=maxloopDependOnBrowser + 1;
loadinImageTakingMuchTime=true;
break;
} else {
totalSecond=i;
Thread.sleep(1000);
}
}
Thread.sleep(1000);
if(loadinImageTakingMuchTime){
throw new Throwable();
}
}catch (Throwable t) {
throw new Exception("FAILED:>>> Loading image is taking too much time :>>"+Throwables.getStackTraceAsString(t));
}
}
XpathKey :- to find the loader element
public static boolean loaderDisplayed(String XpathKey) {
int i = 0;
try {
driver.manage().timeouts().implicitlyWait(5, TimeUnit.MILLISECONDS);
List<WebElement> elementList = getORObject_list(XpathKey/*, 0, 500*/);
for (Iterator<WebElement> iterator = elementList.iterator(); iterator.hasNext();) {
WebElement webElement = (WebElement) iterator.next();
if (webElement.isDisplayed()) {
i = 1;
break;
}
}
} catch (Throwable t) {
}
finally {
driver.manage().timeouts().implicitlyWait(Long.parseLong(1), TimeUnit.SECONDS);
}
if (i == 0) {
return
} else {
return true;
}
}
You can join waiting
WebDriverWait wait = new NWebDriverWait(driver, 10); //10 second
wait.until(ExpectedConditions.presenceOfElementLocated(By.id("btn1")));
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("btn1")));
wait.until(ExpectedConditions.elementToBeClickable(By.id("btn1")));

Unable to handle alert using phantomJS in Java

I have a Java code as below and when I am running through PhantomJs getting "Unsupported Command Exception" but it is working fine if I run through firefox and chrome:-
Note: With phantomJs we could able to execute till 3rd step in below code.I searched in many blogs but those answers didn't solve my problem.
1. cvvField.sendKeys(cvcData);
2. proceedToPayBtn.click();
3. Reporter.log("Card details are submitted from payment UI page");
4. Alert a1=driver.switchTo().alert();
5. Reporter.log("Alert with text:"+a1.getText());
6. a1.accept();
Here cvvField and proceedToPayBtn are WebElements and cvcData have value as "111".
Error log:-
org.openqa.selenium.UnsupportedCommandException: Invalid Command Method -
{"headers":{"Accept-Encoding":"gzip,deflate","Cache-Control":"no-cache","Connection":"Keep-Alive","Host":"localhost:30462","User-Agent":"Apache-HttpClient/4.5.1 (Java/1.8.0_101)"},"httpVersion":"1.1","method":"GET","url":"/alert_text","urlParsed":{"anchor":"","query":"","file":"alert_text","directory":"/","path":"/alert_text","relative":"
/alert_text","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/alert_text","queryKey":{},"chunks":["alert_text"]},"urlOriginal":"/session/9e392a50-ce79-11e6-b24a-2b12cf1ec4d6/alert_text"}
Command duration or timeout: 31 milliseconds
I have edited above code as below but same error is coming.Please suggest
if (driver 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();
}
I am getting "Alert has been handled" in output console but alert is not handled.
Some issue due to wait time can be the source of your problem
The code above can help to wait until element is visible (since the wait of ngWebDriver or Selenium Webdriver are not compatible with PhantomJS)
public static String waitJSResponse(PhantomJSDriver driver, String script) {
String ReturnedValue = null;
int sleeper = 10;
Boolean flag = false;
int timeOut = 30000;
int i = 0;
while ((!flag) & ((i*sleeper)<timeOut)) {
try {
Thread.sleep(sleeper);
ReturnedValue = (String) driver.executeScript(script);
} catch (Exception e) {
flag = false;
i++;
}
if (ReturnedValue != null) {
flag = true;
System.out.println("Overall wait time is : "+(i * sleeper)+" ms \n\r");
break;
}
}
return ReturnedValue;
}
This code will wait 10ms then verify that the element is visble, if there is an exception, it will loop again.
The returned value must be a text, an object or anything that is not null.
the script value must be your JS script to get the correct element.
Hope it work.
I tried the above code by:-
1.Creating a class "Test" and writing above method in it.
2.Above method is called by creating an object(TestObject) as
TestObject.waitJSResponse((PhantomJSDriver) driver, "window.confirm = function(){return true;};");
But ReturnedValue in
try
{
Thread.sleep(sleeper);
ReturnedValue = (String) driver.executeScript(script);
System.out.println(ReturnedValue);
}
returns null.So Can u please help with this?

assertEquals works in selenium but not in JAVA

I made a testcase in selenium which repeats perfectly and then exported it to JAVA /JUnit4 / Webdriver :
public void emailInvalid() throws Exception {
driver.get(baseUrl + "/test/contacts.html");
driver.findElement(By.name("companyName")).clear();
driver.findElement(By.name("companyName")).sendKeys("testcomp");
driver.findElement(By.name("phone")).clear();
driver.findElement(By.name("phone")).sendKeys("45454545");
driver.findElement(By.name("email")).clear();
driver.findElement(By.name("email")).sendKeys("test.ee");
driver.findElement(By.name("message")).clear();
driver.findElement(By.name("message")).sendKeys("qwerty");
driver.findElement(By.cssSelector("button.submit")).click();
assertEquals("Not valid email.", driver.findElement(By.cssSelector("span.error.notValidEmail")).getText());
}
The test fails in Java because assertEquals can't get the text its looking for. The error message is
org.junit.ComparisonFailure: expected:<[Not valid email]> but was:<[]>
In most cases your problem would be bad synchronization.
Your element is found but its text is empty.
You can try touse webDriverWait with expecting the stalenessOf, you can change the way an element is located by using its expected text in the locator or you can add very short sleep
Apparently the element cannot be found by the css selector and thereby the assertion fails.
Maybe the element is loaded after the assertion is executed or the element is not loaded at all.
Try to wait for the element to be loaded before the assertion using the following code:
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("span.error.notValidEmail")));
assertEquals("Not valid email.", driver.findElement(By.cssSelector("span.error.notValidEmail")).getText());
If this is not the case then check again if the selector is correct.
Also check what getText() returns by printing the actual string.
Try waiting for the text present and use an assert if the text is located within the specified time interval.
Also be sure to check the uniqueness of the element using your css locator.
public void emailInvalid() throws Exception {
driver.get(baseUrl + "/test/contacts.html");
driver.findElement(By.name("companyName")).clear();
driver.findElement(By.name("companyName")).sendKeys("testcomp");
driver.findElement(By.name("phone")).clear();
driver.findElement(By.name("phone")).sendKeys("45454545");
driver.findElement(By.name("email")).clear();
driver.findElement(By.name("email")).sendKeys("test.ee");
driver.findElement(By.name("message")).clear();
driver.findElement(By.name("message")).sendKeys("qwerty");
driver.findElement(By.cssSelector("button.submit")).click();
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("span.error.notValidEmail")));
assertTrue(waitForTextPresent(driver, By.cssSelector("span.error.notValidEmail"), "Not valid email.", 20));
}
public static boolean waitForTextPresent(WebDriver driver, By locator, String text, int timeOut) {
int i = 0;
int WAIT_SLEEP_INTERVAL = 500;
boolean isTextPresent = false;
while (!isTextPresent) {
i = i + 1;
try{
Thread.sleep(WAIT_SLEEP_INTERVAL);
} catch(Exception e) {
//do nothing
}
isTextPresent = driver.findElement(locator).getText().contains(text);
if (i * WAIT_SLEEP_INTERVAL >= timeOut) {
return false;
}
}
return true;
}
Actually you can also do a get text after the line:
wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("span.error.notValidEmail")));
System.out.println(driver.findElement(By.cssSelector("span.error.notValidEmail")).getText());
And see if you are getting the text that you are looking for. You may not need to use the method waitForTextPresent in that case.
Try to check what value of baseUrl. Is it equals "http://yousite" or just ".." or so on? Try to debug this method may be Java didn't found correct url. Or use logging and logging baseUrl + "/test/contacts.html". It look like problem with baseUrl.

StateElementReferenceException in Selenium

I am getting a StateElementReferenceException when I try to perform a drag-and-drop action, see the code snippets below. Can anyone please help to solve this with appropriate suggestions and explanations?
#Test(priority=4)
public void addUserBySearch() {
driver.findElement(By.xpath(OR.getProperty("btnUserGroup"))).click();
driver.findElement(By.xpath(OR.getProperty("btnCreateUG"))).click();
driver.findElement(By.xpath(OR.getProperty("textUGName"))).sendKeys("UserGroup:" + Utils.randGen());
driver.findElement(By.xpath(OR.getProperty("userSearchField"))).sendKeys("testuser2", Keys.ENTER);
source = driver.findElement(By.xpath(OR.getProperty("searchedUserSource")));
destination = driver.findElement(By.xpath(OR.getProperty("userDestination")));
waitUntilElementVisible(30, source);
dragAndDrop(source, destination);
driver.findElement(By.xpath(OR.getProperty("btnScheduleNow"))).click();
}
public void waitUntilElementVisible(int seconds, WebElement element) {
WebDriverWait explicitWait = new WebDriverWait(driver, seconds);
explicitWait.until(ExpectedConditions.visibilityOf(element));
}
public void dragAndDrop(WebElement sourceElement, WebElement destinationElement){
try {
if (sourceElement.isDisplayed() && destinationElement.isDisplayed()) {
Actions action = new Actions(driver);
action.dragAndDrop(sourceElement, destinationElement).build().perform();
}
else {
System.out.println("Element not found to drag and drop");
}
}
catch (StaleElementReferenceException exc) {
exc.printStackTrace();
}
catch (NoSuchElementException exc) {
exc.printStackTrace();
}
}
btnUserGroup = //*[text()='User Groups']
btnCreateUG = //*[#id='stage']/div/div[2]/div/div/div[2]/div[3]/a
textUGName = //input[#id='user_group_name']
btnScheduleNow = //*[text()='Schedule Now']
userDestination = //*[#class='ConnectedList ConnectedListAdded']/div[2]/ul
userSearchField = //div[#class='ConnectedListConnectedListSelect']/div[2]/div[1]/ul/li[1]/input
searchedUserSource = //div[#class='ConnectedList ConnectedListSelect']/div[2]/ul/li/span[5]
Exception:
org.openqa.selenium.StaleElementReferenceException: Element not found in the cache - perhaps the page has changed since it was looked up
Command duration or timeout: 10.28 seconds
A StaleReferenceException occurs for mainly one of two reasons:
The element has been deleted entirely.
The element is no longer attached to the DOM.
One possible solution to your problem is to surround dragAndDrop() in a while loop, and continually try and dragAndDrop() until you succeed. So something like the following:
boolean draggedAndDropped = false;
while(!draggedAndDropped ) {
try{
source = driver.findElement(By.xpath(OR.getProperty("searchedUserSource")));
destination = driver.findElement(By.xpath(OR.getProperty("userDestination")));
dragAndDrop(source, destination);
draggedAndDropped = true;
} catch(StaleElementReferenceException e) {
System.out.println("StaleElementReferenceException caught, trying again");
}
}
Of course its never a good idea idea to give allow a loop to loop infinitely, so you will want to incorporate a max attempts into the while loop.
As stated by the Selenium project's documentation, a StaleElementReferenceException can be thrown for two reasons:
The element has been deleted entirely.
The element is no longer attached to the DOM.
As such, I suspect that a race condition is occurring at this point:
driver.findElement(By.xpath(OR.getProperty("userSearchField"))).sendKeys("testuser2", Keys.ENTER);
source = driver.findElement(By.xpath(OR.getProperty("searchedUserSource")));
After you've entered "testuser2" in the "userSearchField" WebElement you've used Keys.ENTER to presumably submit the search query - the problem may be occurring because WebDriver is retrieving a reference to the "searchedUserSource" WebElement before the page has fully refreshed.
To get around this, you could try using the WebElement.submit() method to submit the search as it blocks the WebDriver's execution until the page has finished changing (i.e. finished displaying the search result).
Below is an example of how you could implement this:
driver.findElement(By.xpath(OR.getProperty("userSearchField"))).sendKeys("testuser2").submit();
source = driver.findElement(By.xpath(OR.getProperty("searchedUserSource")));

Assert that a WebElement is not present using Selenium WebDriver with java

In tests that I write, if I want to assert a WebElement is present on the page, I can do a simple:
driver.findElement(By.linkText("Test Search"));
This will pass if it exists and it will bomb out if it does not exist. But now I want to assert that a link does not exist. I am unclear how to do this since the code above does not return a boolean.
EDIT This is how I came up with my own fix, I'm wondering if there's a better way out there still.
public static void assertLinkNotPresent (WebDriver driver, String text) throws Exception {
List<WebElement> bob = driver.findElements(By.linkText(text));
if (bob.isEmpty() == false) {
throw new Exception (text + " (Link is present)");
}
}
It's easier to do this:
driver.findElements(By.linkText("myLinkText")).size() < 1
I think that you can just catch org.openqa.selenium.NoSuchElementException that will be thrown by driver.findElement if there's no such element:
import org.openqa.selenium.NoSuchElementException;
....
public static void assertLinkNotPresent(WebDriver driver, String text) {
try {
driver.findElement(By.linkText(text));
fail("Link with text <" + text + "> is present");
} catch (NoSuchElementException ex) {
/* do nothing, link is not present, assert is passed */
}
}
Not Sure which version of selenium you are referring to, however some commands in selenium * can now do this:
http://release.seleniumhq.org/selenium-core/0.8.0/reference.html
assertNotSomethingSelected
assertTextNotPresent
Etc..
There is an Class called ExpectedConditions:
By loc = ...
Boolean notPresent = ExpectedConditions.not(ExpectedConditions.presenceOfElementLocated(loc)).apply(getDriver());
Assert.assertTrue(notPresent);
Try this -
private boolean verifyElementAbsent(String locator) throws Exception {
try {
driver.findElement(By.xpath(locator));
System.out.println("Element Present");
return false;
} catch (NoSuchElementException e) {
System.out.println("Element absent");
return true;
}
}
With Selenium Webdriver would be something like this:
assertTrue(!isElementPresent(By.linkText("Empresas en Misión")));
boolean titleTextfield = driver.findElement(By.id("widget_polarisCommunityInput_113_title")).isDisplayed();
assertFalse(titleTextfield, "Title text field present which is not expected");
It looks like findElements() only returns quickly if it finds at least one element. Otherwise it waits for the implicit wait timeout, before returning zero elements - just like findElement().
To keep the speed of the test good, this example temporarily shortens the implicit wait, while waiting for the element to disappear:
static final int TIMEOUT = 10;
public void checkGone(String id) {
FluentWait<WebDriver> wait = new WebDriverWait(driver, TIMEOUT)
.ignoring(StaleElementReferenceException.class);
driver.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
try {
wait.until(ExpectedConditions.numberOfElementsToBe(By.id(id), 0));
} finally {
resetTimeout();
}
}
void resetTimeout() {
driver.manage().timeouts().implicitlyWait(TIMEOUT, TimeUnit.SECONDS);
}
Still looking for a way to avoid the timeout completely though...
You can utlilize Arquillian Graphene framework for this. So example for your case could be
Graphene.element(By.linkText(text)).isPresent().apply(driver));
Is also provides you bunch of nice API's for working with Ajax, fluent waits, page objects, fragments and so on. It definitely eases a Selenium based test development a lot.
For node.js I've found the following to be effective way to wait for an element to no longer be present:
// variable to hold loop limit
var limit = 5;
// variable to hold the loop count
var tries = 0;
var retry = driver.findElements(By.xpath(selector));
while(retry.size > 0 && tries < limit){
driver.sleep(timeout / 10)
tries++;
retry = driver.findElements(By.xpath(selector))
}
Not an answer to the very question but perhaps an idea for the underlying task:
When your site logic should not show a certain element, you could insert an invisible "flag" element that you check for.
if condition
renderElement()
else
renderElementNotShownFlag() // used by Selenium test
Please find below example using Selenium "until.stalenessOf" and Jasmine assertion.
It returns true when element is no longer attached to the DOM.
const { Builder, By, Key, until } = require('selenium-webdriver');
it('should not find element', async () => {
const waitTime = 10000;
const el = await driver.wait( until.elementLocated(By.css('#my-id')), waitTime);
const isRemoved = await driver.wait(until.stalenessOf(el), waitTime);
expect(isRemoved).toBe(true);
});
For ref.: Selenium:Until Doc
The way that I have found best - and also to show in Allure report as fail - is to try-catch the findelement and in the catch block, set the assertTrue to false, like this:
try {
element = driver.findElement(By.linkText("Test Search"));
}catch(Exception e) {
assertTrue(false, "Test Search link was not displayed");
}
This is the best approach for me
public boolean isElementVisible(WebElement element) {
try { return element.isDisplayed(); } catch (Exception ignored) { return false; }
}
For a JavaScript (with TypeScript support) implementation I came up with something, not very pretty, that works:
async elementNotExistsByCss(cssSelector: string, timeout=100) {
try {
// Assume that at this time the element should be on page
await this.getFieldByCss(cssSelector, timeout);
// Throw custom error if element s found
throw new Error("Element found");
} catch (e) {
// If element is not found then we silently catch the error
if (!(e instanceof TimeoutError)) {
throw e;
}
// If other errors appear from Selenium it will be thrown
}
}
P.S: I am using "selenium-webdriver": "^4.1.1"
findElement will check the html source and will return true even if the element is not displayed. To check whether an element is displayed or not use -
private boolean verifyElementAbsent(String locator) throws Exception {
boolean visible = driver.findElement(By.xpath(locator)).isDisplayed();
boolean result = !visible;
System.out.println(result);
return result;
}
For appium 1.6.0 and above
WebElement button = (new WebDriverWait(driver, 10).until(ExpectedConditions.presenceOfElementLocated(By.xpath("//XCUIElementTypeButton[#name='your button']"))));
button.click();
Assert.assertTrue(!button.isDisplayed());

Categories