使用 Cypress 从文本文件上传 multipart/form-data
Uploading multipart/form-data from text file using Cypress
我整天都在做这个,我真的需要在正确的方向上轻推。
我的依赖项是 -
"dependencies": {
"typescript": "^4.3.5",
"cypress": "^8.1.0",
"cypress-file-upload": "^5.0.8"
}
我有一个名为 uploadBlob.txt
的夹具
这是它的样子 -
------WebKitFormBoundary7BhOPSS0NpEAppSA
Content-Disposition: form-data; name="UploadedFileName"
Prod_CA.ACI
------WebKitFormBoundary7BhOPSS0NpEAppSA
Content-Disposition: form-data; name="OrderId"
7815968_13735
------WebKitFormBoundary7BhOPSS0NpEAppSA
Content-Disposition: form-data; name="Options[orderid]"
7815968_13735
------WebKitFormBoundary7BhOPSS0NpEAppSA
Content-Disposition: form-data; name="Options[clientcode]"
1135
------WebKitFormBoundary7BhOPSS0NpEAppSA
Content-Disposition: form-data; name="Options[vendorserviceurl]"
[... 80+ More Items ...]
------WebKitFormBoundary7BhOPSS0NpEAppSA--
我想做的是这样的-
Cypress.Commands.add("formRequest", (info: ReqInfo) => {
cy.readFile("./fixtures/uploadBlob.txt", "utf-8").then(fixture => {
const blob = Cypress.Blob.binaryStringToBlob(fixture, "application/text");
const formData = new FormData();
formData.append('file', blob, "uploadBlob.txt");
return cy.request({
url: info.url,
method: info.method,
headers: info.headers,
form: true,
body: formData
})
})
});
info
看起来像这样 -
let info : ReqInfo = {
method: "POST",
url : 'https://uat-delivery.acisky.com/Delivery/bkfs/Start',
headers: {
'Authority': 'uat-delivery.acisky.com',
'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundary7BhOPSS0NpEAppSA',
'Path': '/DeliveryUpload/bkfs/UploadFile',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-origin',
}
}
这是我遇到的错误 -
From Node.js Internals:
TypeError [ERR_INVALID_ARG_TYPE] [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received undefined
at Function.from (buffer.js:333:9)
at Object.sendPromise
最后,我根据这些 -
尝试了 XMLHttpRequest()
的多次迭代
- In Cypress sending form data using POST request is not working
- Multipart formdata POST request just doesn't work in Cypress for me
例如-
Cypress.Commands.add("formRequest", (info: ReqInfo) => {
cy.readFile("./fixtures/uploadBlob.txt", "utf-8").then(fixture => {
const blob = Cypress.Blob.binaryStringToBlob(fixture, "application/text");
const formData = new FormData();
formData.append('file', blob, "uploadBlob.txt");
const xhr = new XMLHttpRequest();
xhr.responseType = 'text';
xhr.onload = function () {
if (xhr.readyState === xhr.DONE) {
if (xhr.status === 200) {
console.log(xhr.response);
console.log(xhr.responseText);
}
}
};
xhr.open(info.method, info.url);
xhr.setRequestHeader("accept", "application/json");
xhr.setRequestHeader("content-Type", "multipart/form-data");
xhr.setRequestHeader('Authority', 'uat-delivery.acisky.com'),
xhr.send(formData);
})
但这里我收到错误 -
{"errors":["No file found in request"]}
尽管我可以看到 ReadFile
工作正常。
我选择 readFile/fixture 路径和 WebKitBoundry
的原因是因为有超过 80 个“字段”,将来我们将需要此文件的 20-30 个变体.
如果有人对如何完成这项任务有任何想法,我很乐意提供帮助。
谢谢
下面的例子可以帮到你:
cy.fixture("xml.xml", 'binary')
.then((file) => Cypress.Blob.binaryStringToBlob(file))
.then((blob) => {
var formdata = new FormData();
formdata.append("file", blob, "xml.xml");
cy.request({
url: "/api",
method: "POST",
headers: {
Authorization: `bearer ${token}`,
'content-type': 'multipart/form-data'
},
body: formdata
}).its('status').should('be.equal', 200)
})
为了在cypress中使用multipart/form-data,我们需要创建上面调用FormData
的实例。
我正在发布更新,以防有人看到我是如何解决它的。
it('Should Upload the ACI document', () => {
let url = format(aci_url, ENV.env, workOrder.workOrderId, integrator.postfix)
cy.visitURL(url).enter().then(iFrame => {
iFrame().find(UploadDocPage.pageBody).then(input => {
cy.fixture("./files/" + UploadDocPage.fixtureName, 'binary')
.then(Cypress.Blob.binaryStringToBlob)
.then(fileContent => {
cy.wrap(input).attachFile({
fileContent: fileContent,
filePath: UploadDocPage.fixtureName
}).task("log", `Document Attached`)
})
}).wait(5000)
iFrame().waitForElement(UploadDocPage.goButton).click({force: true})
iFrame().waitForElement(UploadDocPage.deliverButton).click({force: true})
cy.task("log", `Document Sent`)
})
})
使这变得更加困难的是它在 iFrame() 中。
该文件是一个 ACI 文档 ("TestFile.ACI") - 本质上它将夹具作为二进制文件,将其转换为 blob 字符串,然后将字符串发送到“输入”。
我整天都在做这个,我真的需要在正确的方向上轻推。
我的依赖项是 -
"dependencies": {
"typescript": "^4.3.5",
"cypress": "^8.1.0",
"cypress-file-upload": "^5.0.8"
}
我有一个名为 uploadBlob.txt
这是它的样子 -
------WebKitFormBoundary7BhOPSS0NpEAppSA
Content-Disposition: form-data; name="UploadedFileName"
Prod_CA.ACI
------WebKitFormBoundary7BhOPSS0NpEAppSA
Content-Disposition: form-data; name="OrderId"
7815968_13735
------WebKitFormBoundary7BhOPSS0NpEAppSA
Content-Disposition: form-data; name="Options[orderid]"
7815968_13735
------WebKitFormBoundary7BhOPSS0NpEAppSA
Content-Disposition: form-data; name="Options[clientcode]"
1135
------WebKitFormBoundary7BhOPSS0NpEAppSA
Content-Disposition: form-data; name="Options[vendorserviceurl]"
[... 80+ More Items ...]
------WebKitFormBoundary7BhOPSS0NpEAppSA--
我想做的是这样的-
Cypress.Commands.add("formRequest", (info: ReqInfo) => {
cy.readFile("./fixtures/uploadBlob.txt", "utf-8").then(fixture => {
const blob = Cypress.Blob.binaryStringToBlob(fixture, "application/text");
const formData = new FormData();
formData.append('file', blob, "uploadBlob.txt");
return cy.request({
url: info.url,
method: info.method,
headers: info.headers,
form: true,
body: formData
})
})
});
info
看起来像这样 -
let info : ReqInfo = {
method: "POST",
url : 'https://uat-delivery.acisky.com/Delivery/bkfs/Start',
headers: {
'Authority': 'uat-delivery.acisky.com',
'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundary7BhOPSS0NpEAppSA',
'Path': '/DeliveryUpload/bkfs/UploadFile',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-origin',
}
}
这是我遇到的错误 -
From Node.js Internals:
TypeError [ERR_INVALID_ARG_TYPE] [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received undefined
at Function.from (buffer.js:333:9)
at Object.sendPromise
最后,我根据这些 -
尝试了XMLHttpRequest()
的多次迭代
- In Cypress sending form data using POST request is not working
- Multipart formdata POST request just doesn't work in Cypress for me
例如-
Cypress.Commands.add("formRequest", (info: ReqInfo) => {
cy.readFile("./fixtures/uploadBlob.txt", "utf-8").then(fixture => {
const blob = Cypress.Blob.binaryStringToBlob(fixture, "application/text");
const formData = new FormData();
formData.append('file', blob, "uploadBlob.txt");
const xhr = new XMLHttpRequest();
xhr.responseType = 'text';
xhr.onload = function () {
if (xhr.readyState === xhr.DONE) {
if (xhr.status === 200) {
console.log(xhr.response);
console.log(xhr.responseText);
}
}
};
xhr.open(info.method, info.url);
xhr.setRequestHeader("accept", "application/json");
xhr.setRequestHeader("content-Type", "multipart/form-data");
xhr.setRequestHeader('Authority', 'uat-delivery.acisky.com'),
xhr.send(formData);
})
但这里我收到错误 -
{"errors":["No file found in request"]}
尽管我可以看到 ReadFile
工作正常。
我选择 readFile/fixture 路径和 WebKitBoundry
的原因是因为有超过 80 个“字段”,将来我们将需要此文件的 20-30 个变体.
如果有人对如何完成这项任务有任何想法,我很乐意提供帮助。
谢谢
下面的例子可以帮到你:
cy.fixture("xml.xml", 'binary')
.then((file) => Cypress.Blob.binaryStringToBlob(file))
.then((blob) => {
var formdata = new FormData();
formdata.append("file", blob, "xml.xml");
cy.request({
url: "/api",
method: "POST",
headers: {
Authorization: `bearer ${token}`,
'content-type': 'multipart/form-data'
},
body: formdata
}).its('status').should('be.equal', 200)
})
为了在cypress中使用multipart/form-data,我们需要创建上面调用FormData
的实例。
我正在发布更新,以防有人看到我是如何解决它的。
it('Should Upload the ACI document', () => {
let url = format(aci_url, ENV.env, workOrder.workOrderId, integrator.postfix)
cy.visitURL(url).enter().then(iFrame => {
iFrame().find(UploadDocPage.pageBody).then(input => {
cy.fixture("./files/" + UploadDocPage.fixtureName, 'binary')
.then(Cypress.Blob.binaryStringToBlob)
.then(fileContent => {
cy.wrap(input).attachFile({
fileContent: fileContent,
filePath: UploadDocPage.fixtureName
}).task("log", `Document Attached`)
})
}).wait(5000)
iFrame().waitForElement(UploadDocPage.goButton).click({force: true})
iFrame().waitForElement(UploadDocPage.deliverButton).click({force: true})
cy.task("log", `Document Sent`)
})
})
使这变得更加困难的是它在 iFrame() 中。
该文件是一个 ACI 文档 ("TestFile.ACI") - 本质上它将夹具作为二进制文件,将其转换为 blob 字符串,然后将字符串发送到“输入”。