I have a situation(mentioned below) due to which my selenium script is failing. Can someone help me?
I have a webpage where there is a save button, clicking on save button opens a new popup window. My requirement is to switch to the new window and click on one of the buttons(in the new window) which will automatically close the window and navigates to some other page. I have written a code which actually works fine but sometimes due to the application problem the new window is not getting closed. And due to this my script is failing. Here is the code I have used.
public void test() {
// i have two pages gets involved in this scenario
driver.get("some url"); // user is in page 1
// clicking on save button
driver.findElement(By.xpath("some xpath")).click(); // a new window opens
Set<String> winIDS = driver.getWindowHandles();
if (winIDS.size() > 1) {
Iterator<String> it = winIDS.iterator();
it.next();
String childWindow = it.next();
driver.switchTo().window(childWindow);
driver.findElement(By.xpath("some xpath")).click();
//after clicking on this button the user is navigated to page2
}
// after clicking on the button in the new window the new window gets closed and the user is navigate to page 2 as mentioned before.
// To validate if that has happened i am using the below code so that my test case flow wont be stopped. But
// the code is getting hanged at the new window as the app fails to perform the button click action on the new window.
winIDS = driver.getWindowHandles();
if(winIDS.size() > 1)
{
Iterator<String> it = winIDS.iterator();
it.next();
String childWindow = it.next();
driver.switchTo().window(childWindow);
driver.close();
//i m making the test failed here as the new window is not closed.
}
}
Looking at your code, I can see that you do twice the iteration to next window:
it.next();
String childWindow = **it.next();**
The second it.next() is obsolet.
Hope this solvs your issue.
Related
There is a print button in my application. When I click on the button print windows open with cancel and print button.
I want to click on cancel button in the print window.
I know handling print window is not possible using selenium webdriver alone. I tried using Robot class. But it is not working.
WebDriver driver = (WebDriver) new ChromeDriver();
driver.get("https://www.joecolantonio.com/SeleniumTestPage.html");
driver.manage().window().maximize();
Thread.sleep(2000);
//clicking on the print button
driver.findElement(By.id("printButton")).click();
//print window opens
//creating robot class object
Robot r = new Robot();
r.delay(1000);
r.keyPress(KeyEvent.VK_ESCAPE);
r.keyRelease(KeyEvent.VK_ESCAPE);
The print window opens but nothing happens after that. I was expecting escape button will make the window exit but its does not happens. But manually when I press escape button print window disappears.
Actually you can handle print page window using javascript executor in selenium.
following codes are c#.
If your program is stuck after opening window.print(); which in my case it was happening, try to use the following javascript code instead:
setTimeout(function() { window.print(); }, 0);
this will release your application and you can work with the print page.
then you can switch to the print page simply by the following line:
driver.SwitchTo().Window(driver.WindowHandles.Last());
then you can get the JSPath of any element in print window and interact with it
(IWebElement)js.ExecuteScript($"return {JSPath}").Click();
A complete example of this, is as follows where print window will be opened then the cancel button will be clicked after 2 seconds.
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
js.ExecuteScript("setTimeout(function() { window.print(); }, 0);");
driver.SwitchTo().Window(driver.WindowHandles.Last());
Thread.Sleep(2000);
string JSPath = "document.querySelector('body>print-preview-app').shadowRoot.querySelector('#sidebar').shadowRoot.querySelector('print-preview-button-strip').shadowRoot.querySelector('cr-button.cancel-button')";
IWebElement cancelBtn = (IWebElement)js.ExecuteScript($"return {JSPath}");
cancelBtn.Click();
Since the elements in print window exist in the shadow root you cannot select them by selenium web driver that's why I used Javascript Executor to get the cancel button.
Use tab and then click escape.I think it works.
Using Robot is not something I would recommend to handling the print preview page as it will bite you back when you will be running your tests in Parallel mode.
You could click "Cancel" button as follows:
Switch to the Print Preview window using driver.switchTo() function:
driver.switchTo().window(driver.getWindowHandles().stream().filter(handle -> !handle.equals(driver.getWindowHandle())).findAny().get());
Find preview-app Shadow DOM element using i.e. XPath and convert it into a WebElement
WebElement printPreviewApp = driver.findElement(By.xpath("//print-preview-app"));
WebElement printPreviewAppContent = (WebElement) driver.executeScript("return arguments[0].shadowRoot", printPreviewApp);
Find preview-header Shadow DOM element using i.e. CSS and convert into a Selenium's Web Element
WebElement printPreviewHeader = printPreviewAppContent.findElement(By.cssSelector("print-preview-header"));
WebElement printPreviewHeaderContent = (WebElement) driver.executeScript("return arguments[0].shadowRoot", printPreviewHeader);
Locate Cancel button and click it
printPreviewHeaderContent.findElement(By.cssSelector("paper-button[class*=cancel]")).click();
Answer for someone else who still looking solution
To download save as a pdf from the print pop-up window from any web
Add argument
options.addArguments("kiosk-printing");
This will prevent to open any popups from clicking on any print button.But a window dialog folder will open to download the file as a pdf.
Now you need to input the file name and press enter button. For this, we will use the robot class
StringSelection s=new StringSelection("remotePetrol_report.pdf"); // Set the File Name
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(s,null);
//native keystrokes for CTRL, V, and ENTER keys
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_V);
robot.keyRelease(KeyEvent.VK_V);
robot.keyRelease(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ENTER);
I have an Ecommerce website and on one page there is a button named Place Order. When I click on the Place Order button, then it allows me to open a new window named Paypal. I need to stay on the same tab without opening the new window. After that I need to click on the element for that Paypal page.
How can I do this?
My code is as follows:
String parent_handle= driver.getWindowHandle();
System.out.println(parent_handle);
driver.findElement(By.xpath(".//*[#id='co-place-order-area']/div[2]/div[3]/div/button")).click();
new WebDriverWait(driver,10).until(ExpectedConditions.numberOfWindowsToBe(1));
Set<String> handles = driver.getWindowHandles();
System.out.println(handles);
for(String handle1:handles)
if(!parent_handle.equals(handle1))
{
driver.switchTo().window(handle1);
System.out.println(handle1);
}
I don't know about java but in C# you would use PopupWindowFinder class
var target = driver.findElement(By.xpath(".//*[#id='co-place-order-area']/div[2]/div[3]/div/button"));
PopupWindowFinder finder = new PopupWindowFinder(driver);
var parent = driver.CurrentWindowHandle;
string newHandle = finder.Click(target);
driver.SwitchTo().Window(newHandle);
Then after you deal with the new window you can switch back to the parent window.
Hi I had posted a question along these lines recently but this is now a little more specific to my requirements. So, I have an Application where the user needs to log in. The log in process can take some time so I decided to put up a little animated GIF to show it is doing something. Sounds simple...!!??
I noticed soon that the login process was freezing the animation so I thought, I will put the login process on its own thread. I had countless instances of it referencing objects on the UI Thread so thought I would try the other way round and have the Image display on a new thread. Same issue - so I decided to create a new window containing the image, format it accordingly and display this as a new thread! Simple! That (bit) worked... I click to login, animation appears and disappears onces login is complete. So the Thread variable is set as global one:
Friend g_thLoading As Thread
And when the Login button is clicked I have the following:
g_thLoading = New Thread(AddressOf LoginSplashScreen)
g_thLoading.SetApartmentState(ApartmentState.STA)
g_thLoading.IsBackground = True
g_thLoading.Name = "LoginThread"
g_thLoading.Start()
VerifyLogin() 'Process that takes a while...
g_thLoading.Abort()
Then the method that is called in the new thread:
Sub LoginSplashScreen()
Dim SplashScreenWin As New SplashScreen()
Try
SplashScreenWin.ShowDialog()
System.Windows.Threading.Dispatcher.Run()
Catch ex As Exception
SplashScreenWin.Close()
SplashScreenWin = Nothing
End Try
End Sub
This works - but not if I have to click the button more than once. However If (for example) the user enters the wrong credentials, clicks login (the above processes and completes) they are prompted to re-enter - click the login button again... but this time, the window doesnt display (but oddly does appear in the Task Bar)... Then the application is forced to close (nothing in debug on why that is).
I am confident that the Dialogue Window is closing correctly after the first instance as i) it is no longer in the Task Bar and secondly I have put some checks on the Windows Close event. I am fairly confident that the created Thread is closed after the first instance as I can see it drop off from the Thread Window in Visual Studio... So - I am at a total loss. I have also tried the Join function on the thread but this just hangs the process before it gets to g_thLoading.Abort()
I am open to any advice on how I can go about achieving my end goal... whether it is expanding on what I have done here or another suggestion altogether. I have messed around with the Background Worker but not had much more luck there.
Use the BackgroundWorker class to implement your long running processes. The class allows you to specify code that will run on a background thread (in the DoWork event handler), code that will run during "updates" on the thread that created the BackgroundWorker in the ProgressChanged event handler, and code that will run when the process completes, again on the thread that created the BackgroundWorker in the RunWorkerCompleted event handler.
Using it goes something like this:
private class LoginParameters {
public string Name { get; set; }
public string Password { get; set; }
// Any other properties needed
}
// Make this a property of your form.
BackgroundWorker LoginWorker { get; set; }
// Somewhere in your UI code after the user clicks the "login button"
LoginWorker = new BackgroundWorker();
LoginWorker.WorkerReportsProgress = true;
LoginWorker.WorkerSupportsCancellation = true; // Can set to false if you don't allow the operation to be cancelled.
LoginWorker.DoWorker += DoLogin;
LoginWorker.ProgressChanged += ReportProgress;
LoginWorker.RunWorkerCompleted += LoginFinished;
LoginParameters login = new LoginParameters {
// Code to initialize everything here
};
LoginWorker.RunWorkerAsync(login);
// Put this in the click event handler for the Cancel button, if you have one
if ( LoginWorker != null )
LoginWorker.CancelAsync();
private void DoLogin(object sender, DoWorkEventArgs e) {
BackgroundWorker worker = (BackgroundWorker) sender;
LoginParameters login = (LoginParameters) e.Argument;
// Your logic to process the login goes here. It should periodically do the following to check to see if the user clicked the cancel button:
if ( worker.CancellationPending ) {
e.Cancel = true;
return;
}
// When you want to update the UI, do this:
worker.ReportProgress( percentComplete, objectWithOtherDataToWriteToTheUI );
// When you're done, just return.
}
private void ReportProgress(object sender, ProgressChangedEventArgs e) {
// Your code to extract the data you need to update the display from the arguments & to then update the display goes here. Remember, this runs on the UI thread
}
private void LoginFinished( object sender, RunWorkerCompletedEventArgs e ) {
if (e.Cancelled == true)
// Your code to inform the user of the cancellation here
else if (e.Error != null)
// All unhadgled exceptions throws by the DoWork event handler end up here
// Your code to inform the user of the error here
else {
// Your code to inform the user of the success goes here.
// Remember, this runs on the UI thread.
// I recommend you set the form BackgroundWorker property to null after its finished, as you can't reuse it after its finished.
LoginWorker = null;
}
}
Sorry this is in C# if you're looking for VB.NET, but it shouldn't be hard to translate.
To handle multiple windows I have written below code. Its not giving me any error, however no action is getting performed on new window. Can you please help me to fix this issue or suggest me any other way. Thanks!
Code:
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
FirefoxDriver dw2 = new FirefoxDriver();
dw2.get("http://quercus0638v.quercus.kpn.org:90");
//OPEN login and provide credentials
dw2.manage().window().maximize();
Thread.sleep(2000);
dw2.findElement(By.id("ContentPlaceHolder1_GebruikersnaamTextBox")).clear();
dw2.findElement(By.id("ContentPlaceHolder1_GebruikersnaamTextBox")).sendKeys("behdse");
dw2.findElement(By.id("ContentPlaceHolder1_WachtwoordTextBox")).clear();
dw2.findElement(By.id("ContentPlaceHolder1_WachtwoordTextBox")).sendKeys("fiet$hok");
//Login : Clcik on Login button
dw2.findElement(By.id("ContentPlaceHolder1_LoginButton")).click();
//Click on Select button. After that new window will open
dw2.findElement(By.id("ContentPlaceHolder1_CWDatumRadioButton")).click();
// Below code I written to get the window handles
Set<String> AllWindowHandles = dw2.getWindowHandles();
String window1 = (String) AllWindowHandles.toArray()[0];
System.out.print("window1 handle code = "+AllWindowHandles.toArray()[0]);
String window2 = (String) AllWindowHandles.toArray()[1];
System.out.print("\nwindow2 handle code = "+AllWindowHandles.toArray()[1]);
//Switch to window2(child window) and performing actions on it.
dw2.switchTo().window(window2);
//Click the user
dw2.findElement(By.id("AfdelingGebruikersListView_RowCheckBox_8")).click();
//Click on OK button after selecting User
dw2.findElement(By.id("AfdelingGebruikersListView_OKButton")).click();
//Switch to window1(child window) and performing actions on it.
dw2.switchTo().window(window1);
//Click the order type you want to retrieve
dw2.findElement(By.id("ContentPlaceHolder1_VerwerktRadioButton")).click();
//Click for exporting the data to Excel Sheet
dw2.findElement(By.id("ContentPlaceHolder1_ExporteerNaarExcelButton")).click();
}
U can switch to windows using:
for (String winHandle : objDriver.getWindowHandles()) {
objDriver.switchTo().window(winHandle);
}
This will switch to the last window opened. To get back to parent window by again using the above code. It would be better that u incorporate the code in a different method in order to reuse.
Hope this helps. Thanks.
Editing the Code as per the comment by OP :-
Since, as I suggested in comment, it might not be a new window. It must be a pop-up. So, please replace your code as below and try:
//Click on Select button. After that new window will open
dw2.findElement(By.id("ContentPlaceHolder1_CWDatumRadioButton")).click()
//Click the user
try{
WebDriverWait wait = new WebDriverWait(dw2,20);
WebElement ele = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("AfdelingGebruikersListView_RowCheckBox_8")));
ele.click();
}catch(Throwable e){
System.err.println("Error while clicking on the element. "+e.getMessage());
}
//Click on OK button after selecting User
dw2.findElement(By.id("AfdelingGebruikersListView_OKButton")).click();
Some context here...I have a System.Windows.Window that is used to display a modal message box. I created a Show() method that initializes the content of the window, and then calls ShowDialog(). The user clicks a button on this window, some information about the clicked button is set in the Tag property, and then the window is closed via Close().
As expected, I get a ShowDialog Exception when attempting to call ShowDialog() on the Window once is has been closed. Is there some way to reuse that same Window instance so that I don't have to new up an instance every time I need a message box?
For example...
MessageBoxWindow mbw = new MessageBoxWindow();
result = mbw.Show("caption", "message 1");
mbw.Show("caption", "message 2");
// The above throws an exception, so I have to do this...
mbw = new MessageBoxWindow();
result = mbw.Show("caption", "message 2");
Any help would be greatly appreciated!
Use .Hide() instead of .Close(). That removes it without destroying it. Then you can call Show() again when needed.
MainWindow test = new MainWindow();
test.Show();
test.Hide();
test.Show();
You can add a FormClosing event that cancels the form close and instead sets the Form.Visible to false. Then you would also need Show method that checks if this Form is null, so you would know whether you need to create a new Form or just show the one you already have.
For example:
private void FormMessageBox_FormClosing(object sender, FormClosingEventArgs e)
{
//This stops the form from being disposed
e.Cancel = true;
this.Visible = false;
}
public static void Show(FormMessageBox formMessageBox, string message)
{
//if formMessageBox is null we need to create a new one otherwise reuse.
if (formMessageBox == null)
{
formMessageBox = new FormMessageBox(message);
formMessageBox.ShowDialog();
}
else
{
formMessageBox.lblMessage.Text = message;
formMessageBox.Visible = true;
}
}