I wrote a function for window handling but it's not working in selenium webdriver - selenium

I am working on Selenium webdriver and I have write a function for window handling. I have written code for naukri.com popup handling. My scenario is to Open the naukri.com and without closing popup window. I want to switch main window and click on Login button.I have written the code and created a function. when I am running the script focus is going on main page and url is displayed as selected but I am not able to click on Login button. I am not understanding where the problem is.Please suggest me.
public static WebDriver fn_SetFocus_According_Title(WebDriver dObj, String arg_title)
{
Set<String> setcol_windowHandle=dObj.getWindowHandles();
Iterator<String>itcol_handleval=setcol_windowHandle.iterator();
while(itcol_handleval.hasNext()==true){
String windowhanldval=itcol_handleval.next();
dObj=dObj.switchTo().window(windowhanldval);
String apptitle=dObj.getTitle();
if(apptitle.contains(arg_title))
{
dObj=dObj.switchTo().window(arg_title);
}
}
return dObj;
}
}
WebDriver dObj = new FirefoxDriver();
dObj.manage().window().maximize();
dObj.get("https://www.naukri.com");
dObj.manage().timeouts().implicitlyWait(60,TimeUnit.SECONDS);
dObj=fn_SetFocus_According_Title(dObj,"Jobs - Recruitment - Job Search - Employment - Job Vacancies - Naukri.com");
dObj.findElement(By.xpath("//a[#id='login_Layer']")).click();

Make the following changes in your code:
Change to:
dObj.switchTo().window(windowhanldval);
Reduce the actual string of "arg_title" as you would be looking for this entire string within the String obtained by getTitle()
When you are already on that page trying to match the page title which means the focus is already on the actual page where we need to locate the Login button element. So remove the second switch () line entirely. Rather use "break" to come out if loop.
Let me know if these steps works for you.

The function below works for me.
public static void switchToWindow(String windowTitle)
{
for (String window : driver.getWindowHandles())
{
driver.switchTo().window(window);
if (driver.getTitle().equals(windowTitle))
{
return;
}
}
throw new InvalidParameterException("The window titled <" + windowTitle + "> does not exist.");
}
One issue you may run into is that when a new tab/window is created, you may need to wait for it to appear. To do that, you can use something like
int count = driver.getWindowHandles().size() + 1; // add 1 to the current window count
// do something that spawns a new window
new WebDriverWait(driver, 3).until(ExpectedConditions.numberOfWindowsToBe(count));
You don't need to return the WebDriver instance. It's the same driver instance you are already using. If the expected window title is not found, the function will throw an exception.

Hope this will work for you.
public void Parenthandle(WebDriver wb){
try {
String ParentPageHandle = wb.getWindowHandle();
for (String newPage : wb.getWindowHandles()) {
if (!ParentPageHandle.equals(newPage)) {
wb.switchTo().window(newPage);
}
}
} catch (Exception e) {
System.err.println(e.getMessage());
}

Related

Selenium click and wait

I have a registration form that register many users ,the problem in the first loop when I click on create it go too fast and didn't register the first one and resister the second ...,
so I use Thread.sleep(500);
I want to avoid using sleep
is there a way to do it
here is my code
#Given("user on registration page and create users")
public void user_on_registration_page_and_create_users() throws InterruptedException {
System.out.println(userLoginPageDataList);
for(UserLoginPageData userLoginPageData:userLoginPageDataList){
userRegistrationPage.init();
logger.info("*************************************** init the driver && go to registration page http://localhost:4200/register");
logger.info("*************************************** reading line "+userLoginPageData.getRowIndex() +" from Excel file");
userRegistrationPage.enterUserLogin(userLoginPageData.getUsername());
userRegistrationPage.enterUserPassword(userLoginPageData.getPassword());
userRegistrationPage.enterUserRole(userLoginPageData.getUserRole());
userRegistrationPage.clickOnCreate();
// Thread.sleep(500);
logger.info(userLoginPageData.getUsername()+" is registred");
}
}
You can use explicit(smart) wait.
WebDriverWait w = new WebDriverWait(driver, 5); //will wait 5 seconds most , but if element is visuble in the third second it will wait 3 sec.
w.until(ExpectedConditions.visibilityOfElementLocated(By.id("submit_btn")));
read more on When to use explicit wait vs implicit wait in Selenium Webdriver?
One of the possible solutions (when you work with PageFactory) is to implement your own Locator that can be extended from AjaxElementLocator.
Say you have a form and the form has some noticeable property saying that it is ready to accept the input (this might be some button state or displaying some label, etc).
So you can initialize your page object in the way its fields will be "available" if that condition is met.
This can be achieved using your custom Locator/LocatorFactory in your PageFactory.init().
For example here is the form of two fields. The condition saying it is ready for interaction is then create button is enabled:
class MyForm {
#FindBy(id = "user")
WebElement user;
#FindBy(id = "create")
WebElement create;
public MyForm(SearchContext searchContext){
PageFactory.initElements(field -> new AjaxElementLocator(searchContext, field, 10){
#Override
protected boolean isElementUsable(WebElement element) {
return create.isEnabled();
}
}, this);
}
}
Unless create button is enabled any attempt to invoke fields methods would be failing and the script will fail in 10 seconds of retries.
More details about how you use the conditions with page objects you can find in this post.

Selenium.StaleElementReferenceException on action.SendKeys after following link?

I am having some issues using selenium, and specifically using actions, although this could just be a symptom for a bigger issue. To quickly explain what try to do:
I scroll down to the bottom of a page using SendKeys(Keys.ArrowDown)
I press a button, and I change the page to a different language.
I try to scroll down on the new page using SendKeys(Keys.ArrowDown). This is where i receive an error!
The strange thing here is that i have no issues with the scrolling in step 1 even though I am using the same function, but in step 3 i receive an error message:
OpenQA.Selenium.StaleElementReferenceException: 'The element reference of is stale; either the element is no longer attached to the DOM, it is not in the current frame context, or the document has been refreshed'
I have tried to redeclare my footer variable, and also included it as a Footer class variable (originally it wasn't), but nothing i do change anything
The reason I am using SendKeys and not MoveToElement is due to MoveToElement doesn't work for off-screen elements in Firefox. I have included all relevant code below, including an image of the error and when it happens.
Could anyone please advice what I am doing wrong?
[TestMethod]
public void Reset_newsletter_subscription_form_BR_site()
{
Browser.Goto(siteUrl);
Webpage.Footer.GoTo_CountryPageViaFooter("br");
Webpage.Footer.ScrollToFooter(); // -> This is where it fails!
Other.Irrelevant.Stuff();
}
Below this is the Selenium parts:
public static class Browser
{
public static IWebDriver webDriver;
public static Actions actions;
public static void Goto(string url)
{
webDriver.Url = url;
}
}
public static class Webpage
{
public static Footer Footer
{
get
{
var footer = new Footer(Browser.webDriver, Browser.actions);
return footer;
}
}
}
public class Footer
{
private IWebDriver webDriver;
private Actions actions;
private IWebElement footer;
public Footer(IWebDriver webDriver, Actions actions)
{
this.webDriver = webDriver;
this.actions = actions;
}
public void GoTo_CountryPageViaFooter(string CountryTag)
{
footer = webDriver.FindElement(By.ClassName("c-footer"));
var changeCountryButton = footer.FindElement(By.ClassName("c-footer__toggle-country-selector"));
ScrollToFooter();
actions.MoveToElement(footer).Perform();
actions.MoveToElement(changeCountryButton).Perform();
changeCountryButton.Click();
var intPageLink = footer.FindElement(By.XPath("//*[#href='/" + CountryTag + "/']"));
intPageLink.Click();
}
public void ScrollToFooter()
{
footer = webDriver.FindElement(By.ClassName("c-footer"));
//MoveToElement does not work for Firefox, so a workaround is needed.
if (webDriver is FirefoxDriver)
{
int i = 0;
while (i < 5)
{
actions.SendKeys(Keys.ArrowDown).Perform(); //This is where it fails!
i++;
}
}
actions.MoveToElement(footer).Perform();
}
Image of the exception
Whenever Perform() method is invoked, it figures how to interact with the Page. So its job is to find out the active element present in the Page(if element not specified as in MoveToElement(element) or during clicking an element using Actions).
So in your case, as no Element is specified actions.SendKeys(Keys.ArrowDown).Perform(); so Actions will focus on any Active Element present in the Page and Perform the SendKeys Operation on that.
Details about Actions Interaction with Web Page..
So, as soon as the Language change link is getting clicked the Elements attached to the DOM are changing as a result Selenium Webdriver detects this as a change in the current Active Element as a result StaleElementReference Exception thrown.
In order to get rid of the Exception, you can add wait statement in between or there is a great way to handle StaleElementReference Exception given here
Thanks :)
I wouldn't use .SendKeys() to scroll the page. It won't be consistent. Imagine if the page is longer or shorter... how many times will you need to scroll? I think a better approach is to use JS to scroll the page to the desired element.
public void ScrollToFooter()
{
footer = webDriver.FindElement(By.ClassName("c-footer"));
// MoveToElement does not work for Firefox, so a workaround is needed
if (webDriver is FirefoxDriver)
{
IJavaScriptExecutor jse = (IJavaScriptExecutor)webDriver;
jse.ExecuteScript("arguments[0].scrollIntoView();", footer);
}
else
{
actions.MoveToElement(footer).Perform();
}
}
If you decide to stick with your method, you have a bug because of a missing else. If the driver is FF, after your scrolldown code is executed, it will execute .MoveToElement() and fail.
You could simplify this function to just use JS for all drivers.
public void ScrollToFooter()
{
footer = webDriver.FindElement(By.ClassName("c-footer"));
IJavaScriptExecutor jse = (IJavaScriptExecutor)webDriver;
jse.ExecuteScript("arguments[0].scrollIntoView();", footer);
}
Instead of
actions.SendKeys(Keys.ArrowDown).Perform();
I suggest:
webDriver.FindElement(By.cssSelector("body")).sendKeys(Keys.ArrowDown);

Selenium how to make click and hold button

In webpage I test is a modal which appears after pressing a button for circa 5sec.
And now I'm trying to make this in selenium.
I have method like this:
public static void ClickHold(IWebElement by)
{
SpecialInteractions.ClickAndHold(by);
}
where
public static Actions SpecialInteractions { get; set; }
and there is no hold time to set.
It looks like just clicking and releasing. Is there a way to wait for particular amount of time and then release?
Without digging dipper I can tell you the program above probably returns NulReference exception. I suspect you need to instantiate the Actions by wrapping the current driver instance.
Possible solution could be:
public void ClickHold(IWebElement element)
{
Actions action = new Actions(driver);
action.clickAndHold(webelement).build().perform();
//you need to release the control from the test
//actions.MoveToElement(element).Release();
}
Keep in mind that this will not work if you are using Selenium Grid. There is a bug that makes moveToElement an unrecognized command.
public static Boolean moveToThenSlowClickElement(final WebDriver driver, final WebElement toElement, final int millisecondsOfWaitTime) {
final Actions clickOnElementAndHold = new Actions(driver);
final Actions release = new Actions(driver);
clickOnElementAndHold.moveToElement(toElement).clickAndHold(toElement).perform();
sleep(millisecondsOfWaitTime);
release.release(toElement).perform();
final Action hoverOverCheckBox = clickOnElementAndHold.build();
hoverOverCheckBox.perform();
return true;
}

org.openqa.selenium.remote.SessionNotFoundException: The FirefoxDriver cannot be used after quit()

driver.findElement(By.xpath(OR.getProperty(object))).click();
System.out.println("Test");
Click works for some button.But on clicking a specific button in application.
But 'org.openqa.selenium.remote.SessionNotFoundException' erro comes after the above driver action. Test is not printed on console after that click. Why is it so?
public static void click(String object, String data){
try{
/*try
{
driver.switchTo().alert().accept();
}
catch(Exception e){}*/
new WebDriverWait(driver, 30).until(ExpectedConditions.elementToBeClickable(By.xpath(OR.getProperty(object))));
driver.findElement(By.xpath(OR.getProperty(object))).click();
System.out.println("Test");
Log.info("Clicking on Webelement "+ object);
}catch(Exception e){
Log.error("Not able to click --- " + e.getMessage());
DriverScript.bResult = false;
}
}
This is the code. Its a keyword driven framework. This action keyword gets executed 6 times perfectly. But on clicking some button which popups new window this error occurs. Switch window is supposed to be the next action keyword to be executed. But it is not reaching there . Just after .click it stands idle for long time. Then the above exception.
public static void switchwindow(String object,String data){
try{
parentHandle = driver.getWindowHandle();
System.out.println(driver.getWindowHandles().size());// get the current window handle
for (String winHandle : driver.getWindowHandles()) {
if(winHandle.equalsIgnoreCase("73e19507-bf40-44ce-822a-62630be49c2b"))
{driver.switchTo().window(winHandle);break;} // switch focus of WebDriver to the next found window handle (that's your newly opened window)
}
Log.info("Switched to new window");
}
catch(Exception e){
Log.error("Not able to switch the window --- " + e.getMessage());
DriverScript.bResult = false;
}
}
Seems that your browser is already closed.
I would simplified tests and not call quit anywhere in code.
I would also tried if problem exist in other browsers. Also U could debug or introduce sleeps to check where execly problem is.
I suspect there could be an issue with your code for switching windows. It would be better to debug if you could show the code for switching windows.

Problem using Selenium to automate a postback link that is inside an ASP.NET UpdatePanel [duplicate]

This question already has answers here:
Selenium IDE click() timeout
(2 answers)
Closed 3 years ago.
I have a GridView control with sorting enabled inside an UpdatePanel. I used Selenium IDE to record a test that clicks on the sort link of the table, but when I try to execute the test it get's stuck on the click command. Looking at the log I see:
[info] Executing: |click | link=Name | |
[error] Timed out after 30000ms
I haven't tried it with Selenium-RC yet, I don't know if it will be any different. I don't want Selenium to wait for anything. Any ideas of how to work around it?
Thanks!
when using selenium + Ajax (or the page just get refresh under certain conditions).
I usually use:
selenium.WaitForCondition
or I created the following code recently (the page uses frames).
public bool AccessElementsOnDynamicPage(string frame, Predicate<SeleniumWrapper> condition)
{
DateTime currentTime = DateTime.Now;
DateTime timeOutTime = currentTime.AddMinutes(6);
while (currentTime < timeOutTime)
{
try
{
SelectSubFrame(frame);
if (condition(this))
return true;
}
catch (SeleniumException)
{
//TODO: log exception
}
finally
{
currentTime = DateTime.Now;
}
}
return false;
}
public bool WaitUntilIsElementPresent(string frame, string locator)
{
return AccessElementsOnDynamicPage(frame, delegate(SeleniumWrapper w)
{
return w.IsElementPresent(locator);
});
}
public bool WaitUntilIsTextPresent(string frame, string pattern)
{
return AccessElementsOnDynamicPage(frame, delegate(SeleniumWrapper w)
{
return w.IsTextPresent(pattern);
});
}
Soon you will get to the point you will need selenium RC integrated on your development environment, for this I recommend you to read:
How can I make my Selenium tests less brittle?
It is around waiting but for specific elements that should be (or appear) on the page.