Click then CTRL Click not working with selenium-java 2.39 + Firefox 26 - selenium

I'm facing this issue since some days now but didn't manage to overcome it trying different ideas.
Problem description: I wanna select a line in a table (GWT CellTable), perform some actions (which are my application specific) on it and then unselect back the line.
The line never gets unselected.
I'm quite new to selenium And I don't know if someone else has run into same problem and if there is a workaround to it. Thanks in advance
Code:
#Test
#SuppressWarnings("serial")
public void testClearEventCodes(){
refreshBrowser();
testWEHSearch();
WebContext faresContext = rootContext.gotoId(Strings.WEH_FARES_TABLE);
//INITIALLY HOT AND EVENT FARE
assertTrue("Y N N N N".equals(faresContext.gotoTableCell(1, 15).getText()));
assertTrue("CHINAYEAR".equals(faresContext.gotoTableCell(1, 16).getText()));
checkColorCodes(new HashMap<String, String[]>(){
{
put(getFareKey("GMP", "PAR", "KE", "0004", "K001", "OW", "Public"), new String[]{"1", COLOR_CODE_HOT_AND_EVENT_FARE});
}
});
faresContext.gotoTableRow(1).getElementWebContext(1).click();
rootContext.gotoId(Strings.WEH_CLEAR_EVENT_CODES_BUTTON).click();
faresContext.gotoTableRow(1).getElementWebContext(1).ctrlClick();
//ENSURE ALL EVENT CODES ARE CLEARED
assertTrue("".equals(faresContext.gotoTableCell(1, 16).getText()));
checkColorCodes(new HashMap<String, String[]>(){
{
put(getFareKey("GMP", "PAR", "KE", "0004", "K001", "OW", "Public"), new String[]{"1", COLOR_CODE_HOT_FARE});
}
});
}
And bellow is the method to CTRL CLICK the line:
/**
* Holds Control key and Clicks on current element.
*/
public void ctrlClick() {
Actions actionBuilder = new Actions(driver);
actionBuilder.keyDown(Keys.CONTROL).click(getSingleElement()).keyUp(Keys.CONTROL);
org.openqa.selenium.interactions.Action action = actionBuilder.build();
action.perform();
}

Your problem might be related to the new Firefox feature in which display settings are now taken into account. You can try changing the display settings for your computer to 100% and try again.
https://code.google.com/p/selenium/issues/detail?id=6774

Related

WinAppDriver having issues identify elements in a driver when the driver changes too much

For example: Launch Outlook on your desktop. Notice how there is a "splash loading screen" well the driver I have will look at this executable and wait x seconds before trying to click on the "New Email" button. However when it gets to the page where the new email button appears, it can't find it. Strange... hmm okay lets start the application but have it trigger the executable that is already in the process. It looks for the new email button and finds it no problem.
The only thing i can think of is that the driver loads the executable, the executable then changes its data drastically or something. Then all of a sudden i need to build a new driver. But I dont think this is the way to go about it.
[TestInitialize]
public void TestMethod1()
{
options.AddAdditionalCapability("app", #"C:\Program Files (x86)\<PATH>");
_driver = new WindowsDriver<WindowsElement>(new Uri("http://127.0.0.1:4723"), options);
System.Threading.Thread.Sleep(5000);
}
[TestMethod]
public void TEST()
{
LoginPage page = new LoginPage(new WindowsDriver<WindowsElement>(new Uri("http://127.0.0.1:4723"), options)); // Notice how i am building a new driver just for this page. This is VERY heavy.
page.Login("USERNAME", "PASSWORD");
}
You probably have the "splash screen issue".
Here's a explantation about what to do about it.
In short, winappdriver creates a new windowhandle for every new window it encounters. As the splash screen counts for a separate window, you should have 2 windowhandles available at the moment you wanted to click that "new email" button. The most recent windowhandle will be the highest index.
You can switch between windowhandles like this (copied from link):
// Return all window handles associated with this process/application.
// At this point hopefully you have one to pick from. Otherwise you can
// simply iterate through them to identify the one you want.
var allWindowHandles = session.WindowHandles;
// Assuming you only have only one window entry in allWindowHandles and it is in fact the correct one,
// switch the session to that window as follows. You can repeat this logic with any top window with the same²
// process id (any entry of allWindowHandles)
session.SwitchTo().Window(allWindowHandles[0]);
Also take a look at this answer. Could be useful too.

Handling a button that opens a new tab and redirects you to it

After clicking the create invoice button, it opens a new tab and redirects you to it. Next, it should click a button but it says no element exists. Did it search the element on the current page ? not on the new tab?
Tried explicit wait for that button and tried switching back and forth to the tab
#Test (priority=3)
public void ProductListExpress() {
driver.findElement(By.className("bttn-imp-create")).click();
System.out.println("Successful in proceeding to Purchase.php");
String newUrl1 = driver.getCurrentUrl();
if(newUrl1.equalsIgnoreCase("http://localhost:82/purchase.php")){
System.out.println("Successful in proceeding to Purchase page ");
}
else {
System.out.println("Failed in proceeding to Purchase page");
}
}
#Test (priority=4)
public void ClickInvoice() {
}
#Test (priority=5)
public void test() {
//Click create invoice button
driver.findElement(By.name("btncreateinvoice")).click();
System.out.println("Successful in clicking create invoice");
}
Expect to click button after redirecting.
First of all wait for 2nd window to open and be available to the WebDriver. You can use Explicit Wait for this like:
new WebDriverWait(driver,10).until(ExpectedConditions.numberOfWindowsToBe(2));
Check out How to use Selenium to test web applications using AJAX technology article for more information on the concept
Once you have the confidence that the number of windows is 2 you can use switchTo().window() function to change the context for the 2nd window:
driver.switchTo().window(driver.getWindowHandles().stream().reduce((f, s) -> s).orElse(null));
When you are clicking on new button, new tab is getting open. In this scenario, you need to use WindowsHandles. Try below code:
#Test (priority=3)
public void ProductListExpress() {
driver.findElement(By.className("bttn-imp-create")).click();
System.out.println("Successful in proceeding to Purchase.php");
Set<String> winHandles= driver.getWindowHandles();
Iterator<String> it = winHandles.iterator();
String parentWindowId = it.next();
String newWindowID= it.next();//Here you will get windows id of newly opened tab
driver.switchTo().window(newWindowID); //now your driver is switching to new tab
String newUrl1 = driver.getCurrentURL();
if(newUrl1.equalsIgnoreCase("http://localhost:82/purchase.php")){
System.out.println("Successful in proceeding to Purchase page ");
}
else {
System.out.println("Failed in proceeding to Purchase page");
}
}
You can switch to new tab with this way :
//Click create invoice button
driver.findElement(By.name("btncreateinvoice")).click();
System.out.println("Successful in clicking create invoice");
ArrayList<String> tabs = new ArrayList<String> (driver.getWindowHandles());
driver.switchTo().window(tabs.get(1));
during execution whenever a new tab or window opens, control of the driver still remains in the original tab or window unless we write couple of lines of code to manually switch the control to new tab or window.
In your case, Since the driver control is still in original tab and next element to click is in new tab, selenium is not able to find it, hence it says no element exists
#Test (priority=5)
public void test() {
WebDriverWait w= new WebDriverWait(driver, 10);
ArrayList<String> x = new ArrayList<String>(driver.getWindowHandles());
driver.switchTo().window(x.get(1)); // here x.get(1) indicates that
driver control is switched to new tab or new window
w.until(ExpectedConditions.elementToBeClickable("locator of button to be clicked"));
}
In case ,in your next steps if you can to continue execution in the original window or tab, you have to again switch selenium driver control back .
driver.switchTo().window(x.get(0));// during next steps if you want
driver control to switch back to original tab or window you have to write this line
of code
IDK if this is what you're asking, but it might be. I was CTRL+CLICKING a button to open a new tab. This is how I found the tab:
Set<String> curWindows = new HashSet<> (driver.getWindowHandles ());
String newWindowHandle = null;
a.keyDown(Keys.LEFT_CONTROL).click(THE_BUTTON).keyUp(Keys.LEFT_CONTROL).build().perform();
this.delay (500);
for (String windowHandle : driver.getWindowHandles ()) {
if (curWindows.contains (windowHandle) == false) {
newWindowHandle = windowHandle;
break;
}
}
if (newWindowHandle == null) {
log.error ("Unable to find the new window handle.");
return null;
}

The element is obscured(Server did not provide stack information) automation in edge browser with selenium

org.openqa.selenium.WebDriverException: Element is obscured (WARNING: The server did not provide any stacktrace information).
This code is working fine for chrome and firefox but not with edge browser.
`public class Login {
public WebDriver driver;
By userName = By.id("ctl14_UserName");
By password = By.id("ctl14_Password");
By login = By.id("ctl14_LoginButton");
public Login(WebDriver driver) {
this.driver = driver;
}
// Set password in username textbox
public void setUserName(String strUserName) {
driver.findElement(userName).sendKeys(strUserName);
}
// Set password in password textbox
public void setPassword(String strPassword) {
driver.findElement(password).sendKeys(strPassword);
}
public void clickMyaccount(){
driver.findElement(myAccount).click();
}
// Click on login button
public void clickLogin() {
driver.findElement(login).click();
}
}
//Test class
public class AdminLogin extends BaseForDifferentLogins {
Login objLoginAdmin;
#Test(priority=0)
public void login() throws InterruptedException{
objLoginAdmin=new Login(driver);
objLoginAdmin.clickMyaccount();
Thread.sleep(3000);
objLoginAdmin.setUserName("superuser1");
objLoginAdmin.setPassword("superuser1");
Thread.sleep(3000);
objLoginAdmin.clickLogin();
Thread.sleep(3000);
}
}`
Instead of using webElement.click() you can try to build Actions with click and do perform. Had the same issue on Edge and that did the trick for me:
Actions actions = new Actions(webDriver);
actions.click(webElement).perform();
I have encountered the issue and tried several things to solve it:
enabled EdgePageLoadStrategy.Normal - did not help;
disabled the "save your password?" bubble. - did not help;
normalized the zoom level to 100% - bingo / eureka. This solved the issue.
My test script is a bit more performance-oriented, so I had no desire to add additional objects / capabilties / options. If you want your test to be more deployable add registry editing capabilities to your selenium script. This can be a starter: http://www.winhelponline.com/blog/microsoft-edge-disable-zoom-reset-zoom-level-every-start/
I encountered the same issue on the Edge browser.
It was difficult to figure out what was actually wrong, since the issue seemed to appear/disappear from time to time in my case.
So at some point I decided to contact MS and created this ticket question
Here Steven K mentioned that the obscured element error is most likely due to zoom level not being at 100% So I checked and indeed it was at 125% for some reason.
After I set it back to 100% the issue was resolved for me.
browser.send_keys [:control, '0']
I know this is a ruby+watir example, but I'm sure there is a similar Java trick for this.
I have also encountered this problem while testing Angular with Protractor in Microsoft Edge.
What finally helped me was combining two workarounds:
Set browser zoom value to 100% explicitly in beforeEach function:
browser.actions().keyDown(protractor.Key.CONTROL).sendKeys('0')
.keyUp(protractor.Key.CONTROL).perform();
Do click through browser actions:
browser.actions().mouseMove(yourElementThatIsNotActuallyObscured).click().perform();
Resetting Zoom level to 100% will fix the issue.
public void clickUntillNotObsecured(WebElement elementToClick) {
boolean obsecuredThrown = true;
int c=0;
while (obsecuredThrown && c<30) {
try {
clickOnElement(elementToClick);
obsecuredThrown = false;
} catch (WebDriverException e) {
obsecuredThrown = true;
}
c++;
}
}
You can perform the task with the Action chains in the python specially with Edge browser:
from selenium.webdriver import ActionChains
actionChains = ActionChains(driver)
button_xpath = '//xapth...'
button = driver.find_element_by_xpath(button_xpath)
actionChains.move_to_element(button).click().perform()
But sometimes Action chain does not finds the DOM element. Hence better option to use execute_script in following way which is compatible with all browsers:
button_xpath = '//xapth...'
button = driver.find_element_by_xpath(button_xpath)
driver.execute_script("arguments[0].click();", button)
Even I faced same problem today running tests on Edge, But when I observed the problem, after which step it's failing just check it up, after that step give a time delay of 5 to 10 seconds, by doing this it solved my problem. And i got the same error many times while running in Edge at different part of my program, i just added time delay at all those steps, it solved my problem and now test successfully running on EDGE.
I added delay by using
Thread.sleep(5000);
just try this, if it doesn't work for you, I found one other solution if it's failing at the time of clicking, that is perform click operation using javascript.
WebElement element = driver.findElement(By.id("gbqfd"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", element);
This solution I got from
https://softwaretestingboard.com/qna/363/word-around-for-edge-driver-click
https://softwaretestingboard.com/qna/745/excpetion-selenium-webdriverexception-element-obscured
First one worked for me.

How to make Selenium WebDriver wait for page to load when new page is loaded via JS event

I'm working on automating a site which has a number of links which load new pages via a JS event. Basically, there are elements which are clickable, clicking on one causes some JavaScript to run and this leads to a form being submitted and routing to a new page.
Now if these were just standard HTML links there would be no problem as Selenium is smart enough to tell that there's a new page coming and to wait to do things. But as good as it is, Selenium can't tell that the clicks in this instance are leading to new pages to load so it doesn't wait and just keeps going. As such it doesn't wait for the new page, tries to find elements which aren't there and my tests all fail. Bummer.
As a temporary solution I'm just pausing the program for three seconds like so:
oldPageDriver.clickThatButton();
try {
Thread.sleep(3000);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
newPageDriver = new NewPageDriver(driver);
newPageDriver.doStuffOnNewPage();
And this works, sort of. I don't like it because it's "hacky," and just interrupting the program instead of doing something smarter. Because the delay is hard coded at three seconds I get failures if the link is working but just slow. I've considered something like an implicit wait but that accomplishes the same thing and I've not found a solid, workable answer in Java anywhere after a considerable amount of looking.
So, can anyone suggest a way around this? Specifically, how to make Selenium know that a new page is expected and to wait until it's available?
The wait for the document.ready event is not the entire fix to this problem, because this code is still in a race condition: Sometimes this code is fired before the click event is processed so this directly returns, since the browser hasn't started loading the new page yet.
After some searching I found a post on Obay the testing goat, which has a solution for this problem. The c# code for that solution is something like this:
IWebElement page = null;
...
public void WaitForPageLoad()
{
if (page != null)
{
var waitForCurrentPageToStale = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
waitForCurrentPageToStale.Until(ExpectedConditions.StalenessOf(page));
}
var waitForDocumentReady = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
waitForDocumentReady.Until((wdriver) => (driver as IJavaScriptExecutor).ExecuteScript("return document.readyState").Equals("complete"));
page = driver.FindElement(By.TagName("html"));
}
`
I fire this method directly after the driver.navigate.gotourl, so that it gets a reference of the page as soon as possible. Have fun with it!
Explicit waits are what you need;
http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp
You can directly add this to your test or you may want to DRY it up, especially if there is a common wait expectation such as the disappearance of a spinning icon.
You could extend the click method to always wait after clicking or if following page objects, add a wait_until_loaded method to a base page class. There many other valid approaches but dependent on how the AUT is implemented
Simple ready2use snippet, working perfectly for me
static void waitForPageLoad(WebDriver wdriver) {
WebDriverWait wait = new WebDriverWait(wdriver, 60);
Predicate<WebDriver> pageLoaded = new Predicate<WebDriver>() {
#Override
public boolean apply(WebDriver input) {
return ((JavascriptExecutor) input).executeScript("return document.readyState").equals("complete");
}
};
wait.until(pageLoaded);
}

'sendKeys' are not working in Selenium WebDriver

I am not able to put any value in my application using WebDriver. My application is using frames.
I am able to clear the value of my textbox with driver.findElement(By.name("name")).clear();, but I'm unable to put any value using driver.findElement(By.name("name")).sendKeys("manish");. The click command works for another button on the same page.
I also had that problem, but then I made it work by:
myInputElm.click();
myInputElm.clear();
myInputElm.sendKeys('myString');
Before sendkeys(), use the click() method (i.e., in your case: clear(), click(), and sendKeys()):
driver.findElement(By.name("name")).clear();
driver.findElement(By.name("name")).click(); // Keep this click statement even if you are using click before clear.
driver.findElement(By.name("name")).sendKeys("manish");
Try clicking on the textbox before you send keys.
It may be that you need to trigger an event on the field before input and hopefully the click will do it.
I experienced the same issue and was able to collect the following solution for this:
Make sure element is in focus → try to click it first and enter a string.
If there is some animation for this input box, apply some wait, not static. you may wait for an element which comes after the animation. (My case)
You can try it out using Actions class.
Clicking the element works for me too, however, another solution I found was to enter the value using JavaScript, which doesn't require the element to have focus:
var _element= driver.FindElement(By.Id("e123"));
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
js.ExecuteScript("arguments[0].setAttribute('value', 'textBoxValue')", _element);
Use JavaScript to click in the field and then use sendkeys() to enter values.
I had a similar problem in the past with frames. JavaScript is the best way.
First pass the driver control to the frame using:
driver.switchTo().frame("pass id/name/index/webelement");
After that, perform the operation which you want to do on the webelement present inside the frame:
driver.findElement(By.name("name")).sendKeys("manish");
I have gone with the same problem where copy-paste is also not working for that text box.
The below code is working fine for me:
WebDriver driver = new FirefoxDriver();
String mobNo = "99xxxxxxxx";
WebElement mobileElementIrs =
driver.findElement(By.id("mobileNoPrimary"));
mobileElementIrs.click();
mobileElementIrs.clear();
mobileElementIrs.sendKeys(mobNo);
I had a similar problem too, when I used
getDriver().findElement(By.id(idValue)).clear();
getDriver().findElement(By.id(idValue)).sendKeys(text);
The value in "text" was not completely written into the input. Imagine that "Patrick" sometimes write "P" another "Pat",...so the test failed
The fix is a workaround and uses JavaScript:
((JavascriptExecutor)getDriver()).executeScript("$('#" + idValue + "').val('" + value + "');");
Now it is fine.
Instead of
driver.findElement(By.id("idValue")).sendKeys("text");
use,
((JavascriptExecutor)getDriver()).executeScript("$('#" + "idValue" + "').val('" + "text" + "');");
This worked for me.
I had a similar problem recently and tried some of the suggestions above, but nothing worked. In the end it fell back on a brute-force retry which retries if the input box wasn't set to what was expected.
I wanted to avoid thread.sleep for obvious reasons and saw different examples of it failing that looked like some kind of race or timing condition.
public void TypeText(string id, string text)
{
const int numberOfRetries = 5;
for (var i = 1; i < numberOfRetries; i++)
{
try
{
if (TryTypeText())
return;
}
catch (Exception)
{
if (i == numberOfRetries)
throw;
}
}
bool TryTypeText()
{
var element = _webDriver.FindElement(By.Id(id));
element.Click();
element.Clear();
element.SendKeys(text);
if (element.TagName.ToLower() == "input"
&& !DoesElementContainValue(element, text, TimeSpan.FromMilliseconds(1000)))
{
throw new ApplicationException($"Unable to set the type the text '{text}' into element with id {id}. Value is now '{element.GetAttribute("value")}'");
}
return true;
}
}
private bool DoesElementContainValue(IWebElement webElement, string expected, TimeSpan timeout)
{
var wait = new WebDriverWait(_webDriver, timeout);
return wait.Until(driver =>
{
try
{
var attribute = webElement.GetAttribute("value");
return attribute != null && attribute.Contains(expected);
}
catch (StaleElementReferenceException)
{
return false;
}
});
}
In my case, I had some actions.keyDowns(Keys.CONTOL).XXXX;
But I forgot to add the keyUp for that button and that prevented from sending keys and resulted in weird behaviors
Adding X.keyUp() after the x.keyDown() fixed the issue
Try using JavaScript to sendkeys().
WebElement element = driver.findElement(By.name("name"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", element);
More information on JavaScript Executor can be found at
JavascriptExecutor - Selenium.
Generally I keep a temporary variable. This should work.
var name = element(by.id('name'));
name.clear();
name.sendKeys('anything');