我想通过 AngularJS 的端到端(e2e)测试来测试文件上传。在 e2e 测试中如何实现这一操作?我通过 Grunt Karma 运行我的测试脚本。
我想通过 AngularJS 的端到端(e2e)测试来测试文件上传。在 e2e 测试中如何实现这一操作?我通过 Grunt Karma 运行我的测试脚本。
这是我的做法:
var path = require('path');
it('should upload a file', function() {
var fileToUpload = '../some/path/foo.txt',
absolutePath = path.resolve(__dirname, fileToUpload);
element(by.css('input[type="file"]')).sendKeys(absolutePath);
element(by.id('uploadButton')).click();
});
path
模块来解析您想要上传的文件的完整路径。这在火狐浏览器上不起作用。Protractor会抱怨因为该元素不可见。要在火狐浏览器中上传,您需要使输入框可见。这是我所做的:
browser.executeAsyncScript(function(callback) {
// You can use any other selector
document.querySelectorAll('#input-file-element')[0]
.style.display = 'inline';
callback();
});
// Now you can upload.
$('input[type="file"]').sendKeys(absolutePath);
$('#uploadButton').click();
__dirname
可能指向临时目录(可能是测试运行程序复制测试的地方)。如果是这种情况,你可以使用 process.cwd()
替换 __dirname
。 - BorisOkunskiy直接操作是不可能的。
出于安全原因,在类似ngScenario这样的功能测试套件中,您无法模拟选择系统上文件的用户。
使用Protractor,由于其基于WebDriver,应该可以使用这个技巧
Q:WebDriver支持文件上传吗? A:是的。
您无法直接与本机操作系统文件浏览器对话框交互,但我们会进行一些操作,以便如果您在文件上传元素上调用WebElement#sendKeys(“/path/to/file”),它会执行正确的操作。 确保您不要单击文件上传元素的WebElement#click(),否则浏览器可能会挂起。
这很好地解决了问题:
$('input[type="file"]').sendKeys("/file/path")
// requires an absolute path
var fileToUpload = './testPackages/' + packageName + '/' + fileName;
var absolutePath = path.resolve(__dirname, fileToUpload);
// Find the file input element
var fileElem = element(by.css('input[type="file"]'));
// Need to unhide flowjs's secret file uploader
browser.executeScript(
"arguments[0].style.visibility = 'visible'; arguments[0].style.height = '1px'; arguments[0].style.width = '1px'; arguments[0].style.opacity = 1",
fileElem.getWebElement());
// Sending the keystrokes will ultimately submit the request. No need to simulate the click
fileElem.sendKeys(absolutePath);
// Not sure how to wait for the upload and response to return first
// I need this since I have a test that looks at the results after upload
// ... there is probably a better way to do this, but I punted
browser.sleep(1000);
var imagePath = 'http://placehold.it/120x120&text=image1';
element(by.id('fileUpload')).sendKeys(imagePath);
这对我有效。
这是我在Firefox上上传文件的方法,这个脚本使元素可见以设置路径值:
browser.executeScript("$('input[type=\"file\"]').parent().css('visibility', 'visible').css('height', 1).css('width', 1).css('overflow', 'visible')");
首先,为了上传文件,应该有一个input
元素,用于输入文件路径。通常,它紧挨着“上传”按钮... 但是我见过这种情况,当按钮周围没有一个输入框时可能会让人感到困惑。保持冷静,输入框必须存在于页面上!尝试在DOM中查找具有类似“上传”或“文件”之类的输入元素,只需记住它可以出现在任何地方。
当您找到它后,获取其选择器,并键入文件路径。请记住,它必须是绝对路径,从您的根目录开始(对于MAC用户为/something/like/this
,对于Windows用户为C:/some/file
)
await $('input[type="file"]').sendKeys("/file/path")
Protractor的sendKeys只能在可见的输入框中输入文字。通常,输入框可能会被隐藏或大小为0
像素。你也可以解决这个问题。
let $input = $('input[type="file"]');
await browser.executeScript(
"arguments[0].style.visibility = 'visible'; arguments[0].style.height = '1px'; arguments[0].style.width = '1px'; arguments[0].style.opacity = 1",
$input.getWebElement()
);
// 从 C:\ 目录上传文件
{
var path = require('path');
var dirname = 'C:/';
var fileToUpload = '../filename.txt';
var absolutePath = path.resolve('C:\filename.txt');
var fileElem = ptor.element.all(protractor.By.css('input[type="file"]'));
fileElem.sendKeys(absolutePath);
cb();
fileToUpload
是用来做什么的? - user6749601 browser.executeAsyncScript(function (callback) {
document.querySelectorAll('input')[2]
.style = '';
document.querySelectorAll('input')[2].scrollIntoView();
callback();
});
(我还删除了文件输入元素的所有样式)
var path = require('path');
var remote = require('../../node_modules/selenium-webdriver/remote');
browser.setFileDetector(new remote.FileDetector());
var fileToUpload = './resume.docx';
var absolutePath = path.resolve(process.cwd() + fileToUpload);
element(by.css('input[type="file"]')).sendKeys(absolutePath);
当前记录的解决方案仅在用户加载jQuery时有效。在所有不同的情况下,用户都会收到一个错误,如:Failed: $未定义
我建议记录一种使用本地angularjs代码的解决方案。
例如,我建议不是建议:
$('input[type="file"]') .....
建议:
angular.element(document.querySelector('input[type="file"]')) .....
后者更标准,在 Angular 的基础上,更重要的是不需要 jQuery。