I am automating a file upload with C# and selenium (running Google Chrome), but I don't want to type the file path on the file input, I would like to emulate how a real user would do it (Typing the path in the file dialog box). Using the SendKeys.SendWait() method is the perfect solution for this, however I am encountering a problem.
I have the following code.
var e = driverWait.Until(driver => driver.FindElement(By.Id("file-button")));
e.Click();
SendKeys.SendWait(#"C:\Users\seawolf\Downloads\Result.pdf");
The problem is before the open file dialog pops up, SendWait begins typing on the keyboard, so the path is typed on the Webpage and not the dialog box.
Is there a way until an open file dialog pops up with C#? It doesn't have to be built into selenium as it's easy to integrate everything with driverWait. What I want to do is something like:
driverWait.Until(_ => DialogIsOpen() );
Thanks to #Jimi, here is my solution.
var chromeElement = AutomationElement.RootElement.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "Chrome_WidgetWin_1"));
var openDialogClassName = "#32770";
Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent, chromeElement, TreeScope.Subtree, (sender, _) =>
{
var element = sender as AutomationElement;
Console.WriteLine("running");
if (element.Current.ClassName.Equals(openDialogClassName))
{
SendKeys.SendWait(#"C:\Users\seawolf\Downloads\Result.pdf");
}
});
This is what I use. I just put a wait to allow for the window to appear before using sendwait. A majority of times, you will switch focus to the upload window once it appears.
//Click browse btn to open upload window
driver.FindElement(By.ClassName("uploadbtn")).Click();
//Wait for Upload Window to appear(may not be necessary in some cases)
Thread.Sleep(2000);
//Send the path and then click the Right arrow key
SendKeys.SendWait(GetProjectRoot() + #"\DataFiles\red.png" + #"{RIGHT}");
//Click Enter Key to submit
SendKeys.SendWait(#"{Enter}");
Related
I have searched StackOverflow and could not find the correct solution for the following problem:
In an internal Sharepoint site, after clicking Upload, and then Folders, I use SendKeys.SendWait to input the directory location,. And then after sending "Enter" as Send.Keys.SendWait, a dialogue box appears, where I need to click the Upload button, but this element is not searchable, as it seems to be not part of the DOM.
Here is the code snippet:
SendKeys.SendWait(#"C:\Automation\Testing\");
SendKeys.SendWait("{Enter}");
SendKeys.SendWait("{Enter}");
IAlert alert = Driver.driver.SwitchTo().Alert();
alert.Accept();
I have also tried to use JavaScript to handle this but it didn't help:
IJavaScriptExecutor jsX = (IJavaScriptExecutor)driver;
jsX.ExecuteScript("Object.defineProperty(BeforeUnloadEvent.prototype,
'returnValue', { get:function(){}, set:function(){} });");
In another thread I noticed a suggestion to add "--disable-notifications" and "--disable-popup-blocking", but that didn't work either.
Here is the code:
ChromeOptions options = new ChromeOptions();
options.AddArguments("disable-infobars", "start-maximized", "no-sandbox", "--disable-notifications", "--disable-popup-blocking");
Driver.driver = new ChromeDriver(options);
What is the best way to find and click the "Upload" in the dialogue box?
You may try to use InputSimulator Nuget for simulating keyboard buttons events. On the screenshot Cancel button is selected, pressing Tab key might change the focus to Upload button, then Enter key may press Upload button:
var sim = new WindowsInput.InputSimulator();
System.Threading.Thread.Sleep(3000);
sim.Keyboard.KeyPress(WindowsInput.Native.VirtualKeyCode.TAB);
System.Threading.Thread.Sleep(300);
sim.Keyboard.KeyPress(WindowsInput.Native.VirtualKeyCode.RETURN);
I'm developing a WPF Application. Right now I'm trying to do something like this:
//Print the information about what happened, and open toolbar.
MessageBox.Show("Cannot find the destination file, The application will now open Google Chrome." + Environment.NewLine
+ "Please fill in the information and when you finish close Google Chrome.");
//open Attributes Toolbar
new AttributesToolbar(application.Attributes).Show();
//start google chrome and wait for the user to close it
Process.Start(startInfo).WaitForExit();
var success = (MessageBox.Show("Did you succeed?", "Status check", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes);
return new RPAResult()
{
Succeeded = success
};
These are the steps:
1) After the application could not found a configuration file, it prints a message that the user has to fill in some details himself (That's the background story, not so important).
2) The application opens a toolbar window - that's a WPF Window with some details that the user has to copy and paste from it to the chrome page.
3) The application opens google chrome and waits until the user closed it
The problem is when the "WaitForExit()" command is executed, the entire application is freezed, even the new WPF Window that has just been opened and the user cannot copy and paste anything.
I have tried to open a new thread but it causes a STAThread problem.
Any help please?
You could try to start your process in a task and then continue on exit with your message box.
Task.Factory.StartNew(() =>
{
Process.Start(startInfo).WaitForExit();
}).ContinueWith(prevTask =>
{
var success = (MessageBox.Show("Did you succeed?", "Status check", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes);
[...]
});
I'm developing a WPF application that's meant to live in the tool tray, so it doesn't involve any windows. Right-clicking the tool tray icon brings up a menu with a Configure Report Path... option, and I'd like to display a folder browser dialog to the user when this is clicked:
What I'm finding is that when the option is selected, a dialog opens and immediately closes unless I assign some window to Application.Current.MainWindow and show it before opening the dialog. This is the code I'm using:
public CounterIconViewModel(IMessenger messenger)
{
void ConfigureReportPath()
{
// Application window must be created and displayed.
Application.Current.MainWindow = new Window();
Application.Current.MainWindow.Show();
var browseDialog = new VistaFolderBrowserDialog { ShowNewFolderButton = false };
if (browseDialog.ShowDialog() != true)
{
return;
}
// (Separate issue) Command doesn't execute unless I comment out the line below.
//messenger.Send(browseDialog.SelectedPath, "ReportPath");
}
ConfigureReportPathCommand = new RelayCommand(ConfigureReportPath);
ExitApplicationCommand = new RelayCommand(Application.Current.Shutdown);
}
In this case I'm using VistaFolderBrowserDialog from Ookii.Dialogs.Wpf, but I've tried the same thing with another WPF browser dialog and notice identical behaviour.
Is there a reason why a browser dialog seems to require a window to be displayed to remain open, and any workarounds?
Update
I've found that if I initialize and pass an instance of Window to browseDialog.ShowDialog, the dialog remains open without me having to assign the main application window and display it:
if (browseDialog.ShowDialog(new Window()) != true)
I don't understand why this works. I'll post this as an answer if no others appear so that at least people in a similar situation are aware of this workaround.
Update 2
The other dialog I tested it with was CommonOpenFileDialog from Microsoft.WindowsApiCodePack-Shell:
var browseDialog = new CommonOpenFileDialog { IsFolderPicker = true };
browseDialog.ShowDialog();
My tool tray icon displays a rich tool-tip (a custom UserControl) if I hover over it, and with this browser dialog I found that:
If I hover over the icon to make the tool-tip display, then the browser dialog works fine when I try to open it on the first and every subsequent attempt.
If I try to open the browser dialog before displaying the tool-tip display, the browser dialog opens and closes immediately on the first try, but then remains open on every subsequent attempt.
This dialog also accepts a Window instance in ShowDialog but it makes no difference if I pass one or not.
My workaround (initializing and passing a blank window to the Ookli dialog browser) seems to work fine regardless of whether I first bring up the tool-tip, so I'm sticking with that for the time being.
Based on this post, I managed to open a new tab, but when I try to navigate in the new tab, the navigation occurs in the old tab.
I saw that I should use this:
driver.switchTo().window(windowName);
but what is windowName?
You have to use window handle function here. You asked for a solution in c#. I used java with selenium webdriver. They both would use similar concepts.
Here is a sample working code in java:
String parentHandle = driver.getWindowHandle(); // get the current window handle
System.out.println(parentHandle); //Prints the parent window handle
String anchorURL = anchor.getAttribute("href"); //Assuming u are clicking on a link which opens a new browser window
anchor.click(); //Clicking on this window
for (String winHandle : driver.getWindowHandles()) { //Gets the new window handle
System.out.println(winHandle);
driver.switchTo().window(winHandle); // switch focus of WebDriver to the next found window handle (that's your newly opened window)
}
//Now your driver works on the current new handle
//Do some work here.....
//Time to go back to parent window
driver.close(); // close newly opened window when done with it
driver.switchTo().window(parentHandle); // switch back to the original window
Hope this helps!
I've run into an issue with the Microsoft.Win32.SaveFileDialog in our Wpf application.
If the user enters an enormous file path, above the allowed maximum (I think its 255 chars?), within the SaveFileDialog then it starts to become unusable (details of this are in the code example).
So as a work-around I want to close the dialogue and make them enter the file path again. However the problem is that the SaveFileDialog does not have a Close() routine or anything else that I can see to close it. How can I close the dialogue programmatically?
// error only seems to occur if a filter is specified.
var dialog = new Microsoft.Win32.SaveFileDialog
{
Filter = "My juicy file (*.mjf) | *.mjf"
};
try
{
dialog.ShowDialog();
}
catch (System.IO.PathTooLongException error) // handle
{
/*
* if I handle this exception (by displaying a message to the user)
* the dialog will remain open, but if the user attempts to use it
* and enter another filename a mixture of the following exceptions
* are raised:
*
* AccessViolationException
* FatalExecutionEngineError
* ExecutionEngineException
*/
MessageBox.Show(error.Message);
}
EDIT
Thanks for you answers/comments. I've just tested this on my Windows 7 box and it behaves as expected so this maybe an issue only on XP.
In WPF 4.0 on Windows 7 the SaveFileDialog is showing its own error dialog:
<long path?
The path is too long.
Try a shorter name.
with an OK button to dismiss the error dialog. That leads the user back to the original SaveFileDialog where they can change their value or Cancel.
For earlier versions where the behavior might be different, you can use the Windows UI Automation framework to programmatically click the 'Cancel' button on the SaveFileDialog.
if (dialog != null)
{
dialog.DialogResult = DialogResult.Cancel;
}
Try setting the dialog result to close the dialog.
Send the window a WM_SYSCOMMAND message with a wParam parameter of SC_CLOSE. This is the equivalent of clicking on the Close button in the upper-right corner of the dialog.