I'm using the Selenium Chrome Driver to run a couple tests on various site environments, however, when attempting to use an element from a hover drop down menu, I can't seem to reliably select the elements. This works 100% of the time when I'm debugging, but when I run it without an attached debugger it fails about 2/3rds of the time. Here is the code:
private void prepWindow(WebDriver driver, boolean isNightly, String toClick) {
WebDriverWait wait = new WebDriverWait(driver, 300);
try {
if (isNightly) {
WebElement nightlyPopup = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(BOWebElements.nightlyPopup)));
nightlyPopup.click();
}
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Nightly popup has changed names again.", "Error", JOptionPane.ERROR_MESSAGE);
}
WebElement user = wait.until(ExpectedConditions.visibilityOfElementLocated(By.linkText("Users")));
Actions action = new Actions(driver);
action.moveToElement(user).build().perform(); //Makes hover drop down appear
driver.findElement(By.id(toClick)).click(); //Should click element that is only visible when hover drop down is open
}
I should also note that the same code above works perfectly without using a debugger on a coworker's computer, but not my own.
I would like to use XPath but unfortunately the elements of the drop down aren't actually children of the link I have to hover over to open the drop down. If I try to navigate directly to the element using the XPath, it gives me an error saying the XPath isn't valid. Here is one of the potential XPaths:
//html/body/#outTemplateId/#preambleFormId/#globalNavigation/#navBGC/#navBGCmainMM/ul/li/ul/table/tbody/tr/td/ul.ui-menu-list.ui-helper-reset/li.ui-menuitem.ui-widget.ui-corner-all/a#fleetUsersId2.ui-menuitem-link.ui-corner-all.submenu
How can I make the behavior consistent?
Chain your actions together to better emulate the actions that a user would take:
action.moveToElement(user).moveToElement(driver.findElement(By.id(toClick))).click().build().perform();
Check out this question for more details:
https://stackoverflow.com/a/17294390/3537915
Related
I am using Java and Selenium to write a test, I use the code below to get into Chrome:setting
driverChrome.manage().window().maximize();
driverChrome.get("chrome://settings");
But when the page is open I can not find any of its web Elements, for example when I try to find "show advanced setting...." by this code
driverChrome.findElement(By.xpath("//a[#id='advanced-settings-expander']")).click();
it throws an error saying that "no such element: Unable to locate element"
I tried to located other elements, but they all failed. I saw this post here but it did not help.
Find the code below:
driverChrome.manage().window().maximize();
driverChrome.get("chrome://settings");
Thread.sleep(5000);
WebElement w = driverChrome.findElement(By
.xpath("//iframe[#name='settings']"));
driverChrome = driverChrome.switchTo().frame(w);
Thread.sleep(1000);
while (true) {
try {
WebElement we = w.findElement(By
.xpath("//a[text()='Show advanced settings...']"));
if (we.isDisplayed()) {
we.click();
Thread.sleep(1000);
break;
}
} catch (Exception e) {
System.out.println(e.getMessage());
System.out.println("=========================");
}
}
I haven't tested this but I took your code snippet and cleaned it up a bit. Try this and see if it works. This should be pretty close.
Once you switch to the IFRAME context, you don't need to reference the IFRAME as you did with w.findElement().
In general, Thread.sleep() is not a good practice. You should prefer to use WebDriverWait with ExpectedConditions. Check the docs for all the different things you can wait for using ExpectedConditions. I used .elementToBeClickable() in my code below. This is perfect since you want to click an element. The .until() returns the element waited for so you can just append .click() on the end of the statement... or you can store the element in a WebElement variable and use it elsewhere.
driverChrome.manage().window().maximize();
driverChrome.get("chrome://settings");
WebElement w = driverChrome.findElement(By.xpath("//iframe[#name='settings']"));
driverChrome = driverChrome.switchTo().frame(w);
WebDriverWait wait = new WebDriverWait(driverChrome, 10);
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[text()='Show advanced settings...']"))).click();
// alternative example... store returned element and then click on a separate line... or use the variable elsewhere, etc.
// WebElement link = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[text()='Show advanced settings...']")));
// link.click();
You will need to identify Shadow roots to interact with a lot of Chromes native pages including the Settings page.
See this Thread on how to work with them properly:
How to interact with the elements within #shadow-root (open) while Clearing Browsing Data of Chrome Browser using cssSelector
I have some tests which click on a tab, however the click is not always performed.
The xpath is correct as most of the times the test works
It is not a timing issue as I ve used thread.sleep() and other methods to ensure that the element is visible before clicking
The test believes that it is performing the click as it is not throwing an ElementNotFoundException or any other exceptions when 'performing' the click. The test fails later on after the click since the tab content would not have changed.
Further Info
I am using Selenium 2.44.0 to implement tests in Java which run on Chrome 44.0.2403.107 m.
Is there something else that I can do or could this be an issue with selenium?
There are several things you can try:
an Explicit elementToBeClickable Wait:
WebDriverWait wait = new WebDriverWait(webDriver, 10);
WebElement button = wait.until(ExpectedConditions.elementToBeClickable(By.id("myid")));
button.click()
move to element before making a click:
Actions actions = new Actions(driver);
actions.moveToElement(button).click().build().perform();
make the click via javascript:
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("arguments[0].click();", button);
you can go with linkText if the tab name contains any unique string. And make sure your tab is not dynamic. It should be visible in source code(manual source code(ctrl+u)).
The following method work for me
WebElement button = SeleniumTools.findVisibleElement(By.cssSelector("#cssid"));
Actions actions = new Actions(driver);
actions.moveToElement(button).click().build().perform();
I have a similar problem. Tried all solutions from the top answer. Sometimes they work, sometimes don't.
But running code in an infinite loop works always.
For example, we need to click on element-two which is not visible until element-one is clicked.
WebDriverWait wait = new WebDriverWait(webDriver, 10);
while (true){
try {
WebElement elementOne =
wait.until(ExpectedConditions.elementToBeClickable(By.id("element-one")));
elementOne.click();
WebElement elementTwo =
wait.until(ExpectedConditions.elementToBeClickable(By.id("element-two")));
elementTwo.click();
break;
} catch (Exception e){
//log
}
}
I have a similar problem. Here is my solution:
table_button = driver.find_element(By.XPATH, insert your xpath)
try:
WebDriverWait(driver, 15).until(EC.element_to_be_clickable(table_button)).click()
except WebDriverException as e:
print('failed')
print(e)
Through code above, you can find the error message if your button is not clickable.
For example, my error message is 'nosuchelement' and 'clcik is not clickable', then I got back to check the table_button.accessible_name, found it print a 'null' value, so that means my XPATH is incorrect.
The following code tests an autocomlete box of a webpage:
public class Test {
public static void main(String[] args) throws InterruptedException {
System.setProperty("webdriver.chrome.driver","chromedriver\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("http://www..............com");
driver.switchTo().frame("mainFrame");
WebDriverWait waitst = new WebDriverWait(driver, 120);
waitst.until(ExpectedConditions.visibilityOfElementLocated(By.name("sourceTitle")));
WebElement sourceTitle = driver.findElement(By.name("sourceTitle"));
WebElement small = driver.findElement(By.cssSelector("li#nameExampleSection label + small"));
sourceTitle.sendKeys("Times");
Thread.sleep(5000);
Actions actions = new Actions(driver);
actions.click(small).perform();
}
}
Why doesn't the autosuggest box load? IMPORTANT: try to type in "..........." manually ... the autocomplete box will load perfectly fine!!! So, why does not cssSelector work, why doesn't it load the autocomplete box?
How come an automated input does not allow for autocomplete options BUT a manual input does???
PS: I also tried fireEvent, sendKeys but nothing works.
I tried your code, it does exactly what the manual walkthough does. "Associated Press, The" returns only a "No Match, please try sources". In your code you then try to click on the next form list item, not the results popup. The autosuggest popup is dynamically populated at the top of your html page positioned under the input form. The following code does select the first option on your drop down.
#Test
public void test() throws InterruptedException {
WebDriver driver = new ChromeDriver();
driver.get("http://www.lexisnexis.com/hottopics/lnacademic/?verb=sf&sfi=AC00NBGenSrch");
driver.switchTo().frame("mainFrame");
WebDriverWait waitst = new WebDriverWait(driver, 0);
waitst.until(ExpectedConditions.visibilityOfElementLocated(By.name("sourceTitle")));
WebElement sourceTitle = driver.findElement(By.name("sourceTitle"));
sourceTitle.sendKeys("Times");
Thread.sleep(5000);
WebElement firstItem = driver.findElement(By.xpath("//*[#class='auto_suggest']/*[#class='title_item']"));
firstItem.click();
}
I found a workaround about this. My problem was:
Selenium inputted 'Mandaluyong' to an auto-suggest location field
The auto-suggest field appears together with the matched option
Then selenium left the auto-suggest drop-down open not selecting the matched option.
What I did was:
driver.findElement(By.name("fromLocation")).sendKeys("Mandaluyong");
driver.findElement(By.name("fromLocation")).sendKeys(Keys.TAB);
This is because on a manual test, when I try to press TAB key, two things were done by the system:
Picks the matched option from the auto-suggest drop-down
Closes the auto-suggest drop-down
Hope this helps.
// allow autopuplation value to fill the text box.
// wait for 6 sec make sure auto value is inserted
thread.sleep(6000L);
// clear auto filled value
driver.findElement(By.name("txtBox")).clear();
driver.findElement(By.name("txtBox")).sendKeys("value");
Try first clicking on the Input textbox.
This will trigger the auto populating dropdown box and then enter the required value using sendKeys
Either you can use tab or enter to Escape the scenario or,it is not possible by selenium if it is mandatory fields. (sad)
I'm writing an automated test case for a web page. Here's my scenario.
I have to click and type on various web elements in an html form. But, sometimes while typing on a text field, an ajax loading image appears , fogging all elements i want to interact with. So, I'm using web-driver wait before clicking on the actual elements like below,
WebdriverWait innerwait=new WebDriverWait(driver,30);
innerwait.until(ExpectedConditions.elementToBeClickable(By.xpath(fieldID)));
driver.findelement(By.xpath(fieldID)).click();
But the wait function returns the element even if it is fogged by another image and is not clickable. But the click() throws an exception as
Element is not clickable at point (586.5, 278).
Other element would receive the click: <div>Loading image</div>
Do I have to check every time if the loading image appeared before interacting with any elements?.(I can't predict when the loading image will appear and fog all elements.)
Is there any efficient way to handle this?
Currently I'm using the following function to wait till the loading image disappears,
public void wait_for_ajax_loading() throws Exception
{
try{
Thread.sleep(2000);
if(selenium.isElementPresent("id=loadingPanel"))
while(selenium.isElementPresent("id=loadingPanel")&&selenium.isVisible("id=loadingPanel"))//wait till the loading screen disappears
{
Thread.sleep(2000);
System.out.println("Loading....");
}}
catch(Exception e){
Logger.logPrint("Exception in wait_for_ajax_loading() "+e);
Logger.failedReport(report, e);
driver.quit();
System.exit(0);
}
}
But I don't know exactly when to call the above function, calling it at a wrong time will fail. Is there any efficient way to check if an element is actually clickable? or the loading image is present?
Thanks..
Given the circumstances that you describe, you are forced to verify one of two conditions:
Is the element that you want to click clickable?
Is the reason that blocks the clicks still present?
Normally, if the WebDriver is able to find the element and it is visible, then it is clickable too. Knowing the posible reasons that might block it, I would rather choose to verify those reasons. Besides, it would be more expressive in the test code: you clearly see what you are waiting for, what you are checking before clicking the element, instead of checking the "clickability" with no visible reason for it. I think it gives one (who reads the test) a better understanding of what is (or could be) actually going on.
Try using this method to check that the loading image is not present:
// suppose this is your WebDriver instance
WebDriver yourDriver = new RemoteWebDriver(your_hub_url, your_desired_capabilities);
......
// elementId would be 'loadingPanel'
boolean isElementNotDisplayed(final String elementId, final int timeoutInSeconds) {
try {
ExpectedCondition condition = new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(final WebDriver webDriver) {
WebElement element = webDriver.findElement(By.id(elementId));
return !element.isDisplayed();
}
};
Wait w = new WebDriverWait(yourDriver, timeoutInSeconds);
w.until(condition);
} catch (Exception ex) {
// if it gets here it is because the element is still displayed after timeoutInSeconds
// insert code most suitable for you
}
return true;
}
Perhaps you will have to adjust it a bit to your code (e.g. finding the element once when the page loads and only checking if it is displayed).
If you are not sure when exactly the loading image comes up (though I suppose you do), you should call this method before every click on elements that would become "unclickable" due to the loading image. If the loading image is present, the method will return true as soon as it disappears; if it doesn't disappear within 'timeoutInSeconds' amount of time, the method will do what you choose (e.g. throw an exception with specific message).
You could wrap it together like:
void clickSkippingLoadingPanel(final WebElement elementToClick) {
if (isElementNotDisplayed('loadingPanel', 10)) {
elementToClick.click();
}
}
Hope it helps.
I am trying to automate test scripts in selenium. Scenario of the activity to be automated:
It should open automatically a page URL first.
Click on the left navigation.
The page then gets populated with a drop-down, it should select a fixed value from the drop down(say = company)
Click a create button at the bottom of the page.
In my case the code is working until the population of drop down but after that the code fails to click the create button as the next action. The error message which I got in the command console is as follows:
Element name = create not found on session c48334c30....96ed
Here is my code:
public class testing {
Selenium selenium = null;
#Test
public void submit() throws Exception {
selenium = new DefaultSelenium("localhost", 4545, "*firefox", "URL");
selenium.start();
selenium.open("URL");
selenium.windowFocus();
selenium.windowMaximize();
selenium.click("link=Work with company names");
selenium.waitForPageToLoad("30000");
selenium.select("//select[#name='company_id']", "label=company");
selenium.waitForPageToLoad("3000");
selenium.click("name = create");
}
}
Please provide me your suggestions to solve this, since I am not able to understand why it is failing to click the button named "create". I also tried to use selenium.click("xpath=//button[matches(#id,'.*create')]"); instead of selenium.click("name = create") but it didnt work as well.
Please let me know what can be the issue for this error and how can I resolve it? Thanks.
1) it would be good if you provide html code of your page.
2) before clicking any element (which is loaded after some action) I recommend using WaitForElementPresent (from Selenium IDE), i.e. be sure that element really exists. Selenium works rather fast and it may try clicking the element before the element actually loaded.
You may use something like this:
public bool waitForElementPresent(string Xpath) {
bool present = false;
for (int second = 0; ; second++) {
if (second >= 5) {
break;
}
if (IsElementPresent(Xpath)) {
present = true;
break;
}
Thread.Sleep(1000);
}
return present;
}
try with this
selenium.click("//*[contains(#name,'create')]");
As you are using: selenium.waitForPageToLoad("3000");
Selenium is waiting for page to load. You want to add a pause, though thread.sleep isn't the best practise it can still work for you.