从网站下载PDF时如何在另存为对话框中按OK

从网站下载PDF时如何在另存为对话框中按OK,pdf,webdriver,Pdf,Webdriver,我在C#中使用Selenium WebDriver,到目前为止已经完成了以下步骤; 转到网页,打开PDF,按下载按钮 { [TestFixture] public class DownloadPDF { private static IWebDriver driver = null; private StringBuilder verificationErrors = null; private string baseURL; [TestFixtureSetUp

我在C#中使用Selenium WebDriver,到目前为止已经完成了以下步骤; 转到网页,打开PDF,按下载按钮

{
[TestFixture]
public class DownloadPDF
{
    private static IWebDriver driver = null;
    private StringBuilder verificationErrors = null;
    private string baseURL;

    [TestFixtureSetUp]
    public void TestSetup()
    {
        driver = new FirefoxDriver();          
        baseURL = ("http://pdfobject.com/");
        driver.Manage().Timeouts().ImplicitlyWait(new TimeSpan(5000));

    }
    [Test]
    public void main()
    {
        driver.Navigate().GoToUrl(baseURL + "/pdf/pdfobject.pdf#view=FitH&pagemode=thumbs&search=pdfobject&toolbar=0&statusbar=0&messages=0&navpanes=1");
        driver.FindElement(By.Id("download")).Click();
    }

}
}
我现在得到一个保存对话框,它有两个单选按钮(打开和保存文件)和一个复选框(以后自动执行此操作)

默认选中的选项是“保存文件”,因此我想选中“从现在起自动执行此操作”,然后按“确定”

我看过一些Java示例,说明了如何实现这一点,但到目前为止,我在C#中没有发现任何东西


理想情况下,如果可能的话,我想直接下载到我机器上的文件位置?

假设您提到的保存对话框不是网页DOM的一部分,Selenium将无法完成很多工作

您可以使用来处理这些情况。它是免费的,重量轻,可以处理基本的窗口和控制。通过添加对Interop.AutoItX3Lib.dll的引用,在C#项目中使用它

以下是我处理AutoIt API的包装器类:

namespace QA.AutoIt
{
    using System;
    using AutoItX3Lib;

    public class AutoItWindow
    {
        public static AutoItX3 AutoItDriver;
        public string Title;
        public string Text;

        public AutoItWindow(string windowTitle, string windowText = "")
        {
            AutoItDriver = new AutoItX3();;
            Title = windowTitle;
            Text = windowText;
        }

        public void Activate()
        {
            AutoItDriver.WinActivate(Title, Text);
        }
    }

    public class AutoItElement
    {
        private static AutoItX3 _au3;
        private AutoItWindow _parent;
        private string _controlID;

        public AutoItElement(AutoItWindow parentWindow, string controlID)
        {
            _au3 = AutoItWindow.AutoItDriver;
            _parent = parentWindow;
            _controlID = controlID;
        }

        public void Click(string button = "LEFT")
        {
            // Set the window active
            _parent.Activate();

            // Click on the control
            _au3.ControlClick(_parent.Title, _parent.Text, _controlID, button);
        }

        public void SendText(string textToSend)
        {
            // Set the window active
            _parent.Activate();

            // Send the specified text to the control
            _au3.ControlFocus(_parent.Title, _parent.Text, _controlID);
            _au3.ControlSend(_parent.Title, _parent.Text, _controlID, textToSend);
        }
    }
}
下面是一个上载文件的示例。类似于你想要达到的目标。我定义了一个类,该类使用OpenFile方法对对话框UI进行建模,以执行所需的操作。使用AutoIt object spy工具可以轻松获取标识窗口及其子控件的字符串

public class FileOpenWindow : AutoItWindow
{
    #region Child Controls
    public AutoItElement FileNameEdit;
    public AutoItElement OKButton;
    #endregion

    public FileOpenWindow(string title = "Open", string text = "")
        : base(title, text)
    {
        FileNameEdit = new AutoItElement(this, "[CLASS:Edit; INSTANCE:1]");
        OKButton = new AutoItElement(this, "[CLASS:Button; INSTANCE:1]");
    }

    public void OpenFile(string fileName)
    {
        // Wait for the window to appear then activate it
        WaitToAppear(30);
        Activate();

        // Enter in the filename and click OK to start upload
        FileNameEdit.SendText(fileName);
        OKButton.Click();

        // Wait for the window to disappear
        WaitToDisappear(30);
    }
}
在我的工作中,我通常使用库与桌面应用程序进行交互。此外,您还可以使用一些专门为此目的开发的框架(例如White)。但对我来说,使用winapi、uiautomation编写自己的应用程序更容易。您可以包装您的对话框并公开它的元素,以便从测试中可以轻松地在任何地方使用它。下面是此类代码的示例:

[TestFixture]
public class DownloadPDF
{
    private static IWebDriver driver = null;
    private StringBuilder verificationErrors = null;
    private string baseURL;

    [TestFixtureSetUp]
    public void TestSetup()
    {
        driver = new FirefoxDriver();          
        baseURL = ("http://pdfobject.com/");
        driver.Manage().Timeouts().ImplicitlyWait(new TimeSpan(5000));

    }
    [Test]
    public void main()
    {
        driver.Navigate().GoToUrl(baseURL + "/pdf/pdfobject.pdf#view=FitH&pagemode=thumbs&search=pdfobject&toolbar=0&statusbar=0&messages=0&navpanes=1");
        driver.FindElement(By.Id("download")).Click();
        var window = new Window("your window name");
        window.OpenWithBtn.Click();
        window.Save.Click();
    }

}

public class Window
    {
        private readonly string _windowName;
        private AutomationElement _window;

        public Window(string windowName)
        {
            _windowName = windowName;
            _window = GetWindow(_windowName);
        }

        private AutomationElement GetWindow(string windowName)
        {
            return UIAutomationElements.FindDescedantByCondition(AutomationElement.RootElement,
                new PropertyCondition(AutomationElement.NameProperty, windowName));
        }

        private AutomationElement GetElement(string elementName)
        {
            if (_window == null)
                _window = GetWindow(_windowName);
            return UIAutomationElements.FindDescedantByCondition(_window,
                new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.RadioButton),
                    new PropertyCondition(AutomationElement.NameProperty, elementName)));
        }

        public Button OpenWithBtn
        {
            get
            {
                return new Button(GetElement("Open With..."));
            }
        }

        public Button Save
        {
            get
            {
                return new Button(GetElement("Open With..."));
            }
        }
    }

    public class Button
    {
        private readonly AutomationElement _btnElement;

        public Button(AutomationElement btnElement)
        {
            _btnElement = btnElement;
        }

        public void Click()
        {
            //perform click using winapi or invoke button if 'InvokePattern' available for it
            var invokePattern = _btnElement.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern; 
            invokePattern.Invoke();
        }
    }

public class UIAutomationElements
{
    /// <summary>
    /// Find descedant of specified element by it's index.
    /// </summary>
    /// <param name="element">Main element in which search should be performed.</param>
    /// <param name="condition">Condition by wchich element will be identified. See <see cref="Condition"/>, <see cref="PropertyCondition"/> etc...</param>
    /// <param name="itemIndex">Index of element which should found</param>
    /// <returns>Founded element as <see cref="AutomationElement"/> with specified index</returns>
    public static AutomationElement FindDescedantByCondition(AutomationElement element, Condition condition, int itemIndex)
    {
        var result = element.FindAll(TreeScope.Descendants, condition);

        return result[itemIndex];
    }

    /// <summary>
    /// Find all descedants in the main element.
    /// </summary>
    /// <param name="element">Main element in whick search should be performed.</param>
    /// <param name="condition">Condition by wchich element will be identified. See <see cref="Condition"/>, <see cref="PropertyCondition"/> etc...</param>
    /// <returns><see cref="AutomationElementCollection"/></returns>
    public static AutomationElementCollection FindDescedantsByCondition(AutomationElement element, Condition condition)
    {
        var result = element.FindAll(TreeScope.Descendants, condition);
        return result;
    }

    /// <summary>
    /// Find descedant by specified condition
    /// </summary>
    /// <param name="element">Main element in which search should be performed.</param>
    /// <param name="condition">Condition by wchich element will be identified.
    ///  See <see cref="Condition"/>, <see cref="PropertyCondition"/> etc...</param>
    /// <returns>Element as <see cref="AutomationElement"/></returns>
    public static AutomationElement FindDescedantByCondition(AutomationElement element, Condition condition)
    {
        var result = element.FindFirst(TreeScope.Descendants, condition);

        return result;
    }
}
[TestFixture]
公共类下载PDF
{
私有静态IWebDriver驱动程序=null;
私有StringBuilder verificationErrors=null;
私有字符串baseURL;
[TestFixtureSetUp]
公共void TestSetup()
{
驱动程序=新的FirefoxDriver();
baseURL=(“http://pdfobject.com/");
driver.Manage().Timeouts().ImplicitlyWait(新的时间跨度(5000));
}
[测试]
公共图书馆
{
driver.Navigate().gotour(baseURL+“/pdf/pdfobject.pdf#view=FitH&pagemode=thumbs&search=pdfobject&toolbar=0&statusbar=0&messages=0&navpanes=1”);
driver.FindElement(By.Id(“下载”))。单击();
var窗口=新窗口(“您的窗口名称”);
window.OpenWithBtn.Click();
window.Save.Click();
}
}
公共类窗口
{
私有只读字符串\u windowName;
专用AutomationElement _窗口;
公共窗口(字符串windowName)
{
_windowName=windowName;
_window=GetWindow(_windowName);
}
私有AutomationElement GetWindow(字符串windowName)
{
返回UIAutomationElements.FindDescedDantByCondition(AutomationElement.RootElement,
新属性条件(AutomationElement.NameProperty,windowName));
}
私有AutomationElement GetElement(字符串elementName)
{
如果(_window==null)
_window=GetWindow(_windowName);
返回UIAutomationElements.FindDescedDantByCondition(\u窗口,
新和条件(新属性条件(AutomationElement.ControlTypeProperty、ControlType.RadioButton),
新属性条件(AutomationElement.NameProperty,elementName));
}
使用BTN打开公共按钮
{
收到
{
返回新按钮(GetElement(“打开…”);
}
}
公共按钮保存
{
收到
{
返回新按钮(GetElement(“打开…”);
}
}
}
公共类按钮
{
私有只读AutomationElement _btneElement;
公共按钮(AutomationElement btnElement)
{
_btnElement=btnElement;
}
公共作废点击()
{
//如果“InvokePattern”可用,请使用winapi或invoke按钮执行单击
var invokePattern=_btneElement.GetCurrentPattern(invokePattern.Pattern)作为invokePattern;
invokePattern.Invoke();
}
}
公共类自动化元件
{
/// 
///通过指定元素的索引查找该元素的descendant。
/// 
///应在其中执行搜索的主要元素。
///将识别该元素的条件。请参阅等。。。
///应找到的元素的索引
///按指定索引创建元素
公共静态AutomationElement FindDescedDantByCondition(AutomationElement元素、Condition条件、int itemIndex)
{
var result=element.FindAll(TreeScope.subjects,条件);
返回结果[itemIndex];
}
/// 
///查找主元素中的所有描述。
/// 
///应在其中执行搜索的主要元素。
///将识别该元素的条件。请参阅等。。。
/// 
公共静态AutomationElementCollection FindDescedantsByCondition(AutomationElement元素、条件)
{
var result=element.FindAll(TreeScope.subjects,条件);
返回结果;
}
/// 
///按指定条件查找descedant
/// 
///应在其中执行搜索的主要元素。
///将识别该元素的条件。
///看,等等。。。
///元素作为
公共静态AutomationElement FindDescedDantByCondition(AutomationElement元素,Condition条件)
{
var result=element.FindFirst(TreeScope.subjects,条件);
返回结果;
}
}
要执行单击,可以在winapi方法上使用。所描述的一些解决方案。希望这会有所帮助

另外,如果你只需要点击OK按钮,你不需要包装任何东西。只需找到对话框中的按钮并执行click=)

嗨,Andrey,我可以