网站搜索

在使用 TypeScript 时添加自定义 Cypress 命令


我正在尝试创建一个新的 cypress 命令,它允许我使用 formData 上传文件,因为 cy.request 还不支持 formData。

我正在为 POST 本身使用 request-promise-native。

首先,在我的 commands.ts 中,我像这样扩展 Cypress.Chainable 接口:

declare global {
  namespace Cypress {
    interface Chainable<Subject = any> {
      postFormData(
        url: string, 
        formData: FormData, 
        token: string): Chainable<FullResponse>
    }
  }
}

FullResponse 是 request-promise-native 的响应类型定义。

我的 postFormData 函数如下所示:

function postFormData(
  url,
  formData,
  token
): Cypress.Chainable<FullResponse> {  // this is line 52
  const response: FullResponse = await post(url, {
    auth: { bearer: token },
    formData
  })
  return cy.wrap(response) // this is line 58
}

最后,我正在注册新命令:

Cypress.Commands.add('postFormData', postFormData)

在我的 test.ts 中,我是这样调用命令的:

const response = cy.postFormData(
  url,
  formData,
  accessToken)
expect(response.statusCode).to.equal(202)

然而,tsc 给了我这些错误:

commands.ts:52:4 -  error TS1064: The return type of an async function or method must be the global Promise<T> type.

commands.ts:58:3 - error TS1058: The return type of an async function must either be a valid promise or must not contain a callable 'then' member.

cy.wrap 返回一个 Chainable 而不是 Promise,那我该如何解决这个问题?

答案#1

这是一个可能的解决方案

import { post, FullResponse } from 'request-promise-native'

declare global {
  namespace Cypress {
    interface Chainable<Subject = any> {
      postFormData(
        url: string, 
        formData: FormData, 
        token: string): Chainable<FullResponse>
    }
  }
}

function postFormData(url, formData, token): Cypress.Chainable<any> {
  return cy.wrap(
    post(url, {
      auth: { bearer: token },
      formData
    })
  )

Cypress.Commands.add('postFormData', postFormData)

正确用法是:

cy.postFormData(
  url,
  formData,
  accessToken)
  .then((response) => {
    expect(response.statusCode).to.equal(202)
  })

更新

由于 request 处于维护模式,并且浏览器和 formData 存在问题,这里提供一个使用 axios 的解决方案:

import axios, { AxiosResponse } from 'axios'

declare global {
  namespace Cypress {
    interface Chainable<Subject = any> {
      postFormData(
        url: string,
        formData: FormData,
        token: string
      ): Chainable<AxiosResponse>
    }
  }
}

function postFormData(url, formData, token): Cypress.Chainable<any> {
  return cy.wrap(
    axios(url, {
      method: 'post',
      url,
      data: formData,
      headers: {
        Authorization: `Bearer ${token}`,
        'Content-Type': 'multipart/form-data'
      }
    })
  )
}

Cypress.Commands.add('postFormData', postFormData)

用法:

cy.postFormData(
  url,
  formData,
  accessToken)
  .then((response) => {
    expect(response.status).to.equal(202)
  })