question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Posting formData using cypress doesn't work

See original GitHub issue

Current behavior:

Uploading file via POST request of formData doesn’t work.

Desired behavior:

Being able to post formData using cypress POST request.

Steps to reproduce:

The following code doesn’t work.

  const formData = new FormData();
  formData.set('file', new File(['data'], 'upload.txt'), 'upload.txt');
  cy.request({
    method: 'POST',
    url: '/upload/end/point',
    body: formData,
    headers: {
      'content-type': 'multipart/form-data',
    },
  });

Versions

cypress@2.1.0 ubuntu 16.04 LTS Chrome 66.0.3359

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:26
  • Comments:32 (3 by maintainers)

github_iconTop GitHub Comments

8reactions
drewbrendcommented, Aug 6, 2018

cc: @srinivasrk @ahmehri

I was able to get a formData submitted with a combination of a mix of answers I found.

I hope this helps you.

Add this to support/commands.js:

Cypress.Commands.add("form_request", (url, formData) => {
    return cy
      .server()
      .route("POST", url)
      .as("formRequest")
      .window()
      .then(win => {
        var xhr = new win.XMLHttpRequest();
        xhr.open(method, url);
        xhr.send(formData);
      })
      .wait("@formRequest");
});

Then you’d be able to do the following in your tests:

cy
  .form_request(url, formData)
  .then(response => {
    // do stuff with your response
  });
4reactions
ryanwelch-degreedcommented, Sep 15, 2020

If XHR request is part of your test setup and you need its response later on, here is the solution I worked out:

In a helper file you can define a function to execute the request:

export function formRequest(method, url, formData, headers) {
  const request = new XMLHttpRequest();
  request.open(method, url, false);
  if (headers) {
    headers.forEach(function(header) {
      request.setRequestHeader(header.name, header.value);
    });
  }
  request.send(formData);
  return JSON.parse(request.response);
}

Using helper function you can define a specific request to your API as:

export function customerUploadFile(accessToken, file, fileName, fileType) {
  return cy.fixture(file, 'binary').then(function(binary) {
    return Cypress.Blob.binaryStringToBlob(binary, fileType).then(function(blob) {
      const targetUrl = `${apiUrl}/${apiVersion}/customer/action/upload_file?license_id=${licenseId}`;
      const headers = [{ name: 'Authorization', value: `Bearer ${accessToken}` }];
      const formData = new FormData();
      formData.set('file', blob, fileName);
      return formRequest('POST', targetUrl, formData, headers);
    });
  });
}

And your custom command:

Cypress.Commands.add('customerUploadFile', function(customerToken, fixtureName) {
  return cy.fixture(fixtureName).then(function(fixture) {
    const { file, fileName, fileType } = fixture;
    return customerUploadFile(customerToken, file, fileName, fileType);
  });
});

Now in your fixtures you can prepare following files:

  • fixtures/image/image.jpg
  • fixture/image.json
{
  "file": "images/image.jpg",
  "fileName": "image.jpg",
  "fileType": "image/jpg"
}

And in your test you can easily handle such image upload:

    it('test', function() {
      const fixtureName = 'image';
      const constAuthToken = 'however you obtain it';
      cy.customerUploadFile(constAuthToken, fixtureName).then(function(uploadResponse) {
       cy.log(uploadResponse);
        });
      });
    });

This will get necessary information about image from the json fixture and then get the binary and upload it.

Thanks @shwarcu this is pretty much everything you need. There are a couple of little things you need to make sure you do with this.

  • cy.fixture() in combination with “Cypress.Blob.binaryStringToBlob()” does not appear to parse the file correctly, unless you specify ‘binary’ in cy.fixture, i.e. cy.fixture(‘filepath’, ‘binary’). If you exclude this the FormData object is not created correctly.
  • Make sure you do not specify the content type when using multipart/form-data. The boundary needs to be added to that header in the request, so we need to let the request add that header on it’s own.
  • logging anything about the FormData or request in this situation is inaccurate. Cypress does not capture the actual request being sent, so you would need to capture the request with a different tool to see what is actually being sent.
  • with Cypress 5 and up, the “Cypress.Blob.binaryStringToBlob” can be assigned directly to a variable as it is no longer a promise.

It would really be ideal for Cypress to add support for multipart/form-data requests using their cy.request() command, but this is a reasonable workaround for the moment. This is very picky on how everything is set up and executed, so it is likely to break with future Cypress updates.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Uploading multipart/form-data from text file using Cypress
In Cypress sending form data using POST request is not working · Multipart formdata POST request just doesn't work in Cypress for me...
Read more >
Cypress-upload-file-post-form - npm.io
It works for excel files. For both cases, the file to be uploaded / sent in the form will be placed in fixtures...
Read more >
Send Data From The Application To The Cypress Test
We hit a slight problem. The application modifies the data before sending it. Of course, the test should know exactly what the expected...
Read more >
request - Cypress Documentation
Cypress does not actually make an XHR request from the browser. We are actually making the HTTP request from Cypress (in Node). So,...
Read more >
Issue - Garett Petersen
I came across a limitation with cypress while trying to upload an image using formData. Cypress cy.request() currently does not support formData submission....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found