Selenium - driver.getWindowHandle() - Firefox stops after opening the new window - selenium

I'm using driver.getWindowHandle() for switching between windows. This is working fine in Chrome but in Firefox after clicking on the button that opens the new window, the execution doesn't continue, neither stops. How can I resolve it?
Edit :- Code shared in comment -
String parentWindow = driver.getWindowHandle();
driver.findElement(By.id("mybutton")).click();
Set<String> handles = driver.getWindowHandles();
Code:
String parentWindow = driver.getWindowHandle();
driver.findElement(By.id("myButton")).click();
Set<String> handles = driver.getWindowHandles();
for (String windowHandle : handles) {
if (!windowHandle.equals(parentWindow)) {
driver.switchTo().window(windowHandle);
//call methods
}
}
driver.switchTo().window(parentWindow); // cntrl to parent window

With Selenium 2.53.1 using firefox 47.0.1 as the WebDriver in Java: You need to open the separate windows/browsers in it's own driver. I have having the same problem. No matter how many windows or tabs I opened, "driver.getWindowHandles()" would only return one handle so it was impossible to switch between tabs. I found Chrome worked way better for me.
Once I started using Chrome 51.0, I could get all handles. The following code show how to access multiple drivers and multiple tabs within each driver.
// INITIALIZE TWO DRIVERS (THESE REPRESENT SEPARATE CHROME WINDOWS/BROWSERS)
driver1 = new ChromeDriver();
driver2 = new ChromeDriver();
// LOOP TO OPEN AS MANY TABS AS YOU WISH
for(int i = 0; i < TAB_NUMBER; i++) {
driver1.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL + "t");
// SLEEP FOR SPLIT SECOND TO ALLOW DRIVER TIME TO OPEN TAB
Thread.sleep(100);
// STORE TAB HANDLES IN ARRAY LIST FOR EASY ACCESS
ArrayList tabs1 = new ArrayList<String> (driver1.getWindowHandles());
// REPEAT FOR THE SECOND DRIVER (SECOND CHROME BROWSER WINDOW)
// LOOP TO OPEN AS MANY TABS AS YOU WISH
for(int i = 0; i < TAB_NUMBER; i++) {
driver2.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL + "t");
// SLEEP FOR SPLIT SECOND TO ALLOW DRIVER TIME TO OPEN TAB
Thread.sleep(100);
// STORE TAB HANDLES IN ARRAY LIST FOR EASY ACCESS
ArrayList tabs2 = new ArrayList<String> (driver2.getWindowHandles());
// NOW PERFORM DESIRED TASKS WITH FIRST BROWSER IN ANY TAB
for(int ii = 0; ii <= TAB_NUMBER; ii++) {
driver2.switchTo().window(tabs2.get(ii));
// LOGIC FOR THAT DRIVER'S CURRENT TAB
}
// PERFORM DESIRED TASKS WITH SECOND BROWSER IN ANY TAB
for(int ii = 0; ii <= TAB_NUMBER; ii++) {
drvier2.switchTo().window(tabs2.get(ii));
// LOGIC FOR THAT DRIVER'S CURRENT TAB
}
Hopefully that gives you a good idea of how to manipulate multiple tabs in multiple browser windows.

Related

Selenium WebDriver - Chrome issue [duplicate]

This question already has an answer here:
Best way to keep track and iterate through tabs and windows using WindowHandles using Selenium
(1 answer)
Closed 2 years ago.
Im wokring on a tool development that tests various services on Chrome browser. For each service I would need to launch a new tab on Chrome. I use the below code,
The first 2 new tabs works fine, when the 3rd tab is launched, the 1st tab's url is navigated to the one used for 3rd tab.
Not sure what's messing up. Need assistance!
I believe when your loop enters second iteration, your if statement executes to true.
You can just do following:
for(String actual: handles){
driver.switchTo().window(actual);
}
After execution of the above loop, your script will always point to last window opened.
Then you can do:
driver.get(URL + service + URL_);
outside the loop.
P.S.: If required, for more enhancement you can use below script:
private void switchToLatestBrowserWindow(WebDriver driver, Set<String> priorHandles)
{
new WebDriverWait(driver, 60).until( // keep trying to switch for 60 seconds
d -> {
Set<String> newHandles = d.getWindowHandles();
if (newHandles.size() != priorHandles.size()) {
log.Info("NewHandles Size not equal to PriorHandles size.");
String lastWindowHandle = "";
for (String windowHandle : newHandles) {
lastWindowHandle = windowHandle;
}
log.Info("LastWindowHandle Id: " + lastWindowHandle);
d.switchTo().window(lastWindowHandle);
log.Info("Switched window to " + lastWindowHandle);
return true;
} else {
return false;
}
});
}
priorHandles is set of window handles retrieved before opening new window. (the first line of code, in your case). So complete snippet would look like:
Set<String> priorHandles = driver.getWindowHandles();
((JavasriptExecutor) driver).executeScript( script: "window.open()");
switchToLatestBrowserWindow(driver, priorHandles);
driver.get(URL + service + URL_);

Focus on newly opened tab

I click a login button in my app that causes new tab to be openned but altough Chrome displays content of the new tab ChromeDriver still is operates on the old tab.
Question: How to make ChromeDriver "follow" newly opened tab so I can interact with elements in it?
when you open another tab using selenium, even though it opened another tab it will still operate on the parent tab(the one that is inside/invoked in the get method) in order to operate on the child tab(newly opened tab) you need to do this
//storing all the windows opened by default parent is index 0
Set<String>ids=driver.getWindowHandles();
Iterator<String> it = ids.iterator();
String parentId = it.next(); //1st one = parent tab
String childId = it.next(); //2nd one = child tab
driver.switchTo().window(childId); //switch to child window
System.out.println(driver.getTitle());
driver.switchTo().window(parentId); //switches back to parent window
You just need to switch to the new tab.
By default selenium driver will stay on the first tab that the driver has opened.
Selenium uses these 2 methods to handle it.
driver.getWindowHandle() [It will get the current tab handle]
driver.getWindowHandles() [It will get all the tab handles that are
open]
So, you need to store all the tabs in a variable and handle them one by one.
See the below example.
//I am using a set string "allWindowHandles1" to store all the tabs.
//I am using a simple string "handle1 " to handle the tabs one by one[if present]
//You can use the below for each loop in future if there is multiple child windows also
Set<String> allWindowHandles1 = driver.getWindowHandles();
for(String handle1 : allWindowHandles1) {
Thread.sleep(2000);
driver.switchTo().window(handle1);
//You can write your code to handle the elements in the child window here
//Now the driver will be in your child window
Thread.sleep(2000);
}
String winHandleNew = driver.getWindowHandle();
//Go through loop to get handle of newest window opened
for(String winHandle : driver.getWindowHandles()){
winHandleNew = winHandle;
}
// Switch to newest window opened
driver.switchTo().window(winHandleNew);
You need switch first, use .switchTo().window:
//handle original window
String original = driver.getWindowHandle();
//do something here to bring new window
btn.click();
for(String handle: driver.getWindowHandles()) {
driver.switchTo().window(handle);
if(!driver.getWindowHandle().equals(original)) {
//perform with new window
}
}
//back to original window
driver.switchTo().window(original);
With the above code you can switch again to original window.

Download PDF file opening as URL in different tab in selenium

Scenario:
I have an application, say A: When we log in to A, we have one link say B clicking on which will open a new browser.
In browser B we have one Link that will open a pdf. Once click on that the PDF is opening as URL in the 2nd tab where we had opened the page A.
Problem:
I have tried switching using iteration through window handle but it is not finding that. I have also tried adding below to find all the window handle where you have below locator.
if(driver.findElement(By.xpath("//*[#id="plugin"]")))
but as PDF URL has opened in a 2nd tab, I am not able to get the window handle. I think as per my code below, if I get Window handle then I will use robot class and save the PDF.
Note : I am using xframium framework so, had to define
WebDriver driver = getCustumWebDriver();
I can only use IE/Chrome and no other browsers
Any suggestions on how to solve?
Code:
public String getWindowUrl(String saveDir, SoftAssert softAssert, Element element)
{
boolean success = false;
String newWindowUrl = null;
try {
WebDriver driver = getCustumWebDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
//current window handle
String beforWindowHandle = driver.getWindowHandle();
_wait(2000);
//Click on the element to which the pdf link is opened
_click(element);
waitForPageLoad();
_wait(30000);
Set<String> allWindowhandles = driver.getWindowHandles();
for(String handle1 : allWindowhandles)
{
if(!handle1.equals(beforWindowHandle))
{
driver.switchTo().window(handle1);
_wait(2000);
newWindowUrl = driver.getCurrentUrl();
docName = newWindowUrl.replaceAll("[^0-9]+", "");
docName = saveDir.concat(docName).concat(".pdf");
Robot rb = new Robot();
rb.keyPress(KeyEvent.VK_CONTROL);
rb.keyPress(KeyEvent.VK_S);
_wait(3000);
rb.keyPress(KeyEvent.VK_CONTROL);
rb.keyPress(KeyEvent.VK_C);
rb.keyRelease(KeyEvent.VK_C);
rb.keyRelease(KeyEvent.VK_CONTROL);
_wait(1000);
rb.keyPress(KeyEvent.VK_HOME);
rb.keyRelease(KeyEvent.VK_HOME);
_wait(3000);
StringSelection stringSelection = new StringSelection(saveDir);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(stringSelection, stringSelection);
rb.keyPress(KeyEvent.VK_CONTROL);
rb.keyPress(KeyEvent.VK_V);
rb.keyRelease(KeyEvent.VK_V);
rb.keyRelease(KeyEvent.VK_CONTROL);
rb.delay(3000);
// _wait(3000);
rb.keyPress(KeyEvent.VK_ENTER);
rb.keyRelease(KeyEvent.VK_ENTER);
_wait(2000);
}
}
success = true;
driver.close();
}
Scenario 2 :
I can force the application to open a new browser window just for PDF but I am not able to get to that specific window where new PDF URL will open.
I will try the below and give my observation:
**for(String handle1 : allWindowhandles)
{
// change focus to new tab
driver.switchTo().window(handle1);
if(!(driver.findElement(By.id("Element that will be present on browser window 1 - A ")).isDisplayed()||
driver.findElement(By.id("Element that will be present on browser window 2 - B ")).isDisplayed()))
{
rb.keyPress(KeyEvent.VK_CONTROL);
rb.keyPress(KeyEvent.VK_S);
_wait(3000);
rb.keyPress(KeyEvent.VK_CONTROL);
rb.keyPress(KeyEvent.VK_C);
rb.keyRelease(KeyEvent.VK_C);
rb.keyRelease(KeyEvent.VK_CONTROL);
_wait(1000);
rb.keyPress(KeyEvent.VK_HOME);
rb.keyRelease(KeyEvent.VK_HOME);
_wait(3000);
StringSelection stringSelection = new StringSelection(saveDir);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(stringSelection, stringSelection);
rb.keyPress(KeyEvent.VK_CONTROL);
rb.keyPress(KeyEvent.VK_V);
rb.keyRelease(KeyEvent.VK_V);
rb.keyRelease(KeyEvent.VK_CONTROL);
rb.delay(3000);
// _wait(3000);
rb.keyPress(KeyEvent.VK_ENTER);
}**
As per my understanding,Developer of that application that you are referring has configured the pdf launching in new tab.so we cannot open it in same tab because it has already configured in application label.
Just call this method:
public void switchToNEWwindow(){
try{
ArrayList<String> newTab = new ArrayList<String> (driver.getWindowHandles());
driver.switchTo().window(newTab.get(1));
}
catch(Exception e){}
}

Get the on-screen location of web page with Selenium WebDriver

Is there a way to get the on-screen coordinates of HTML window (page body) with Selenium WebDriver?
Seen this a few times and haven't found an elegant solution from WebDriver yet (they have a param that looks to support in in their ILocatable settings but the method is not implemented yet).
What I do is use UIAutomation to get the windows AutomationElement and use a treewalker to find the actual object of the window - downside is I noticed the browsers occasionally update what their window is so the conditionals have to change every once in awhile to accommodate.
Here is some example code (I removed some company code here so it's more elegant on my end but this should work for C#)
public static Rectangle GetAbsCoordinates(this IWebElement element)
{
var driver = GetDriver(element);
var handle = GetIntPtrHandle(driver);
var ae = AutomationElement.FromHandle(handle);
AutomationElement doc = null;
var caps = ((RemoteWebDriver) driver).Capabilities;
var browserName = caps.BrowserName;
switch (browserName)
{
case "safari":
var conditions = (new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Pane),
new PropertyCondition(AutomationElement.ClassNameProperty, "SearchableWebView")));
doc = ae.FindFirst(TreeScope.Descendants, conditions);
break;
case "firefox":
doc = ae.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Document));
break;
case "chrome":
doc = ae.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Chrome Legacy Window"));
if (doc == null)
{
doc = ae.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Google Chrome"));
if (doc == null)
throw new Exception("unable to find element containing browser window");
doc = doc.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Document));
}
break;
case "internet explorer":
doc = ae.FindFirst(TreeScope.Descendants, new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Pane),
new PropertyCondition(AutomationElement.ClassNameProperty, "TabWindowClass")));
break;
}
if (doc == null)
throw new Exception("unable to find element containing browser window");
var iWinLeft = (int) doc.Current.BoundingRectangle.Left;
var iWinTop = (int)doc.Current.BoundingRectangle.Top;
var coords = ((ILocatable) element).Coordinates;
var rect = new Rectangle(iWinLeft + coords.LocationInDom.X, iWinTop + coords.LocationInDom.Y, element.Size.Width, element.Size.Height);
return rect;
}
public static IWebDriver GetDriver(this IWebElement e)
{
return ((IWrapsDriver)e).WrappedDriver;
}
public static IntPtr GetIntPtrHandle(this IWebDriver driver, int timeoutSeconds = Timeout)
{
var end = DateTime.Now.AddSeconds(timeoutSeconds);
while(DateTime.Now < end)
{
// Searching by AutomationElement is a bit faster (can filter by children only)
var ele = AutomationElement.RootElement;
foreach (AutomationElement child in ele.FindAll(TreeScope.Children, Condition.TrueCondition))
{
if (!child.Current.Name.Contains(driver.Title)) continue;
return new IntPtr(child.Current.NativeWindowHandle);;
}
}
return IntPtr.Zero;
}
The posted code by Zechtitus is amazing, I tried it under IE11 and Chrome Version 39.0.2171.95 m and it worked like a charm. Although I had to pass the real object of IWebDriver instead of using WrappedDriver because it doesn't work with Chrome. Just for your info, I have Win 7 ultimate x64 and using Selenium WebDriver 2.44. this is the code that I took it from Zechtitus and modified it:
public static Rectangle GetAbsCoordinates(IWebDriver driver, IWebElement element)
{
var handle = GetIntPtrHandle(driver);
var ae = AutomationElement.FromHandle(handle);
AutomationElement doc = null;
var caps = ((RemoteWebDriver)driver).Capabilities;
var browserName = caps.BrowserName;
switch (browserName)
{
case "safari":
var conditions = (new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Pane),
new PropertyCondition(AutomationElement.ClassNameProperty, "SearchableWebView")));
doc = ae.FindFirst(TreeScope.Descendants, conditions);
break;
case "firefox":
doc = ae.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Document));
break;
case "chrome":
doc = ae.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Chrome Legacy Window"));
if (doc == null)
{
doc = ae.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Google Chrome"));
if (doc == null)
throw new Exception("unable to find element containing browser window");
doc = doc.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Document));
}
break;
case "internet explorer":
doc = ae.FindFirst(TreeScope.Descendants, new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Pane),
new PropertyCondition(AutomationElement.ClassNameProperty, "TabWindowClass")));
break;
}
if (doc == null)
throw new Exception("unable to find element containing browser window");
var iWinLeft = (int)doc.Current.BoundingRectangle.Left;
var iWinTop = (int)doc.Current.BoundingRectangle.Top;
var coords = ((ILocatable)element).Coordinates;
var rect = new Rectangle(iWinLeft + coords.LocationInDom.X, iWinTop + coords.LocationInDom.Y, element.Size.Width, element.Size.Height);
return rect;
}
public static IntPtr GetIntPtrHandle(this IWebDriver driver, int timeoutSeconds = 20)
{
var end = DateTime.Now.AddSeconds(timeoutSeconds);
while (DateTime.Now < end)
{
// Searching by AutomationElement is a bit faster (can filter by children only)
var ele = AutomationElement.RootElement;
foreach (AutomationElement child in ele.FindAll(TreeScope.Children, Condition.TrueCondition))
{
if (!child.Current.Name.Contains(driver.Title)) continue;
return new IntPtr(child.Current.NativeWindowHandle); ;
}
}
return IntPtr.Zero;
}
and I used it like this:
Rectangle recView = GetAbsCoordinates(MyWebDriverObj, myIWebElementObj);
the correct X, Y are then stored in recView.X and recView.Y
As I said, it's working for me for both IE11 and Chrome.
Good luck
hmmm, I cannot directly comment to the one user asking about chrome so I will have to add another comment here.
Basically for UIAutomation you will want to get your hands on a tool called inspect (comes free in the 8.1 SDK). Older tools like uispy would probably work as well.
Basically you would fire up chrome and then fire up the inspector tool - your going to look at the tree like structure and then navigate down to the document which contains the DOM. Turn on highlighting in the tool to make this easier.
Chrome is quite dynamic it seems in the layout of the tree controls - have had to modify it a few times to accomodate the control I am looking at. If your using a different version than I had - basically find the document window in the tree and take a look at all of the control patterns associated with it - this is what I am passing into the PropertyCondition for how to search for the control. Intellisense should bring you up different things to query for like AutomationElement.NameProperty. It the example I had - I noticed there is a difference between when I run chrome on a winXP machine vs a win8 machine... hence the checking for null.
Like I have said before - this is not elegant and would be awesome if it was inbuilt into Selenium (I imagine they have much better methods for determining the coords of the DOM area)... I think this will also be problematic for people moving to Selenium Grid (like I am looking at doing) - far as I know with using it I don't know if you can shuttle over a bunch of supporting dll to selenium to the remote machine... at least without a lot of hacks.
If it still doesn't work for you - give me a specific idea on the OS, Chrome version and I'll try to take a look and give exact Property match. Probably best though if you fiddle yourself as these things are not static unfortunately.
Yes. Its possible. With little trick. Find below my code to get on
screen top position of web element.
public static long getScrollYPosition() {
WebDriver driver = DriverFactory.getCurrentDriver();
JavascriptExecutor jse = (JavascriptExecutor) driver;
Long scrollYPos = (Long) jse.executeScript("return window.scrollY;");
return scrollYPos;
}
long scrollPosition = getScrollYPosition();
long elemYPositionOnScreen = (long) elem.getLocation().getY() - scrollPosition;
you can try in this way:
WebDriver driver=new FirefoxDriver();
driver.get("http://www.google.com");
JavascriptExecutor js=(JavascriptExecutor) driver;
Double i= (Double) js.executeScript("var element = document.getElementById('hplogo');var position = element.getBoundingClientRect();return position.left");
System.out.print(i);
I took a quick look at chrome and you may have better luck with the following.
doc = win.Find.ByConditions(new PropertyCondition(AutomationElement.ClassNameProperty, "Chrome_RenderWidgetHostHWND"));
I think that class name is consistent for chrome... seems to work on older and newer OS's for me - chrome version 34.0.1847.116m. Hope that helps.
This should work once it's supported:
WebElement htmlElement = driver.findElement(By.tagName("html"));
Point viewPortLocation = ((Locatable) htmlElement).getCoordinates().onScreen();
int x = viewPortLocation.getX();
int y = viewPortLocation.getY();
However right now it's throwing the following error:
java.lang.UnsupportedOperationException: Not supported yet.
at org.openqa.selenium.remote.RemoteWebElement$1.onScreen(RemoteWebElement.java:342)
(on org.seleniumhq.selenium:selenium-java:2.46.0)
I needed a this in Robot Framework and I was inspired by Jeyabal's solution, so here is an adaptation that works for me:
${verticalWindow}= Execute Javascript return window.scrollY;
${verticalElement} = Get Vertical Position /xpath
${hasScrolled} = Evaluate (${verticalElement} - ${verticalWindow}) == 0
Nothing from above worked for me. A workaround is to use window.innerHeight and window.innerWidth and work your way up from the the left, bottom corner. This assumes that the browser bottom border is almost 0 (no horizontal scrollbar or thick window decoration).
win_pos = selenium.get_window_position()
win_size = selenium.get_window_size()
win_bottom_y = win_pos['y'] + win_size['height']
# We assume viewport x == window x. For y coordinate we take the bottom
# of the browser and subtract the viewport height
viewport_height = selenium.execute_script('return window.innerHeight')
viewport_width = selenium.execute_script('return window.innerWidth')
viewport_y = win_bottom_y - viewport_height
This is not 100% accurate but it's a good workaround that can be tweaked for your case.
SOOO many factors have to be considered to get the element position relative to the screen. For the longest time I was using the UIAutomation code above, but UIAutomation is unreliable, it crashes or fails to find the browser (for some reason), with EdgeDriver, tabs crash consistently making getting the values via UIAutomation now as a 'fallback'.
That said, when it works, the answer is GOLDEN as to the on-screen coordinates of the HTML page.
However, something that always works is using javascript. So we calculate that first, then also attempt to call UIAutomation. If UIAutomation fails, we use this code's answer. If UIAutomation works, we use the UIAutomation values.
// use javascript to get our html document location, but it's off by 2 pixels compared to uiautomation. uiautomation, however, failed so often that is was unreliable
int outerHeight = Int32.Parse(BrowserHelper.ExecuteJavascript(browser, "return window.outerHeight"));
int innerHeight = Int32.Parse(BrowserHelper.ExecuteJavascript(browser, "return window.innerHeight"));
int outerWidth = Int32.Parse(BrowserHelper.ExecuteJavascript(browser, "return window.outerWidth"));
int innerWidth = Int32.Parse(BrowserHelper.ExecuteJavascript(browser, "return window.innerWidth"));
int browserNavHeight = outerHeight - innerHeight;
int browserNavWidth = outerWidth - innerWidth;
iWinLeft = browserNavWidth + 2;
iWinTop = browserNavHeight + 2;
`
Try this, I hope it will help you :
Rectangle rec = new Rectangle(element.getLocation(), element.getSize());

How can selenium web driver get to know when the new window has opened and then resume its execution

I am facing an issue in automating a web application using selenium web driver.
The webpage has a button which when clicked opens a new window. When I use the following code, it throws OpenQA.Selenium.NoSuchWindowException: No window found
WebDriver.FindElement(By.Id("id of the button that opens new window")).Click();
//Switch to new window
_WebDriver.SwitchTo().Window("new window name");
//Click on button present on the newly opened window
_WebDriver.FindElement(By.Id("id of button present on newly opened window")).Click();
To solve the above issue I add Thread.Sleep(50000); between the button click and SwitchTo statements.
WebDriver.FindElement(By.Id("id of the button that opens new window")).Click();
Thread.Sleep(50000); //wait
//Switch to new window
_WebDriver.SwitchTo().Window("new window name");
//Click on button present on the newly opened window
_WebDriver.FindElement(By.Id("id of button present on newly opened window")).Click();
It solved the issue, but I do not want to use the Thread.Sleep(50000); statement because if the window takes more time to open, code can fail and if window opens quickly then it makes the test slow unnecessarily.
Is there any way to know when the window has opened and then the test can resume its execution?
You need to switch the control to pop-up window before doing any operations in it. By using this you can solve your problem.
Before opening the popup window get the handle of main window and save it.
String mwh=driver.getWindowHandle();
Now try to open the popup window by performing some action:
driver.findElement(By.xpath("")).click();
Set s=driver.getWindowHandles(); //this method will gives you the handles of all opened windows
Iterator ite=s.iterator();
while(ite.hasNext())
{
String popupHandle=ite.next().toString();
if(!popupHandle.contains(mwh))
{
driver.switchTo().window(popupHandle);
/**/here you can perform operation in pop-up window**
//After finished your operation in pop-up just select the main window again
driver.switchTo().window(mwh);
}
}
You could wait until the operation succeeds e.g., in Python:
from selenium.common.exceptions import NoSuchWindowException
from selenium.webdriver.support.ui import WebDriverWait
def found_window(name):
def predicate(driver):
try: driver.switch_to_window(name)
except NoSuchWindowException:
return False
else:
return True # found window
return predicate
driver.find_element_by_id("id of the button that opens new window").click()
WebDriverWait(driver, timeout=50).until(found_window("new window name"))
WebDriverWait(driver, timeout=10).until( # wait until the button is available
lambda x: x.find_element_by_id("id of button present on newly opened window"))\
.click()
I finally found the answer,
I used the below method to switch to the new window,
public String switchwindow(String object, String data){
try {
String winHandleBefore = driver.getWindowHandle();
for(String winHandle : driver.getWindowHandles()){
driver.switchTo().window(winHandle);
}
}catch(Exception e){
return Constants.KEYWORD_FAIL+ "Unable to Switch Window" + e.getMessage();
}
return Constants.KEYWORD_PASS;
}
To move to parent window, i used the following code,
public String switchwindowback(String object, String data){
try {
String winHandleBefore = driver.getWindowHandle();
driver.close();
//Switch back to original browser (first window)
driver.switchTo().window(winHandleBefore);
//continue with original browser (first window)
}catch(Exception e){
return Constants.KEYWORD_FAIL+ "Unable to Switch to main window" + e.getMessage();
}
return Constants.KEYWORD_PASS;
}
I think this will help u to switch between the windows.
I use this to wait for window to be opened and it works for me.
C# code:
public static void WaitUntilNewWindowIsOpened(this RemoteWebDriver driver, int expectedNumberOfWindows, int maxRetryCount = 100)
{
int returnValue;
bool boolReturnValue;
for (var i = 0; i < maxRetryCount; Thread.Sleep(100), i++)
{
returnValue = driver.WindowHandles.Count;
boolReturnValue = (returnValue == expectedNumberOfWindows ? true : false);
if (boolReturnValue)
{
return;
}
}
//try one last time to check for window
returnValue = driver.WindowHandles.Count;
boolReturnValue = (returnValue == expectedNumberOfWindows ? true : false);
if (!boolReturnValue)
{
throw new ApplicationException("New window did not open.");
}
}
And then i call this method in the code
Extensions.WaitUntilNewWindowIsOpened(driver, 2);
You can wait for another window to pop using WebDriverWait.
First you have to save current handles of all opened windows:
private Set<String> windowHandlersSet = driver.getWindowHandles();
Then you click a button to open a new window and wait for it to pop with:
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(driver -> !driver.getWindowHandles().equals(windowHandlersSet));
Which checks if there is a change to current window handles set comparing to saved one. I used this solutnion writing tests under Internet Explorer where it always takes few seconds to open new window.
WebDriverWait wait = new WebDriverWait(driver,Duration.ofSeconds(max duration you want it to check for new window));
wait.until(ExpectedConditions.numberOfWindowsToBe(2));//here 2 represents the current window and the new window to be opened
Although this question already has answers, none of them was useful to me really since I can't rely on getting any new window, I needed to filter even more, so I started using Dadoh's solution but tweaked it until I came up with this solution, hope it will be of some use to someone.
public async Task<string> WaitUntilNewWindowIsOpen(string expectedWindowTitle, bool switchToWindow, int maxRetryCount = 100)
{
string newWindowHandle = await Task.Run(() =>
{
string previousWindowHandle = _driver.CurrentWindowHandle;
int retries = 0;
while (retries < maxRetryCount)
{
foreach (string handle in _driver.WindowHandles)
{
_driver.SwitchTo().Window(handle);
string title = _driver.Title;
if (title.Equals(expectedWindowTitle))
{
if(!switchToWindow)
_driver.SwitchTo().Window(previousWindowHandle);
return handle;
}
}
retries++;
Thread.Sleep(100);
}
return string.Empty;
});
return newWindowHandle;
}
So in this solution I opted to pass the expected window title as an argument for the function to loop all windows and compare the new window title, this way, it's guaranteed to return the correct window. Here is an example call to this method:
await WaitUntilNewWindowIsOpen("newWindowTitle", true);
Below function can wait for given max time until your new window is open
public static void waitForWindow(int max_sec_toWait, int noOfExpectedWindow) {
FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver);
wait.pollingEvery(Duration.ofMillis(200));
wait.withTimeout(Duration.ofSeconds(max_sec_toWait));
wait.ignoring(NoSuchWindowException.class);
Function<WebDriver, Boolean> function = new Function<WebDriver, Boolean>(){
#Override
public Boolean apply(WebDriver driver) {
Set<String> handel = driver.getWindowHandles();
if(handel.size() == noOfExpectedWindow)
return true;
else
return false;
}
};
wait.until(function);
}
Js code
await firstPage.clickOnLink();
let tabs = await driver.getAllWindowHandles();
await driver.switchTo().window(tabs[1]);
await driver.wait(await until.titleContains('myString'), 2000);