How do I click depending on state of toggle switch? - selenium

I have a toggle switch I want to click depending on what the switch state is.
If it is "span.switch-right" I want to do:
findElement(By.cssSelector("span.switch-left")).click();
If it is "span.switch-left" I want to do:
findElement(By.cssSelector("span.switch-right")).click();
HTML:
<div tabindex="0" class="has-switch switch-on switch-animate">
<div>
<span class="switch-left">ON</span>
<label for="profile_isProfileSharedWithNearby"> </label>
<span class="switch-right">OFF</span>
<input id="profile_isProfileSharedWithNearby" name="profile[isProfileSharedWithNearby]" class="form-control-borderless hide" value="1" checked="checked" type="checkbox">
</div>
</div>

Assuming the text is reliable, you could use an xpath selector for this:
findElement(By.xpath("//span[contains(#class, 'switch-') and contains(text(), 'OFF')]")).click();
This will always click the OFF switch.

You probably want to give Fluent Wait a try. It gives you the ability to wait for an element bypassing some exception types and poll DOM after a certain period of time and make sure if that exists or not.
By by = By.cssSelector("span.switch-left");
// Waiting 30 seconds for an element to be present on the page, checking
// for its presence once every 5 seconds.
FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, SECONDS)
.pollingEvery(5, SECONDS)
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(by);
}
});
foo.click();
Taken from here
Edit
Provided solution after confusing(;-)) discussion
//*[#tabindex='0'][contains(#class,'switch-off')]

You can check the switch state by following code and can switch it off its on
List<WebElement> switchElement = driver.findElements(By
.cssSelector("div.has-switch.switch-on.switch-animate"));
System.out.println(switchElement.size() + " : Switch Size");
// Check its on, if its on then switch it off
if (switchElement.size() != 0) {
switchElement.get(0)
.findElement(By.cssSelector("span.switch-left")).click();
} else
System.out.println("Switch is already off");

Related

Selenium webdriver wait doesn't seem to work in case of overlay

There is an overlay ( a grey color translucent screen ) that comes up when ever one clicks Login button and it stays for few seconds. Because of this, selenium web driver isn't able to find the elements as this overlay kinds of hides them for a while or at least that is what looks to me. How can I handle this? I don't find Thread.sleep to be an efficient way here.
I tried -
public void login(){
WebDriverWait wait = new WebDriverWait(driver, 60);
wait.until(ExpectedConditions.invisibilityOfElementLocated((By.id("ajax-overlay"))));
wait.until(ExpectedConditions.elementToBeClickable((By.id("okbutton))));
driver.findElement(By.id("username)).sendKeys("admin");
driver.findElement(By.id("password")).sendKeys("admin123");
driver.findElement(By.id("okbutton")).click();
wait.until(ExpectedConditions.invisibilityOfElementLocated((By.id("ajax-overlay"))));
}
but nothing seems to work and I still get error -
org.openqa.selenium.WebDriverException: unknown error: Element <button id="loginDialog:okButton" name="loginDialog:okButton" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only ui-panel-titlebar-icon synchronous" onclick="PrimeFaces.ab({source:'loginDialog:okButton',process:'loginDialog:okButton loginDialog:username loginDialog:password loginDialog:okButton',update:'startingCashFocus loginDialog:dialogFocus loginDialog:lblPassword loginDialog:lblUsername loginDialog:messages',oncomplete:function(xhr,status,args){handleLoginAttempt(xhr, status, args, loginWidget, null); ;}});return false;" tabindex="1" type="submit" role="button" aria-disabled="false">...</button> is not clickable at point (931, 250). Other element would receive the click: <div id="ajax-overlay" class="ui-blockui ui-widget-overlay ui-helper-hidden eternal" style="display: block;"></div>
Also, there is no way to find out the overlay id and thankfully, selenium gave it in its error details.
Try to click element with one of the following method, which will solve this Exception :
Actions action = new Actions(driver);
action.moveToElement(driver.findElement(By.id('okbutton'))).click().perform();
OR
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].click();", driver.findElement(By.id('okbutton')));

Selenium Webdriver wait Expected condition failed: waiting for visibility of element located by By.id

I am trying to put selenium web driver wait, but always I am getting an exception "
org.openqa.selenium.TimeoutException: Expected condition failed: waiting for visibility of element located by By.id: mobileNo (tried for 20 second(s) with 100 milliseconds interval)".
I increased seconds to 100, then also getting the same problem, my id is correct.
WebDriver d = new ChromeDriver();
d.get("http://myurlOne");
WebElement username = d.findElement(By.id("username_id"));
username.sendKeys("123");
WebElement password = d.findElement(By.id("password_id"));
password.sendKeys("123");
d.findElement(By.id("loginButton")).click();
System.out.println("logged in successfully");
d.get("http://navigatedurl");
JavascriptExecutor js = (JavascriptExecutor)d;
System.out.println("navigated to new page");
WebDriverWait wait__mob = new WebDriverWait(d, 20);
try {
System.out.println("Start"+new Date());
wait__mob .pollingEvery(100,TimeUnit.MILLISECONDS).until(ExpectedConditions.visibilityOfElementLocated(By.id("mobileNo")));
d.findElement(By.id("mobileNo")).sendKeys("99999999999);
} catch (TimeoutException e) {
// TODO: handle exception
System.out.println(e.toString());
}
Div code:
<div class="form-group">
<label class="col-xs-5 control-label" for="mobileNo">Mobile No.</label>
<div class="col-xs-6 leftpadding-none">
<input type="tel" class="form-control k-input" id="mobileNo"
name="inputmobileNo" placeholder="" maxlength="10"> <!--required
pattern="\d{10}" validationMessage="Mobile No. is Required"-->
</div>
As per the Java Docs of WebDriverWait Class if you want to change the Polling Interval you need to change it in the constructor as the constructor is as follows :
WebDriverWait(WebDriver driver, long timeOutInSeconds, long sleepInMillis)
Wait will ignore instances of NotFoundException that are encountered (thrown) by default in the 'until' condition, and immediately propagate all others.
Moving forward as you are trying to invoke sendKeys() on the element you need to invoke the ExpectedConditions method elementToBeClickable.
So your code will be :
WebDriver d = new ChromeDriver();
d.get("http://myurlOne");
WebElement username = d.findElement(By.id("username_id"));
username.sendKeys("123");
WebElement password = d.findElement(By.id("password_id"));
password.sendKeys("123");
d.findElement(By.id("loginButton")).click();
System.out.println("logged in successfully");
d.get("http://navigatedurl");
System.out.println("navigated to new page");
WebDriverWait wait__mob = new WebDriverWait(d, 20);
try {
System.out.println("Start"+new Date());
wait__mob.until(ExpectedConditions.elementToBeClickable(By.xpath("//div[#class='form-group']//label[contains(.,'Mobile No.')]//following::div[1]/input[#class='form-control k-input' and #id='mobileNo' and #type='tel']"))).sendKeys("9999999999);
} catch (TimeoutException e) {
System.out.println(e.toString());
}

Stale element error while getting text of element

I want to get the text of li (second) element as below. Code is able to find the element but it is throwing the error while fetching the gettext. Please help.
WebElement element = driver.findElement(By.xpath("//div[contains(#id,'location_group')]/div/ul/li[2]"));
element.getText();
Error
Stale element reference: element is not attached to the page document
HTML
<div id=location_group>
<div>
<ul class="og-tooltip js-og-tooltip" style="display: none; opacity: 100;">
<li class="title_text">Organization Group</li>
<li class="value_text" style="background: rgb(204, 136, 136); border: 2px solid red;">Global / Aricent / gemsecure </li>
<li> </li>
<li class="title_text">Group ID</li>
<li class="value_text">gemsecure</li>
</ul>
</div>
</div>
May be you have to wait for the parent element to be visible then interact with it
WebElement elementUL = driver.findElement(By.xpath("//div[contains(#id,'location_group')]/div/ul"));
WebDriverWait wait=new WebDriverWait(driver, 60);
wait.until(ExpectedConditions.visibilityOf(elementUL));
WebElement element = driver.findElement(By.xpath("//div[contains(#id,'location_group')]/div/ul/li[2]"));
element.getText();
Because this element is wrapped with a ul that has display: none selenium can not interact with it.
Options to try:
element.getAttribute("innerHTML");
or you can use the JavascriptExecutor:
JavascriptExecutor executor = (JavascriptExecutor)driver;
String text= executor.executeScript("document.document.getElementsByClassName('value_text')[0].innerHTML");
Another option is to use querySelector/querySelectorAll which has broader support than getElementsByClassName
Place a explicit waitWebDriverWait and wait till element to be visible
WebElement ele = driver.findElement(By.xpath("Your locator "));
WebDriverWait wait=new WebDriverWait(driver, 25);
wait.until(ExpectedConditions.visibilityOf(ele));
and then getText()
What I recommend is one use the xPath. I think I've tried every solution in java's selenium library, thus my website had tricky selects - once user picks an option, the options are reloaded (ex. selected value sometimes disappears, sometimes different options where loaded depends on particular select).
Lot of stale element exceptions.
What I've used:
private WebElement getDesiredOptionByVisibleText(WebDriver driver, String selectId, String text) {
List<WebElement> options = driver.findElements(By.xpath("//select[#id='" + selectId
+ "']/option[contains(text(),'" + text + "')]"));
if (options == null || options.size() == 0) {
return null;
} else {
return options.get(0);
}
}
especially use this method with waits, for example my wait:
private void waitUntilDesiredOptionVisible(WebDriver driver, String selectId) {
getFluentWait(driver).until(d -> (getDesiredOptionByVisibleText(driver, selectId, value) != null));
}
public static FluentWait<WebDriver> getFluentWait(WebDriver driver) {
return new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(60))
.pollingEvery(Duration.ofMillis(100));
}
Last but not least clicking that option.
private void selectByVisibleTextRegex(WebDriver driver, String selectId) {
WebElement option = getDesiredOptionByVisibleText(driver, selectId, value);
if (option == null) {
throw new NoSuchElementException(String.format("Cannot locate element with text like: %s.", value));
}
option.click();
}

Selenium radiobutton selection

I have an HTML code as follows:
<label class="top" for="id_gender2">
<div id="uniform-id_gender2" class="radio">
<span>
<input id="id_gender2" type="radio" value="2" name="id_gender">
</span>
</div>
Mrs.
</label>
The radio button is getting selected after mouse hover.
I have tried with all possible attributes for selection but I am getting element not found exception.Please let me know how to write java script in webdriver.
Try following code and let me know the result:
Actions action = new Actions(driver);
WebElement hover = driver.findElement(By.xpath("//*[#class='radio hover']"));
action.moveToElement(hover).moveToElement(driver.findElement(By.xpath("//input[#id='id_gender2']"))).click().build().perform();
UPDATE
Actually there is no need in mouse hover. Target radio seem to be initially non-clickable, so you just need extra time to wait for page complete rendering:
WebDriverWait wait = new WebDriverWait(driver, 15);
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("input#id_gender2")));
driver.findElement(By.cssSelector("input#id_gender2")).click();
Try javascript executor as follow:
WebElement element = driver.findElement(By.id("id_gende‌​r2"));
((JavascriptExecutor) driver).executeScript("arguments[0].click();", element);
Your element is probably not loaded properly while getting error. You'd better use explicit wait in your script. Wait until your specific element loaded to be visible/clickable. I think, this may help you.
Code snippet:
By yourElementToSelect = By.id("id_gender2");
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.visibilityOfElementLocated(yourElementToSelect));
driver.findElement(yourElementToSelect).click();

Unable to select an item from a hidden RadComboBox

It would be very much helpful if I could get a solution for the below problem.
I'm unable to select an item from a hidden Radcombobox. The below code just enabled the field and I could see the combobox drops down in a fraction of second but the item specified is not selected. Please assist me correcting my code.
HTML Script
<a id="cmb_40_Arrow" style="overflow: hidden;display: block;position: relative;outline: none;">select</a>
Java Code
((JavascriptExecutor)driver).executeScript("arguments[0].click();", getElement("InterPoint")); //This is the combobox field
new FluentWait<WebDriver>(driver)
.withTimeout(1000, TimeUnit.SECONDS).pollingEvery(1, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class)
.ignoring(StaleElementReferenceException.class)
.until(new Function<WebDriver, Boolean>() {
#NotNull
#Override
public Boolean apply(WebDriver webDriver) {
WebElement element = getElement("CustomerPole"); /*This is the item from the field "Interpoint"*/
return element != null && element.isDisplayed();
}
});
Tried the below code and it doesn't work either
//waitpgm.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(" //*[#id='pnlHeaderInterconnectionPointInformation']"))).click();
//waitpgm.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[#id='cmb_40_DropDown']/div/ul/li[2]"))).click();
//waitpgm.until(ExpectedConditions.elementToBeClickable(getElement("CustomerPole"))).click();