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){}
}
Related
After the selection of date from the date picker,clicking on 'View Report' button and then its take a time to generate the report and then it download the report.. My following code is working without an error but how do i use fluent wait instead of Thread.sleep(20000),(last line in below code). For fluent or explicit wait i ask to wait for what condition? Also wanted to verify whether the file has been downloaded or not with assertion. Any help will be appreciated.
public void generateReport() throws Exception {
clickDatePicker.click();
log.info("Select the Date from datepicker");
Select month = new Select(selectMonth);
month.selectByValue("0");
log.info("Selected the Month from datepicker");
Select year = new Select(selectYear);
year.selectByValue("2020");
log.info("Selected the Year from datepicker");
act.moveToElement(selectDate).click().build().perform();
buttonViewReport.click();
log.info("Finally clicked on Get Report button ");
Thread.sleep(20000);
}
Check the below method, which will make sure the script will wait until the download is started (for max of the minutes specified in the method call)
public void waitUntilDownloadStarted(WebDriver driver, int maxWaitTimeInMinutes) throws InterruptedException {
// Store the current window handle
String mainWindow = driver.getWindowHandle();
// open a new tab
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("window.open()");
// switch to new tab
// Switch to new window opened
for(String winHandle : driver.getWindowHandles()){
driver.switchTo().window(winHandle);
}
// navigate to chrome downloads
driver.get("chrome://downloads");
Instant startTime = Instant.now();
int elapsedTime = (int) Duration.between(startTime, Instant.now()).toMinutes();
// wait until the download is started
while ( (Long)js.executeScript("return document.querySelector('downloads-manager').shadowRoot.querySelectorAll('#downloadsList downloads-item').length") == 0) {
Thread.sleep(1000);
elapsedTime = (int) Duration.between(startTime, Instant.now()).toMinutes();
if (elapsedTime > maxWaitTimeInMinutes) {
break;
}
}
// close the downloads tab2
driver.close();
// switch back to main window
driver.switchTo().window(mainWindow);
}
Tested as below.
waitUntilDownloadStarted(driver, 10);
Does anything appears like that your download has been generated? or inspect any change in HTML. then you can use the following code to wait until change appears.
WebDriverWait wait=new WebDriverWait(driver, 20000);
wait.until(ExpectedConditions.numberOfElementsToBe(locator, number));
where 20000 is time in milliseconds
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;
}
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.
When I click on Help Screen in a web page, it opens a new web browser window containing information of of help webpage. I wanted to read some text or title of that webpage, but i can't able to read anything of that help window. The main objective in this case is to verify the help screen content and close that help window after verifying the help screen. The code i'm using is as follows:
public void verifyNewWindow(String buttonId, String screenShotFileName)
{
String winHandleBefore = driver.getWindowHandle();
clickOnButton(buttonId); //Clicking on help button on a webpage, help id is passed from baseclass)
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
for(String winHandle : driver.getWindowHandles()){
if(!winHandle.equals(winHandleBefore))
{
driver.switchTo().window(winHandle);
takeScreenShot(screenShotFileName);
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.close();
break;
}
}
driver.switchTo().window(winHandleBefore);
}
First get the window handles(not handle) after opening the new window.
Set<String> windows = driver.getWindowHandles();
Once you get the window handles then iterate through them and get the child window handle as below;
String parent = null;
String child = null;
Iterator it = windows.iterator();
while(it.hasNext())
{
parent = it.next();
child = it.next();
}
Then switch to the child window.
driver.switchTo().window(child);
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);