2

I'm trying to create a new cypress command which allows me to post a file using formData as cy.request doesn't support formData yet.

I'm using request-promise-native for the POST itself.

First, in my commands.ts I'm extending the Cypress.Chainable interface like this:

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

FullResponse is the response type definition for request-promise-native.

My postFormData function looks like this:

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
}

Finally, I'm registering the new command:

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

In my test.ts, I'm calling the command like this:

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

However, tsc gives me these errors:

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 returns a Chainable but not a Promise, so how can I solve this?

1 Answer 1

1

This is a possible solution

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)

The correct usage is:

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

Update

As request is in maintainance mode and there's an issue with browsers and formData, here's a solution using 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)

Usage:

cy.postFormData(
  url,
  formData,
  accessToken)
  .then((response) => {
    expect(response.status).to.equal(202)
  })
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.