Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test file download with Watin / IE9?

I'm trying to test file download with Watin 2.1.0 against IE9. I used the suggested code from the accepted answer to the question Downloading a file with Watin in IE9, like this:

var downloadHandler = new FileDownloadHandler(fname);
WebBrowser.Current.AddDialogHandler(downloadHandler);
link.ClickNoWait();
downloadHandler.WaitUntilFileDownloadDialogIsHandled(15);
downloadHandler.WaitUntilDownloadCompleted(200);

However, the downloadHandler.WaitUntilFileDownloadDialogIsHandled(15) call times out. What should I do?

like image 213
aknuds1 Avatar asked Sep 21 '11 13:09

aknuds1


2 Answers

File download dialog doesn't work in IE9 (Windows7) NetFramework 4.0.

Following code snippet might help you resolve the issue:

First you must add references UIAutomationClient and UIAutomationTypes to your test project.

After In Ie9 Tools -> View Downloads -> Options define path to your save folder.

The next method extends Browser class

public static void DownloadIEFile(this Browser browser)
{
    // see information here (http://msdn.microsoft.com/en-us/library/windows/desktop/ms633515(v=vs.85).aspx)
    Window windowMain = new Window(WatiN.Core.Native.Windows.NativeMethods.GetWindow(browser.hWnd, 5));
   System.Windows.Automation.TreeWalker trw = new  System.Windows.Automation.TreeWalker(System.Windows.Automation.Condition.TrueCondition);
   System.Windows.Automation.AutomationElement mainWindow = trw.GetParent(System.Windows.Automation.AutomationElement.FromHandle(browser.hWnd));

    Window windowDialog = new Window(WatiN.Core.Native.Windows.NativeMethods.GetWindow(windowMain.Hwnd, 5));
    // if doesn't work try to increase sleep interval or write your own waitUntill method
    Thread.Sleep(1000);
    windowDialog.SetActivate();
    System.Windows.Automation.AutomationElementCollection amc = System.Windows.Automation.AutomationElement.FromHandle(windowDialog.Hwnd).FindAll(System.Windows.Automation.TreeScope.Children, System.Windows.Automation.Condition.TrueCondition);

    foreach (System.Windows.Automation.AutomationElement element in amc)
    {
        // You can use "Save ", "Open", ''Cancel', or "Close" to find necessary button Or write your own enum
        if (element.Current.Name.Equals("Save"))
        {
            // if doesn't work try to increase sleep interval or write your own waitUntil method
            // WaitUntilButtonExsist(element,100);
            Thread.Sleep(1000);
            System.Windows.Automation.AutomationPattern[] pats = element.GetSupportedPatterns();
            // replace this foreach if you need 'Save as' with code bellow
            foreach (System.Windows.Automation.AutomationPattern pat in pats)
            {
                // '10000' button click event id 
                if (pat.Id == 10000)
                {
                    System.Windows.Automation.InvokePattern click = (System.Windows.Automation.InvokePattern)element.GetCurrentPattern(pat);
                    click.Invoke();
                }
            }
        }
    }
}

if you want click 'Save As' replace foreach code with this

System.Windows.Automation.AutomationElementCollection bmc =  element.FindAll(System.Windows.Automation.TreeScope.Children,   System.Windows.Automation.Automation.ControlViewCondition);
System.Windows.Automation.InvokePattern click1 =  (System.Windows.Automation.InvokePattern)bmc[0].GetCurrentPattern(System.Windows.Automation.AutomationPattern.LookupById(10000));
click1.Invoke();
Thread.Sleep(10000);

System.Windows.Automation.AutomationElementCollection main =  mainWindow.FindAll(System.Windows.Automation.TreeScope.Children
,System.Windows.Automation.Condition.TrueCondition);
foreach (System.Windows.Automation.AutomationElement el in main)
{
    if (el.Current.LocalizedControlType == "menu")
    {
        // first array element 'Save', second array element 'Save as', third second array element    'Save and open'
        System.Windows.Automation.InvokePattern clickMenu = (System.Windows.Automation.InvokePattern)
                    el.FindAll(System.Windows.Automation.TreeScope.Children,        System.Windows.Automation.Condition.TrueCondition)  [1].GetCurrentPattern(System.Windows.Automation.AutomationPattern.LookupById(10000));
                       clickMenu.Invoke();
        //add ControlSaveDialog(mainWindow, filename) here if needed
        break;

    }
}

Edit: Also if you need to automate the save as dialog specifying a path and clicking save you can do it by adding this code just before break;

private static void ControlSaveDialog(System.Windows.Automation.AutomationElement mainWindow, string path)
{
    //obtain the save as dialog
    var saveAsDialog = mainWindow
                        .FindFirst(TreeScope.Descendants,
                                   new PropertyCondition(AutomationElement.NameProperty, "Save As"));
    //get the file name box
    var saveAsText = saveAsDialog
            .FindFirst(TreeScope.Descendants,
                       new AndCondition(
                           new PropertyCondition(AutomationElement.NameProperty, "File name:"),
                           new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit)))
            .GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
    //fill the filename box 
    saveAsText.SetValue(path);

    Thread.Sleep(1000);
    //find the save button
    var saveButton =
            saveAsDialog.FindFirst(TreeScope.Descendants,
            new AndCondition(
                new PropertyCondition(AutomationElement.NameProperty, "Save"),
                new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button)));
    //invoke the button
    var pattern = saveButton.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
    pattern.Invoke();
}
like image 163
Boriss Pavlovs Avatar answered Oct 31 '22 21:10

Boriss Pavlovs


IE9 no longer uses a dialog window for saving files. Instead, it uses the notification bar to prevent focus from being removed from the web site. See http://msdn.microsoft.com/en-us/ie/ff959805.aspx under "Download Manager" for reference.

Unfortunately, this means that the current FileDownloadHandler in WatiN will not work. It instantiates a "DialogWatcher" class per browser instance that is a basic message pump for any kind of child window. When child windows are encountered, the DialogWatcher checks to see if the window is specifically a dialog (which the notification bar is not). If it is a dialog, it then iterates over the registered IDialogHandler instances calling "CanHandleDialog." Even if the notification bar were a dialog, it is of a different Window Style (http://msdn.microsoft.com/en-us/library/windows/desktop/ms632600(v=vs.85).aspx), which is how WatiN detects the type of dialog.

From what I can see, there is no support yet for detecting the IE 9 notification bar and its prompts in WatiN. Until that support is added, you will not be able to automate downloading files in IE9.

like image 31
Joe Bako Avatar answered Oct 31 '22 20:10

Joe Bako