如何使用文件路径使用ChromeDriver导航到本地文件?

时间:2017-02-02 17:26:16

标签: c# .net automated-tests selenium-chromedriver protractor-net

我正在为自动化框架构建一组测试,但遇到导航到我创建的本地HTML页面的问题。

以下是我创建ChromeDriver实例的地方。

if (AllowFileAccessAcrossFiles)
{
   ChromeOptions options = new ChromeOptions();
   // Have tried, none, individually, as well as both.
   options.AddArgument("--allow-file-access-from-files");
   options.AddArgument("--enable-local-file-accesses ");
   driver = new ChromeDriver(options);
}

ChromeDriver实例稍后会传递到NgWebDriver类,以便我可以在测试中使用Protractor-net并抽象测试工具。

internal TestWebDriver(RemoteWebDriver driver, TestConfiguration configuration)
{
    // ...

    _driver = new NgWebDriver(driver);

    // ...
}

当框架调用驱动程序导航到页面时,它会传递正确的文件路径(" file:/// ..."),但它永远不会进入浏览器URL和没有导航到。 (即网址为data;

如何使用ChromeDriver的文件路径导航到本地HTML页面?

1 个答案:

答案 0 :(得分:2)

事实证明,此问题的解决方案植根于NgWebDriver。 NgWebDriver推迟IE,Edge,PhantomJS,Firefox和Safari的驱动程序导航到URL,但如果它是其他任何东西,那么它只运行它:this.ExecuteScript("window.name += '" + AngularDeferBootstrap + "'; window.location.href = '" + value + "';");

正在调用的JavaScript method不处理只传入本地路径,它需要一个http(s)字符串来导航。因此,我们是否可以传入本地路径取决于特定驱动程序对Url属性的set方法的实现。

以下是相关的Protractor-net属性。

public class NgWebDriver : IWebDriver, IWrapsDriver, IJavaScriptExecutor
{
    private const string AngularDeferBootstrap = "NG_DEFER_BOOTSTRAP!";

    private IWebDriver driver;
    private IJavaScriptExecutor jsExecutor;
    private string rootElement;
    private IList<NgModule> mockModules;

    // constructors and stuff

    /// <summary>
    /// Gets or sets the URL the browser is currently displaying.
    /// </summary>
    public string Url
    {
        get
        {
            this.WaitForAngular();
            return this.driver.Url;
        }
        set
        {
            // Reset URL
            this.driver.Url = "about:blank";

            // TODO: test Android
            IHasCapabilities hcDriver = this.driver as IHasCapabilities;
            if (hcDriver != null &&
                (hcDriver.Capabilities.BrowserName == "internet explorer" ||
                 hcDriver.Capabilities.BrowserName == "MicrosoftEdge" ||
                 hcDriver.Capabilities.BrowserName == "phantomjs" ||
                 hcDriver.Capabilities.BrowserName == "firefox" ||
                 hcDriver.Capabilities.BrowserName.ToLower() == "safari"))
            {
                this.ExecuteScript("window.name += '" + AngularDeferBootstrap + "';");
                this.driver.Url = value;
            }
            else
            {
                this.ExecuteScript("window.name += '" + AngularDeferBootstrap + "'; window.location.href = '" + value + "';");
            }

            if (!this.IgnoreSynchronization)
            {
                try
                {
                    // Make sure the page is an Angular page.
                    long? angularVersion = this.ExecuteAsyncScript(ClientSideScripts.TestForAngular) as long?;
                    if (angularVersion.HasValue)
                    {
                        if (angularVersion.Value == 1)
                        {
                            // At this point, Angular will pause for us, until angular.resumeBootstrap is called.

                            // Add default module for Angular v1
                            this.mockModules.Add(new Ng1BaseModule());

                            // Register extra modules
                            foreach (NgModule ngModule in this.mockModules)
                            {
                                this.ExecuteScript(ngModule.Script);
                            }
                            // Resume Angular bootstrap
                            this.ExecuteScript(ClientSideScripts.ResumeAngularBootstrap,
                                String.Join(",", this.mockModules.Select(m => m.Name).ToArray()));
                        }
                        else if (angularVersion.Value == 2)
                        {
                            if (this.mockModules.Count > 0)
                            {
                                throw new NotSupportedException("Mock modules are not supported in Angular 2");
                            }
                        }
                    }
                }
                catch (WebDriverTimeoutException wdte)
                {
                    throw new InvalidOperationException(
                        String.Format("Angular could not be found on the page '{0}'", value), wdte);
                }
            }
        }
    }

由于此属性假定应用程序正在使用Angular,因此在使用Navigate().GoToUrl()导航时,您必须再次包括应用程序是否通过bool使用Angular。 < / p>

在我们的例子中,我们没有使用Angular并将其传递到GoToUrl()方法,通过IWebDriver直接调用包裹的INavigation。此包装驱动程序正确处理本地文件。

下面是Protractor-net中的navigation class

public class NgNavigation : INavigation
{
    private NgWebDriver ngDriver;
    private INavigation navigation;

    // irrelevant constructors and such

    /// <summary>
    /// Load a new web page in the current browser window.
    /// </summary>
    /// <param name="url">The URL to load. It is best to use a fully qualified URL</param>
    /// <param name="ensureAngularApp">Ensure the page is an Angular page by throwing an exception.</param>
    public void GoToUrl(string url, bool ensureAngularApp)
    {
        if (ensureAngularApp)
        {
            this.ngDriver.Url = url;
        }
        else
        {
            this.navigation.GoToUrl(url);
        }
    }