Selenium FindElement 阻塞,直到文件上传完成

Posted

技术标签:

【中文标题】Selenium FindElement 阻塞,直到文件上传完成【英文标题】:Selenium FindElement blocks until file upload is complete 【发布时间】:2014-04-02 05:47:46 【问题描述】:

短片:

当我使用 SendKeys(path) 触发文件上传到代理元素(由 ExecuteScript 放置)然后通过 jquery.fileupload 插件代理到我的隐藏文件时,文件上传正常,但是当我尝试发出 @ 987654321@,它会阻塞直到服务器响应。

长篇:

我正在使用 2.4 C# web 驱动程序、默认 firefox 驱动程序和 jquery 文件上传插件(蓝色小鬼)。

流程从单击按钮打开“概览对话框”开始,其中包含我的

<input id="fileUpload" type="file" name="files[]" accept="video/quicktime,video/x-ms-wmv">
<lablel for="fileUpload">Select a file</label>

对话框合成后,我有

jquery('#fileUpload').fileupload(self.fileUploadOptions);

正常用法让用户单击标签,触发输入,然后触发并添加回调,检查大小/类型,如果确定,则更改为 PROGRESS 对话框,并执行data.submit()

进度一直持续到响应,此时最终对话框会显示一些结果,并且可以使用另一个按钮将其关闭。

所以,简而言之:

    打开一个对话框 将对话框中的模板设置为简介 选择一个文件 将对话框中的模板更改为进度 开始 ajax(或 iframe)上传 在对话框中更改模板以完成

Selenium 无法访问 fileUpload 输入(隐藏),所以为了让 Selenium 触发文件上传,我最终不得不执行一些这样的脚本:

    添加一个新的输入元素:

    jQuery('', id: 'tmpId', type: 'file', name:'files[]').appendTo('modalDivId')

    触发回调:

    $('#tmpId').bind('change', function (e) $('#fileUpload').fileupload('add', 文件:e.target.files || [名称:this.value], 文件输入:$(this) ); );

所以,现在在创建 tmpId 输入元素之后,我的 selenium 脚本会这样做:

var path="\path\to\files";
var tmpInput = WebDriver.FindElement(By.Id("tmpId));
tmpInput.SendKeys(path);

这会触发添加回调,检查文件,将模板更改为“进度”,然后开始上传。 假设上传需要 60 秒,服务器会响应,然后模板会触发“完成”

问题在于:

tmpInput.SendKeys(path);

返回'立即',所以我打电话给

var a = WebDriver.FindElement(By.Id("tmpId"));

这个会一直阻塞,直到文件上传完成(60 秒)。即使进度条正在更新。

然后返回成功。

因为我想要验证这个进度模板,所以我真的很想在上传期间访问 DOM。

有什么想法吗?

【问题讨论】:

【参考方案1】:

表单是否在流程中的任何地方提交?我的意思是提交是在任何地方触发还是刷新或单击 elemnet 或类似的?问题是 webdriver 是一个阻塞 API,当加载/刷新或类似的被触发时,webdriver 将检查各种内容以检查页面是否完成加载(即 document.readyState == 'complete')等。

无论如何,应该可以覆盖这个策略,你可以尝试调查page load strategies。

【讨论】:

表单正在通过 add 回调中的 jquery 插件 (data.submit()) 提交。那么,您是说我创建的 webdriver 在 ajax 发布期间可能被阻塞(等待它“完成”)?听起来我不能在每次通话的基础上覆盖这个策略?我想如果我改变策略,它会弄乱我其余的测试。我想知道我是否可以使用多个驱动程序。我会调查一下,然后回来标记答案。 我真的不太了解页面加载策略的使用,它们是在 FFDriver v2.40(最新,一周前发布)时引入的。您还可以尝试的一件事是设置 pageLoadTimeout 并使用显式等待来确保页面已加载。 “听起来我不能在每次调用的基础上覆盖这个策略?” - 我很确定这是每个驱动程序的事情。【参考方案2】:

如果你想等待ajax操作你可以使用类似这样的东西

            var ajaxIsComplete = javascriptExecutor != null && (bool)javaScriptExecutor.ExecuteScript("return jQuery.active == 0");

如果页面中没有ajax活动,上面的代码将返回true,但我建议你使用等待

        var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(time));
        wait.Until(ElementIsClickable(locator);

如果你想给等待时间,比如 60、120 秒等。它将在持续时间内等待,直到元素被解除阻塞

如果您认为我误解了您的阙,我认为这是最好的解决方案,请告诉我

【讨论】:

你错过了这个问题。 “我真的很想在上传期间访问 DOM。有什么想法吗?” 您想验证进度条是否正确,您是否在进度条上放置了任何块 ui

以上是关于Selenium FindElement 阻塞,直到文件上传完成的主要内容,如果未能解决你的问题,请参考以下文章

Selenium WebDriver findElement(By.xpath())不适合我

selenium元素定位(Java)

selenium学习历程

java+selenium元素定位和元素操作

java+selenium元素定位和元素操作

selenium 定位元素