Cypress 在请求正文中使用文件进行 HTTP POST 时出错

2024-03-19

我从 Cypress 6.8.0 升级到 7.0.1。升级后,当 Cypress 测试之一调用此函数时

async saveTask (task, file) {
  const requestBody = new FormData()
  requestBody.append('file', file)

  return await http.post('/api/endpoint', requestBody, {
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  })
},

我收到以下错误

TypeError [ERR_INVALID_ARG_TYPE] [ERR_INVALID_ARG_TYPE]: 
The first argument must be of type string or an instance of Buffer or Uint8Array. Received type number (45)
    at write_ (_http_outgoing.js:696:11)
    at ClientRequest.write (_http_outgoing.js:661:15)
    at Request.write (/Users/donal/Library/Caches/Cypress/7.0.1/Cypress.app/Contents/Resources/app/packages/server/node_modules/@cypress/request/request.js:1496:27)
    at /Users/donal/Library/Caches/Cypress/7.0.1/Cypress.app/Contents/Resources/app/packages/server/node_modules/@cypress/request/request.js:546:20
    at Array.forEach (<anonymous>:null:null)
    at end (/Users/donal/Library/Caches/Cypress/7.0.1/Cypress.app/Contents/Resources/app/packages/server/node_modules/@cypress/request/request.js:545:23)
    at Immediate._onImmediate (/Users/donal/Library/Caches/Cypress/7.0.1/Cypress.app/Contents/Resources/app/packages/server/node_modules/@cypress/request/request.js:578:7)
    at processImmediate (internal/timers.js:461:21)
 {
  code: 'ERR_INVALID_ARG_TYPE'
}

The http我用来发出 POST 请求的对象是 Axios 实例,file我附加到请求正文的对象是File https://developer.mozilla.org/en-US/docs/Web/API/File。文件对象是问题的原因,因为如果我不将其附加到请求正文,则不会发生错误。

仅当该函数由 Cypress 测试运行时才会发生该错误。 Cypress 使用 Node.js,从上面的错误消息来看,似乎File类型是不允许的。此外,Axios 请求配置文档 https://github.com/axios/axios#request-config表明当axios运行在Node下时,File不允许。

  // `data` is the data to be sent as the request body
  // Only applicable for request methods 'PUT', 'POST', 'DELETE , and 'PATCH'
  // When no `transformRequest` is set, must be of one of the following types:
  // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
  // - Browser only: FormData, File, Blob
  // - Node only: Stream, Buffer
  data: {
    firstName: 'Fred'
  },

所以我想我需要转换File反对别的东西,这样该函数既可以在应用程序本身内运行,也可以在由 Cypress 运行时运行。

在服务器端(Spring Boot 应用程序),此文件绑定到MultipartFile

public void handlePost(
    RequestPart(value = "file") MultipartFile file) {

    // controller action body       
}

如果我的理论File类型是问题,我应该使用什么来代替,我应该如何进行转换?


仅当该函数由 Cypress 测试运行时才会发生该错误。 Cypress 使用 Node.js,从上面的错误消息来看似乎 不允许的文件类型。此外,axios请求配置 文档指出,当axios在Node下运行时,不允许使用File。

默认情况下Cypress starts Electron在无头模式下,即测试始终可以访问浏览器 API。您可以控制要在哪个浏览器上运行测试。更多细节here https://docs.cypress.io/guides/guides/launching-browsers#Electron-Browser.

现在我们看一下文件上传的解决方案

假设file你在函数中引用saveTask is an input现场type=file and name=file.

比方说,您需要上传一个名为的 png 图片email.png这是在cypress/fixtures/images/email.png.

使用以下代码块上传文件。

 cy.fixture('images/email.png').as('emailImage')
   cy.get('input[name=file]').then(function (el) {
     const blob = Cypress.Blob.base64StringToBlob(this.emailImage, 'image/png')
     const file = new File([blob], 'email.png', { type: 'image/png' })
     const list = new DataTransfer()
     list.items.add(file)
     el[0].files = list.files
     el[0].dispatchEvent(new Event('change', { bubbles: true }))
 })
 

现在您可以根据调用您的上传 api (/api/endpoint) 来触发操作,并最终验证上传是否成功。

 // Trigger the action which causes the upload api to be invoked e.g. clicking on a button
 cy.get('input[type=button]').click();
 
 // Verify the api invocation is successful (The below code checks a div with id result to have the String 'Success')
 cy.get('#result').should('contain', 'Success');

您可以上传任何类型的文件,并且不必是图像。欲了解更多信息,请查看fixture https://docs.cypress.io/api/commands/fixture and Blob https://docs.cypress.io/api/utilities/blob。这个答案是基于这个example https://docs.cypress.io/api/utilities/blob#Using-an-image-fixture-for-upload关于 Blob 文档。

此存储库使用 GitHub Actions 在 CI 上运行测试https://github.com/GSSwain/file-upload-cypress-test https://github.com/GSSwain/file-upload-cypress-test服务器是一个 Spring boot 应用程序(在 CI 服务器上作为 Docker 容器运行)代码位于https://github.com/GSSwain/file-upload-ajax-sample https://github.com/GSSwain/file-upload-ajax-sample

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Cypress 在请求正文中使用文件进行 HTTP POST 时出错 的相关文章