Dropdown click not working in Selenium RC - java

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.

Related

Selenium made a sendKeys for two fields instead of one for some reason

I made a pretty simple selenium test, where I want to open web page, clear field value, start entering text for this field, select first value from the hint drop down.
Web site is aviasales.com (I just found some site with a lot of controls, this is not an advertisement)
I did
DriverFactory.getDriver().findElement(By.id("flights-origin-prepop-whitelabel_en")).clear();
and it was working perfectly, I also checked via console that this is the only one object on a page like:
document.getElementById('flights-origin-prepop-whitelabel_en')
So, in next line I'm sending value:
DriverFactory.getDriver().findElement(By.id("flights-origin-prepop-whitelabel_en")).sendKeys("LAX");
but it send LAX value for both "flights-origin-prepop-whitelabel_en" and "flights-destination-prepop-whitelabel_en" for some reason, then i tried
DriverFactory.getDriver().findElement(By.id("//input[#id='flights-destination-prepop-whitelabel_en'][#placeholder='Destination']")).sendKeys(destinationAirport);
but I got the same result:
What could be a reason and how to fix this?
Thank you!
Yep... there's some weird behavior going on there. The site is copying whatever is entered into the first field into the second for reason I don't understand. I gave up trying to understand it and found a way around it.
Whenever I write code that I know I'm going to reuse, I put them into functions. Here's the script code
driver.navigate().to(url);
setOrigin("LAX");
setDestination("DFW");
...and since you are likely to use these repeatedly, the support functions.
public static void setOrigin(String origin)
{
WebElement e = driver.findElement(By.id("flights-origin-prepop-whitelabel_en"));
e.click();
e.clear();
e.sendKeys(origin);
e.sendKeys(Keys.TAB);
}
public static void setDestination(String dest)
{
WebElement e = driver.findElement(By.id("flights-destination-prepop-whitelabel_en"));
e.click();
e.clear();
e.sendKeys(dest);
e.sendKeys(Keys.TAB);
}
You can see the functions but basically I click in the field, clear the text (because usually there's something already in there), send the text, and then press to move out of the field and choose the default (first choice).
The reason of your issue is the ORIGIN and DESTINATION inputbox binded keyboard event which used to supply an autocomplete list according to your typed characters.
The binded keyborad event breaks the normal sendKeys() functionality. I met similar case in my projects and questions on StackOverFlow.
I tried input 'GSO' into DESTINATION by sendKeys('GSO'), but I get 'GGSSOO' on page after the sendKeys() complete.
To resolve your problem, we can't use sendKeys(), we have to use executeScript() to set the value by javascript in backgroud. But executeScript() won't fire keyborad event so you won't get the autocomplete list. So we need find out a way to fire keyborady event after set value by javascript.
Below code snippet worked on chrome when i tested on aviasales.com:
private void inputAirport(WebElement targetEle, String city) {
String script = "arguments[0].value = arguments[1]";
// set value by javascript in background
((JavascriptExecutor) driver).executeScript(script, targetEle, city + "6");
// wait 1s
Thread.sleep(1000);
// press backspace key to delete the last character to fire keyborad event
targetEle.sendKeys(Keys.BACK_SPACE);
// wait 2s to wait autocomplete list pop-up
Thread.sleep(2000);
// choose the first item of autocomplete list
driver.findElement(By.cssSelector("ul.mewtwo-autocomplete-list > li:nth-child(1)")).click();
}
public void inputOrigin(String city) {
WebElement target = driver.findElement(By.id("flights-origin-prepop-whitelabel_en"));
return inputAirport(target, city);
}
public void inputDestination(String city) {
WebElement target = driver.findElement(By.id("flights-origin-prepopflights-destination-prepop-whitelabel_en"));
return inputAirport(target, city);
}

Selenium Driver (Chrome) Can't Find Dropdown on hover Element

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

How can I use assert in Selenium WebDriver?

I need to know how can I do assertion in Selenium WebDriver. My situation is I have one edit, but on screen, but that edit button is present on some certain criteria.
So I want to check that if that button is present. It should be clicked on and it should open another child window and should perform certain actions. If that edit button element is not present on the screen, it should check the next condition which is the log off button in my keyword framework.
I have tried try and catch block and it is working fine.
Here is the code:
public void click_edit_childwindow2(String objectName) {
// Store the current window handle
String winHandleBefore = driver.getWindowHandle();
// Perform the click operation that opens new window
try{
WebElement elemnt = driver.findElement(By.xpath("//*[#id='main']/div[1]/table/tbody/tr[2]/td[6]/button"));
elemnt.click();
driver.findElement(By.xpath("//*[#id='main']/div[1]/table/tbody/tr[2]/td[6]/button")).click();
// Switch to new window opened
for(String winHandle : driver.getWindowHandles()){
driver.switchTo().window(winHandle);
}
// Perform the actions on new window
driver.findElement(By.xpath("//*[#id='myModal']/div/div/div[2]/form/div/div[10]/div/button[1]")).click();
// Close the new window, if that window no more required
//driver.close();
// Switch back to original browser (first window)
driver.switchTo().window(winHandleBefore);
// Continue with original browser (first window)
}
catch(Exception e){
driver.findElement((By.xpath("//*[#id='logoutForm']/ul/li[2]/a"))).click();
}
}
But I want to do it with assert. Though try and catch is not stopping the code, but after testing execution it is showing that the test case as failed. How can I do it with assert?
I am using keyword framework in which one is class is for keyword and another is for reading an Excel file.
A typical Selenium setup will include a test framework that is attached to your project.
There are several test frameworks to use, but here are the most popular for Java:
jUnit
TestNG
...
When you have a test framework attached to your project, you could then use asserts like:
Assert.assertTrue(driver.getWindowHandles().size().equals(2));
If the assertion fails, it will fail the test script. This is just one small example. I'd certainly do some research on how to use your test framework of choice. Selenium out-of-the-box is designed to be agnostic to what you use. Get creative.
Try the below code:
Boolean isPresent = driver.findElements(By.yourLocator).size() > 0
if(isPresent == true)
{
// Code
}
At first you need to check whether that button is displayed in the webpage. You can do that by this -
WebElement web = driver.findElement(By.xpath("//*[#id='myModal']/div/div/div[2]/form/div/div[10]/div/button[1]"));
boolean bool = web.isDisplayed();
Assert.assertEquals(true, bool); // Here it will match that if that button
// is present or not. If present it will
// continue execution from the next line
// or if it is not present the execution
// stops there and your test case fails.
You could avoid try-catch by:
List <WebElement> editButton = driver.findElements(By.xpath("//*[#id='main']/div[1]/table/tbody/tr[2]/td[6]/button"));
if(editButton.size() > 0)
{
editButton.get(0).click();
for(String winHandle : driver.getWindowHandles()){
driver.switchTo().window(winHandle);
}
// Perform the actions on new window
driver.findElement(By.xpath("//*[#id='myModal']/div/div/div[2]/form/div/div[10]/div/button[1]")).click();
// Close the new window, if that window no more required
//driver.close();
//Switch back to original browser (first window)
driver.switchTo().window(winHandleBefore);
}
else
{
driver.findElement((By.xpath("//*[#id='logoutForm']/ul/li[2]/a"))).click();
}

Going through Chrome://settings by Selenium

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

Open link in new tab [duplicate]

I have trawled the web and the WebDriver API. I don't see a way to open new tabs using WebDriver/Selenium2.0 .
Can someone please confirm if I am right?
Thanks,
Chris.
P.S: The current alternative I see is to either load different urls in the same window or open new windows.
There is totally a cross-browser way to do this using webdriver, those who say you can not are just too lazy. First, you need to use WebDriver to inject and anchor tag into the page that opens the tab you want. Here's how I do it (note: driver is a WebDriver instance):
/**
* Executes a script on an element
* #note Really should only be used when the web driver is sucking at exposing
* functionality natively
* #param script The script to execute
* #param element The target of the script, referenced as arguments[0]
*/
public void trigger(String script, WebElement element) {
((JavascriptExecutor)driver).executeScript(script, element);
}
/** Executes a script
* #note Really should only be used when the web driver is sucking at exposing
* functionality natively
* #param script The script to execute
*/
public Object trigger(String script) {
return ((JavascriptExecutor)driver).executeScript(script);
}
/**
* Opens a new tab for the given URL
* #param url The URL to
* #throws JavaScriptException If unable to open tab
*/
public void openTab(String url) {
String script = "var d=document,a=d.createElement('a');a.target='_blank';a.href='%s';a.innerHTML='.';d.body.appendChild(a);return a";
Object element = trigger(String.format(script, url));
if (element instanceof WebElement) {
WebElement anchor = (WebElement) element; anchor.click();
trigger("var a=arguments[0];a.parentNode.removeChild(a);", anchor);
} else {
throw new JavaScriptException(element, "Unable to open tab", 1);
}
}
Next, you need to tell webdriver to switch its current window handle to the new tab. Here's how I do that:
/**
* Switches to the non-current window
*/
public void switchWindow() throws NoSuchWindowException, NoSuchWindowException {
Set<String> handles = driver.getWindowHandles();
String current = driver.getWindowHandle();
handles.remove(current);
String newTab = handles.iterator().next();
locator.window(newTab);
}
After this is done, you may then interact with elements in the new page context using the same WebDriver instance. Once you are done with that tab, you can always return back to the default window context by using a similar mechanism to the switchWindow function above. I'll leave that as an exercise for you to figure out.
The Selenium WebDriver API does not support managing tabs within the browser at present.
var windowHandles = webDriver.WindowHandles;
var script = string.Format("window.open('{0}', '_blank');", url);
scriptExecutor.ExecuteScript(script);
var newWindowHandles = webDriver.WindowHandles;
var openedWindowHandle = newWindowHandles.Except(windowHandles).Single();
webDriver.SwitchTo().Window(openedWindowHandle);
I had the same issue and found an answer. Give a try.
Robot r = new Robot();
r.keyPress(KeyEvent.VK_CONTROL);
r.keyPress(KeyEvent.VK_T);
r.keyRelease(KeyEvent.VK_CONTROL);
r.keyRelease(KeyEvent.VK_T);
It will open a new tab you can perform your actions in the new tab.
Though there is no API for opening a new tab, you can just create a new instance of WebDriver calling it something slightly different and passing the URL you want in the new tab. Once you have done all you need to do, close that tab and make the new driver NULL so that it does not interfere with the original instance of Webdriver. If you need both tabs open, then ensure you refer to the appropriate instance of WebDriver. Used this for Sitecore CMS automation and it worked.
Thanks for the great idea #Jonathan Azoff !
Here's how I did it in Ruby:
def open_new_window(url)
a = #driver.execute_script("var d=document,a=d.createElement('a');a.target='_blank';a.href=arguments[0];a.innerHTML='.';d.body.appendChild(a);return a", url)
a.click
#driver.switch_to.window(#driver.window_handles.last)
end
There's no way we can create new TAB or handle tabs using web driver / selenium 2.0
You can open a new window instead.
Hey #Paul and who ever is having issue opening a second tab in python. Here is the solution
I'm not sure if this is a bug within the webdriver or because it isn't compatible yet with mutlitab but it is definitely acting wrong with it and I will show how to fix it.
Issue:
well I see more than one issue.
First issue has to do that when you open a 2nd tab you can only see one handle instead of two.
2nd issue and here is where my solution comes in. It seems that although the handle value is still stored in the driver the window has lost sync with it for reason.
Here is the solution by fixing the 2nd issue:
elem = browser.find_element_by_xpath("/html/body/div[2]/div[4]/div/a") #href link
time.sleep(2)
elem.send_keys(Keys.CONTROL + Keys.RETURN + "2") #Will open a second tab
#solution for the 2nd issue is here
for handle in browser.window_handles:
print "Handle is:" + str(handle) #only one handle number
browser.switch_to_window(handle)
time.sleep(3)
#Switch the frame over. Even if you have switched it before you need to do it again
browser.switch_to_frame("Frame")
"""now this is how you handle closing the tab and working again with the original tab"""
#again switch window over
elem.send_keys(Keys.CONTROL + "w")
for handle in browser.window_handles:
print "HandleAgain is:" + str(handle) #same handle number as before
browser.switch_to_window(handle)
#again switch frame over if you are working with one
browser.switch_to_frame("Frame")
time.sleep(3)
#doing a second round/tab
elem = browser.find_element_by_xpath("/html/body/div[2]/div[4]/div/a") #href link
time.sleep(2)
elem.send_keys(Keys.CONTROL + Keys.RETURN + "2") #open a 2nd tab again
"""Got it? find the handle, switch over the window then switch the frame"""
It is working perfectly for me. I'm open for questions...
Do this
_webDriver.SwitchTo().Window(_webDriver.WindowHandles.Where(x => x != _webDriver.CurrentWindowHandle).First());
or Last() etc.
PS there is no guarantee that the WindowHandles are in the order displayed on your browser, therefore, I would advise you keep some history of current windows before you do the command to that caused a new tab to open. Then you can compare your stored window handles with the current set and switch to the new one in the list, of which, there should only be one.
#Test
public void openTab() {
//Open tab 2 using CTRL + t keys.
driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL +"t");
//Open URL In 2nd tab.
driver.get("http://www.qaautomated.com/p/contact.html");
//Call switchToTab() method to switch to 1st tab
switchToTab();
}
public void switchToTab() {
//Switching between tabs using CTRL + tab keys.
driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL +"\t");
//Switch to current selected tab's content.
driver.switchTo().defaultContent();
}
we can use keyboard events and automate opening and switching between multiple tabs very easily. This example is refered from HERE
I must say i tried this as well, and while it seemingly works with some bindings (Java, as far as Jonathan says, and ruby too, apparently), with others it doesnt: selenium python bindings report just one handle per window, even if containing multiple tabs
IJavaScriptExecutor is very useful class which can manipulate HTML DOM on run time through JavaScript, below is sample code on how to open a new browser tab in Selenium through IJavaScriptExecutor:
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
object linkObj = js.ExecuteScript("var link = document.createElement('a');link.target='_blank';link.href='http://www.gmail.com';link.innerHTML='Click Me';document.getElementById('social').appendChild(link);return link");
/*IWebElement link = (IWebElement)linkObj;
link.Click();*/
browser.Click("//*[#id='social']/a[3]");
Just to give an insight, there are no methods in Selenium which would allow you to open new tab, the above code would dynamically create an anchor element and directs it open an new tab.
You can try this way, since there is action_chain in the new webdriver.
I'm using Python, so please ignore the grammar:
act = ActionChains(driver)
act.key_down(Keys.CONTROL)
act.click(link).perform()
act.key_up(Keys.CONTROL)
For MAC OS
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Firefox()
driver.get("http://google.com")
body = driver.find_element_by_tag_name("body")
body.send_keys(Keys.COMMAND + 't')
Java Robot can be used to send Ctrl+t (or Cmd+t if MAC OS X) as follows:
int vkControl = IS_OS_MAC ? KeyEvent.VK_META : KeyEvent.VK_CONTROL;
Robot robot = new Robot();
robot.keyPress(vkControl);
robot.keyPress(KeyEvent.VK_T);
robot.keyRelease(vkControl);
robot.keyRelease(KeyEvent.VK_T);
A complete running example using Chrome as browser can be forked here.
I would prefer opening a new window. Is there really a difference in opening a new window vs opening a new tab from an automated solution perspective ?
you can modify the anchors target property and once clicked the target page would open in a new window.
Then use driver.switchTo() to switch to the new window. Use it to solve your issue
Instead of opening new tab you can open new window using below code.
for(String childTab : driver.getWindowHandles())
{
driver.switchTo().window(childTab);
}

Categories