javascript 如何使用赛普拉斯测试文件输入?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/47074225/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to test file inputs with Cypress?
提问by sidoshi
How can I write an e2e test of flow that requires interaction with the file Input DOM element?
如何编写需要与文件 Input DOM 元素交互的 e2e 流测试?
If it's a text input I can interact with it (check value, set value) etc as its a DOM component. But If I have a File Input element, I am guessing that the interaction is limited till I can open the dialog to select a File. I can't move forward and select the file I want to upload as the dialog would be native and not some browser element.
如果它是一个文本输入,我可以与它交互(检查值、设置值)等作为它的 DOM 组件。但是如果我有一个文件输入元素,我猜交互是有限的,直到我可以打开对话框来选择一个文件。我无法前进并选择我要上传的文件,因为对话框是原生的,而不是某些浏览器元素。
So how would I test that a user can correctly upload a file from my site? I am using Cypressto write my e2e tests.
那么我将如何测试用户是否可以从我的网站正确上传文件?我正在使用Cypress编写我的 e2e 测试。
采纳答案by Jennifer Shehane
Testing File Input elements is not yet supported in Cypress. The only way to test File Inputs is to:
赛普拉斯尚不支持测试文件输入元素。测试文件输入的唯一方法是:
- Issue native events (which Cypress has on their Roadmap).
- Understand how your application handles file uploads with File API and then stub it out. It's possible but not generic enough to give any specific advice on.
- 发布本地事件(赛普拉斯在他们的路线图上有)。
- 了解您的应用程序如何使用 File API 处理文件上传,然后将其存根。这是可能的,但不够通用,无法提供任何具体建议。
回答by Javier Aviles
With this approach/hack you can actually make it: https://github.com/javieraviles/cypress-upload-file-post-form
通过这种方法/hack,您实际上可以做到:https: //github.com/javieraviles/cypress-upload-file-post-form
It is based on different answers from the aformentioned thread https://github.com/cypress-io/cypress/issues/170
它基于上述线程https://github.com/cypress-io/cypress/issues/170 的不同答案
First scenario (upload_file_to_form_spec.js):
第一个场景(upload_file_to_form_spec.js):
I want to test a UI where a file has to be selected/uploaded before submitting the form. Include the following code in your "commands.js" file within the cypress support folder, so the command cy.upload_file() can be used from any test:
我想测试一个用户界面,在提交表单之前必须选择/上传文件。将以下代码包含在 cypress 支持文件夹内的“commands.js”文件中,以便可以在任何测试中使用命令 cy.upload_file():
Cypress.Commands.add('upload_file', (fileName, fileType, selector) => {
cy.get(selector).then(subject => {
cy.fixture(fileName, 'hex').then((fileHex) => {
const fileBytes = hexStringToByte(fileHex);
const testFile = new File([fileBytes], fileName, {
type: fileType
});
const dataTransfer = new DataTransfer()
const el = subject[0]
dataTransfer.items.add(testFile)
el.files = dataTransfer.files
})
})
})
// UTILS
function hexStringToByte(str) {
if (!str) {
return new Uint8Array();
}
var a = [];
for (var i = 0, len = str.length; i < len; i += 2) {
a.push(parseInt(str.substr(i, 2), 16));
}
return new Uint8Array(a);
}
Then, in case you want to upload an excel file, fill in other inputs and submit the form, the test would be something like this:
然后,如果你想上传一个 excel 文件,填写其他输入并提交表单,测试将是这样的:
describe('Testing the excel form', function () {
it ('Uploading the right file imports data from the excel successfully', function() {
const testUrl = 'http://localhost:3000/excel_form';
const fileName = 'your_file_name.xlsx';
const fileType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
const fileInput = 'input[type=file]';
cy.visit(testUrl);
cy.upload_file(fileName, fileType, fileInput);
cy.get('#other_form_input2').type('input_content2');
.
.
.
cy.get('button').contains('Submit').click();
cy.get('.result-dialog').should('contain', 'X elements from the excel where successfully imported');
})
})
})
回答by Muhammad Bilal
it('Testing picture uploading', () => {
cy.fixture('testPicture.png').then(fileContent => {
cy.get('input[type="file"]').upload({
fileContent: fileContent.toString(),
fileName: 'testPicture.png',
mimeType: 'image/png'
});
});
});
Use cypress file upload package: https://www.npmjs.com/package/cypress-file-upload
使用cypress文件上传包:https: //www.npmjs.com/package/cypress-file-upload
Note: testPicture.png must be in fixture folder of cypress
注意:testPicture.png 必须在cypress的fixture文件夹中
回答by Vicky
The following function works for me,
以下功能对我有用,
cy.getTestElement('testUploadFront').should('exist');
const fixturePath = 'test.png';
const mimeType = 'application/png';
const filename = 'test.png';
cy.getTestElement('testUploadFrontID')
.get('input[type=file')
.eq(0)
.then(subject => {
cy.fixture(fixturePath, 'base64').then(front => {
Cypress.Blob.base64StringToBlob(front, mimeType).then(function(blob) {
var testfile = new File([blob], filename, { type: mimeType });
var dataTransfer = new DataTransfer();
var fileInput = subject[0];
dataTransfer.items.add(testfile);
fileInput.files = dataTransfer.files;
cy.wrap(subject).trigger('change', { force: true });
});
});
});
// Cypress.Commands.add(`getTestElement`, selector =>
// cy.get(`[data-testid="${selector}"]`)
// );
回答by Vishwa
In my case I had client & server side file validation to check if the file is JPEG or PDF. So I had to create a upload command which would read the file in binary from Fixtures and prepare a blob with the file extension.
就我而言,我进行了客户端和服务器端文件验证以检查文件是 JPEG 还是 PDF。因此,我必须创建一个上传命令,该命令将从 Fixtures 中读取二进制文件并准备一个带有文件扩展名的 blob。
Cypress.Commands.add('uploadFile', { prevSubject: true }, (subject, fileName, fileType = '') => {
cy.fixture(fileName,'binary').then(content => {
return Cypress.Blob.binaryStringToBlob(content, fileType).then(blob => {
const el = subject[0];
const testFile = new File([blob], fileName, {type: fileType});
const dataTransfer = new DataTransfer();
dataTransfer.items.add(testFile);
el.files = dataTransfer.files;
cy.wrap(subject).trigger('change', { force: true });
});
});
});
then use it as
然后将其用作
cy.get('input[type=file]').uploadFile('smiling_pic.jpg', 'image/jpeg');
smiling_pic.jpg will be in fixtures folder
smile_pic.jpg 将在 fixtures 文件夹中
回答by Scott
Also based on previously mentioned github issue, so big thanks to the folks there.
同样基于前面提到的github 问题,非常感谢那里的人。
The upvoted answer worked initially for me, but I ran into string decoding issues trying to handle JSON files. It also felt like extra work having to deal with hex.
赞成的答案最初对我有用,但我在尝试处理 JSON 文件时遇到了字符串解码问题。这也感觉像是必须处理十六进制的额外工作。
The code below handles JSON files slightly differently to prevent encode/decode issues, and uses Cypress's built in Cypress.Blob.base64StringToBlob:
下面的代码以稍微不同的方式处理 JSON 文件以防止编码/解码问题,并使用 Cypress 的内置Cypress.Blob.base64StringToBlob:
/**
* Converts Cypress fixtures, including JSON, to a Blob. All file types are
* converted to base64 then converted to a Blob using Cypress
* expect application/json. Json files are just stringified then converted to
* a blob (prevents issues with invalid string decoding).
* @param {String} fileUrl - The file url to upload
* @param {String} type - content type of the uploaded file
* @return {Promise} Resolves with blob containing fixture contents
*/
function getFixtureBlob(fileUrl, type) {
return type === 'application/json'
? cy
.fixture(fileUrl)
.then(JSON.stringify)
.then(jsonStr => new Blob([jsonStr], { type: 'application/json' }))
: cy.fixture(fileUrl, 'base64').then(Cypress.Blob.base64StringToBlob)
}
/**
* Uploads a file to an input
* @memberOf Cypress.Chainable#
* @name uploadFile
* @function
* @param {String} selector - element to target
* @param {String} fileUrl - The file url to upload
* @param {String} type - content type of the uploaded file
*/
Cypress.Commands.add('uploadFile', (selector, fileUrl, type = '') => {
return cy.get(selector).then(subject => {
return getFixtureBlob(fileUrl, type).then(blob => {
return cy.window().then(win => {
const el = subject[0]
const nameSegments = fileUrl.split('/')
const name = nameSegments[nameSegments.length - 1]
const testFile = new win.File([blob], name, { type })
const dataTransfer = new win.DataTransfer()
dataTransfer.items.add(testFile)
el.files = dataTransfer.files
return subject
})
})
})
})

