Selenium WebDriver for C# - Popup Dialog Boxes - c#

Is there any support for working with popup dialogs (specifically file downloads) in c#?

For a popup windows dialog, you can use the alert to catch:
IAlert alert = driver.SwitchTo().Alert();
alert.Accept();

No, there isn't - at least not natively.
WebDriver only interacts with the webpage. A popup dialog, once instantiated, becomes the domain of the operating system instead of the webpage.
You can circumvent the file download/upload dialog by issuing a POST or a GET with the content you are retrieving or sending to the server.
You can use tools such as AutoIt, or the Windows Automation API, to interact with other dialog windows.

From the WebDriver FAQ: WebDriver offers the ability to cope with multiple windows. This is done by using the "WebDriver.switchTo().window()" method to switch to a window with a known name. If the name is not known, you can use "WebDriver.getWindowHandles()" to obtain a list of known windows. You may pass the handle to "switchTo().window()".
Full FAQ here.
Example from Thoughtworks
String parentWindowHandle = browser.getWindowHandle(); // save the current window handle.
WebDriver popup = null;
Iterator<String> windowIterator = browser.getWindowHandles();
while(windowIterator.hasNext()) {
String windowHandle = windowIterator.next();
popup = browser.switchTo().window(windowHandle);
if (popup.getTitle().equals("Google") {
break;
}
}
Below is the example converted from Java into C# (with deprecated methods replaced)
String parentWindowHandle = _browser.CurrentWindowHandle; // save the current window handle.
IWebDriver popup = null;
var windowIterator = _browser.WindowHandles;
foreach (var windowHandle in windowIterator)
{
popup = _browser.SwitchTo().Window(windowHandle);
if (popup.Title == "Google")
{
break;
}
}

Related

C# IE11 Automation - Cannot Connect To Open IE Window

I'm trying to connect to an Internet Explorer window that is already open. Once connected I need to send some keystrokes (via SendKeys) to the IE window for some processing. I've got the following code below that works up until the SendKeys command. It finds the IE window titled "Graphics Database". When it hits "SendKeys.Send("{TAB}");" I get the error "An unhandled exception of type 'System.NullReferenceException' occurred".
Additional information: I also get the following on the NullReferenceException error. The weird thing is if I code to open a new IE window and then use SendKeys it works fine. Connecting to an existing windows seems to cause this issue.
SendKeys cannot run inside this application because the application is not handling Windows messages. Either change the application to handle messages, or use the SendKeys.SendWait method.
Can anyone please help me figure out what to do to fix this?
Andy
InternetExplorer IE = null;
// Get all browser objects
ShellWindows allBrowsers = new ShellWindows();
if (allBrowsers.Count == 0)
{
throw new Exception("Cannot find IE");
}
// Attach to IE program process
foreach (InternetExplorer browser in allBrowsers)
{
if (browser.LocationName == "Graphics Database")
{
MessageBox.Show ("Found IE browser '" + browser.LocationName + "'");
IE = (InternetExplorer)browser;
}
}
IE.Visible = true;
System.Threading.Thread.Sleep(2000);
SendKeys.Send("{TAB}");
SendKeys.Send("G1007");
SendKeys.Send("{ENTER}");
I was able to resolve this issue. I could never get the IE.Visible = true to work. This seemed to do nothing in my code. I had to use the SetForegroundWindow() to set the focus to the IE window.
// Find the IE window
int hWnd = FindWindow(null, "Graphics Database - Internet Explorer");
if (hWnd > 0) // The IE window was found.
{
// Bring the IE window to the front.
SetForegroundWindow(hWnd);
This site helped me immensely with getting the SetForegroundWindow() working.
http://forums.codeguru.com/showthread.php?460402-C-General-How-do-I-activate-an-external-Window
Andy please bear with me as this will be long. First you are going to want to look mshtml documentation and Dom. https://msdn.microsoft.com/en-us/library/aa741314(v=vs.85).aspx I don't know why automation is so convoluted but it is. The UIautomation class works great for windows apps but has nothing really for IE that I've been able to find. Others will point to third parties like waitn and selenium. Waitn appears to no longer be supported and selenium won't let you grab an open IE browser. I have gone down this path recently because I wanted to be able to create an app to store my web passwords and auto fill them in since I can't save my username and passwords in browser due to security restrictions. I have an example here and hope it helps. First open up IE and navigate to http://aavtrain.com/index.asp. Then have a console project with mshtml referenced and shdocvw. Here is code below. It gets the window then finds elements for username, password, and submit. then populates the username and password and clicks the submit button. I don't have a login to this site so it won't log you in. I have been using it for my testing. Problem I have is sites with javascript login forms. If you get further with this info please post back as I am still trying to evolve the concepts and create something reusable.
SHDocVw.ShellWindows shellWindows = new SHDocVw.ShellWindows();
Console.WriteLine("Starting Search\n\n\n");
foreach (SHDocVw.InternetExplorer ie in shellWindows)
{
if (ie.LocationURL.Contains("aavtrain"))
{
Console.WriteLine(ie.LocationURL);
Console.WriteLine("\n\n\n\n");
Console.WriteLine("FOUND!\n");
mshtml.HTMLDocument document = ie.Document;
mshtml.IHTMLElementCollection elCol = document.getElementsByName("user_name");
mshtml.IHTMLElementCollection elCol2 = document.getElementsByName("password");
mshtml.IHTMLElementCollection elCol3 = document.getElementsByName("Submit");
Console.WriteLine("AutofillPassword");
foreach (mshtml.IHTMLInputElement i in elCol)
{
i.defaultValue = "John";
}
foreach (mshtml.IHTMLInputElement i in elCol2)
{
i.defaultValue = "Password";
}
Console.WriteLine("Will Click Button in 2 seconds");
Thread.Sleep(2000);
foreach (mshtml.HTMLInputButtonElement i in elCol3)
{
i.click();
}
}
}
Console.WriteLine("Finished");

Choose a File from OpenFileDialog with C#

I have a little problem - I don't know how to Select a File and Open it in the Mozilla OpenFileDialog.
First, I open the Dialog by pressing "Browse" with Selenium and then I want to put in a File-Name (I know the exact location via Environment variable)
In my case: Environment.GetEnvironmentVariable("Testplatz_Config_Location") + "\TestConfig.fpc"
So my Question, does anyone know how to handle an already open OpenFileDialog using C# - Or is it perhaps possible to handle this with Selenium?
Selenium does not provide any native way to handle windows based pop ups. But we have some third party tools like AutoIT and RobotClass to handle those windows based pop ups. Refer those and give it a a try.
AutoIT with Selenium and Java
Selenium/SeleniumWebDriver does not provide any native way to handle windows based popups. Still, the best way is to miss this popup using
IWebElement element = driver.FindElement(By.Id("file_input"));
element.SendKeys(filePath);
but this is not allways is possible. And if it is not, you can use my lib:
https://github.com/ukushu/DialogCapabilities
by the following way:
OpenFileDialog:
// for English Windows
DialogsEn.OpenFileDialog(#"d:\test.txt");
//For windows with russian GUI
Dialogs.OpenFileDialog("Открыть", #"d:\test.txt");
MultiFile selection in OpenFileDialog:
var filePaths = new string[] {#"d:\test1.txt", #"d:\test2.txt", #"d:\test3.txt"};
//Or for Eng windows:
DialogsEn.OpenFileDialog(filePaths);
//for russian language OS
Dialogs.OpenFileDialog("Открыть", filePaths);
You can use sendKeys() on the file upload element to upload a file using selenium by path. I would suggest using this instead of AutoIT or Robot.
So instead of clicking on the browse button, you send the path directly to the file input element using sendKeys().
Example:
IWebElement element = driver.FindElement(By.Id("file_input"));
element.SendKeys(
Environment.GetEnvironmentVariable("Testplatz_Config_Location") + "\TestConfig.fpc");
i used selenium with Robot class from Java awt. This is my solution
public static void setClipboardData(String string) {
//StringSelection is a class that can be used for copy and paste operations.
StringSelection stringSelection = new StringSelection(string);
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(stringSelection, null);
}
public static void uploadFile(String fileLocation) {
try {
//Setting clipboard with file location
setClipboardData(fileLocation);
//native key strokes 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);
} catch (Exception exp) {
exp.printStackTrace();
}
}

disable IE visibility while using WatiN

I use watin, because I need to open some websites in the background for which the user needs to support Javascript. I don't know if WatiN is the best for this job, but at the moment it takes very long until Internet Explorer gets visible. I need to disable to popping up of Internet Explorer while using WatiN. User doesn't need to see the opening of sites. Is it possible while using WatiN to visit a website without showing it the user or should I use another alternative which supports JS on client side?
My code at the moment;
public static void visitURL()
{
IE iehandler = new IE("http://www.isjavascriptenabled.com");
if (iehandler.ContainsText("Yes"))
Console.WriteLine("js on");
else
Console.WriteLine("js off");
}
The WatIn.Core.IE class has a Visible property, you can initialize the object like that:
new WatiN.Core.IE() { Visible = true }
This way the IE will just blink on the screen when it's created, and then it will get hidden. You can later control the visibility of the IE with the ShowWindow method of WatiN.Core.IE class - I mean you can show it on the screen if you need, or you can hide again.
I use exactly that trick (of hiding IE) for writing UnitTests (using https://github.com/o2platform/FluentSharp_Fork.WatiN) that run in an hidden IE window
For example here is how I create a helper class (with an configurable hidden value)
public IE_TeamMentor(string webRoot, string path_XmlLibraries, Uri siteUri, bool startHidden)
{
this.ie = "Test_IE_TeamMentor".popupWindow(1000,700,startHidden).add_IE();
this.path_XmlLibraries = path_XmlLibraries;
this.webRoot = webRoot;
this.siteUri = siteUri;
}
which is then consumed by this test:
[Test] public void View_Markdown_Article__Edit__Save()
{
var article = tmProxy.editor_Assert() // assert the editor user (or the calls below will fail due to security demands)
.library_New_Article_New() // create new article
.assert_Not_Null();
var ieTeamMentor = this.new_IE_TeamMentor_Hidden();
var ie = ieTeamMentor.ie;
ieTeamMentor.login_Default_Admin_Account("/article/{0}".format(article.Metadata.Id)); // Login as admin and redirect to article page
var original_Content = ie.element("guidanceItem").innerText().assert_Not_Null(); // get reference to current content
ie.assert_Has_Link("Markdown Editor")
.link ("Markdown Editor").click(); // open markdown editor page
ie.wait_For_Element_InnerHtml("Content").assert_Not_Null()
.element ("Content").innerHtml()
.assert_Is(original_Content); // confirm content matches what was on the view page
var new_Content = "This is the new content of this article".add_5_RandomLetters(); // new 'test content'
ie.element("Content").to_Field().value(new_Content); // put new content in markdown editor
ie.button("Save").click(); // save
ie.wait_For_Element_InnerHtml("guidanceItem").assert_Not_Null()
.element ("guidanceItem").innerHtml()
.assert_Is("<P>{0}</P>".format(new_Content)); // confirm that 'test content' was saved ok (and was markdown transformed)
ieTeamMentor.close();
}
Here are a number of posts that might help you to understand how I use it:
https://github.com/TeamMentor/Dev/tree/master/Source_Code/TM_UnitTests/TeamMentor.UnitTests.QA/TeamMentor_QA_IE
http://blog.diniscruz.com/2014/07/how-to-debug-cassini-hosted-website-and.html
http://blog.diniscruz.com/2014/07/using-watin-and-embedded-cassini-to-run.html
http://blog.diniscruz.com/search/label/WatiN

How to handle multiple tabs in internet explorer with the IWebBrowserApp com interface?

I am using the following code (C#) based on the IWebBrowserApp com interface to find the Internet explorer window that matches the page I am trying to find, based on the title of the page.
I works fine if the page is on the first tab, but it does not work if its a later tab. So how do I get access to the tabs in internet explorer?
objSW = new ShellWindows();
IEnumerator ie = objSW.GetEnumerator();
while (ie.MoveNext())
{
obj = ie.Current;
app = (IWebBrowserApp)ie.Current;
System.Object docObj = app.Document;
HTMLDocumentClass hdoc = (HTMLDocumentClass)docObj;
if (hdoc.title.Contains(title)) matches.Add(app.HWND, app);
//do something
}
Sorry, but there's no supported API for tab enumeration/manipulation in IE9 or earlier.

Is it possible to open a PDF inside a c# application with Acrobat.dll?

I know that I can display a PDF file in my c# executable (not web app) with:
private AxAcroPDFLib.AxAcroPDF axAcroPDF1;
axAcroPDF1.LoadFile(#"somefile.pdf");
axAcroPDF1.Show();
But that is the regular pdf viewer like in the browser. I don't want that. I want full Adobe Standard or Professional functionality in my C# application using the Adobe controls. For example, if I use the code above, it loads in the C# app and I can see the adobe toolbar (print, save, etc.) But it is useless to me because I need things like save which cannot be done with the activex viewer above. Specifically, you cannot save, just as you cannot within the broswer.
So, I referenced the acrobat.dll and am trying to use:
Acrobat.AcroAVDocClass _acroDoc = new Acrobat.AcroAVDocClass();
Acrobat.AcroApp _myAdobe = new Acrobat.AcroApp();
Acrobat.AcroPDDoc _pdDoc = null;
_acroDoc.Open(myPath, "test");
pdDoc = (Acrobat.AcroPDDoc)(_acroDoc.GetPDDoc());
_acroDoc.SetViewMode(2);
_myAdobe.Show();
It opens adobe acrobat but it opens it outside of my c# application. I need it to open in my c# application like the activex library does. Can it be done with these libraries?
If I cannot open it in my c# application I would like to be able to "hold" my c# app tied to it so the c# app knows when I close the adobe app. At least that way I'd have some measure of control. This means I would hit open, the adobe app opens. I close the adobe app, my C# app is aware of this and loads the newly changed doc with the activex library (because I don't need change ability anymore, just displaying.)
I have the full versions of adobe acrobat installed on my computer. It is not the reader.
Thank you for any help.
edit:
There is an example in vb in the adobe acrobat sdk. I believe it is called activeview.
you can check out ABCpdf. I dont know if it has this capability but we have used it for several of our apps
Using a webbrowser control would be an option to display the content.
IText# may help you out.
You can create PDF's and I believe you can use it to read and modify them.
As for displaying in the app..... I am not sure how to display them with iText or if it is possible (have not tried this yet), sorry. iText does let you convert to RTF which may be one approach.
Best option is to write a listener which tells your calling code when Adobe.exe is no longer running. Something like the following (with tweaks for your uses) should work:
public void Open(string myPath)
{
Acrobat.AcroAVDocClass _acroDoc = new Acrobat.AcroAVDocClass();
Acrobat.AcroApp _myAdobe = new Acrobat.AcroApp();
Acrobat.AcroPDDoc _pdDoc = null;
_acroDoc.Open(myPath, "test");
_pdDoc = (Acrobat.AcroPDDoc) (_acroDoc.GetPDDoc());
_acroDoc.SetViewMode(2);
_myAdobe.Show();
NotifyAdobeClosed += new EventHandler(Monitor_NotifyAdobeClosed);
MonitorAdobe();
}
private void Monitor_NotifyAdobeClosed(object sender, EventArgs e)
{
NotifyAdobeClosed -= Monitor_NotifyAdobeClosed;
//Do whatever it is you want to do when adobe is closed.
}
private void MonitorAdobe()
{
while(true)
{
var adcount = (from p in Process.GetProcesses()
where p.ProcessName.ToLower() == "acrobat"
select p).Count();
if (adcount == 0)
{
OnNotifyAdobeClosed();
break;
}
}
}
public event EventHandler NotifyAdobeClosed;
public void OnNotifyAdobeClosed()
{
if (NotifyAdobeClosed != null)
NotifyAdobeClosed(this, null);
}

Categories