Multipart formdata POST request just doesn't w

2019-07-12 18:09发布

问题:

Nothing works for me. If I use cy.request(), I'm unable to send formdata with it which contains a text and an image. So I've to go via XHR route. So, in my command.js I've used the following code to create a command: -

Cypress.Commands.add("formrequest", (method, url, formData, done) => {
  cy.window().then(win => {
    return new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest();
      xhr.open(method, url, false);
      xhr.setRequestHeader("accept", "application/json");
      xhr.setRequestHeader("access-token", accesstoken);
      xhr.setRequestHeader("client", client);
      xhr.setRequestHeader("expiry", expiry);
      xhr.setRequestHeader("token-type", tokentype);
      xhr.setRequestHeader("uid", uid);
      xhr.setRequestHeader("Accept-Encoding", null);
      xhr.onload = function() {
        done(xhr);
      };
      xhr.onerror = function() {
        done(xhr);
      };
      xhr.send(formData);
    });
  });
});

Now, when I'm calling it I will first construct a BLOB and then use it in my formdata to later send the XHR request. Like this: -

it.only("Test XHR", () => {
    cy.AppLogin();
    cy.fixture("/images/clients/Golden JPEG.jpeg", "binary").then(imageBin => {
      // File in binary format gets converted to blob so it can be sent as Form data
      Cypress.Blob.binaryStringToBlob(imageBin, "image/jpeg").then(blob => {
        // Build up the form
        const formData = new FormData();

        formData.set("client[name]", "Test TER"); //adding a plain input to the form

        formData.set(
          "client[client_logo_attributes][content]",
          blob
          //"Bull Client.jpg"
        ); //adding a file to the form

        // Perform the request
        cy.formrequest(method, url, formData, function(response) {
          expect(response.status).to.eq(201);
        });
      });
    });
  });

Please note that cy.AppLogin() sets up the request headers like accesstoken, client, expiry, tokentype and uid.

Kindly refer to the attached file (XHRfromCypress.txt) for checking the XHR request being generated using the code provided above. Also attached is a file (XHRfromCypressUI.txt) for showing XHR request being made when I did run my cypress end-2-end test from application UI.

I'm constantly getting 405, Method not allowed error.

E2E test from UI

API Test

E2E test works but API test using above code simply doesn't work. I also tried cy.request() but as it is not shown in the developers tab I'm not sure I've done it correctly. Also, i'm doubtful about the way I used formdata in there. Means whether cy.request() can even accept dormdata.

I've both (E2E and API) XHR's exported, just in case those are needed.

Do I need to add any libraries to make XHR request? I've aonly added Cypress library in my project setup.

////////////////

Moving all code into Test Case neither fixes anything

it.only("POSTing", () => {
    cy.fixture("/images/clients/Golden JPEG.jpeg", "binary").then(imageBin => {
      Cypress.Blob.binaryStringToBlob(imageBin, "image/jpeg").then(blob => {
        data.set("client[name]", "Test TER fails");
        data.set("client[client_logo_attributes][content]", blob);
        xhr.open(method, url);
        xhr.setRequestHeader("accept", "application/json");
        xhr.setRequestHeader("access-token", accesstoken);
        xhr.setRequestHeader("client", client);
        xhr.setRequestHeader("expiry", expiry);
        xhr.setRequestHeader("token-type", tokentype);
        xhr.setRequestHeader("uid", uid);
        xhr.send(data);
      });
    });
  });

回答1:

Thanks Eric. It works for me following Eric's advise and instructions mentioned at github.com/javieraviles/cypress-upload-file-post-form

Cypress.Commands.add(
  "Post_Clients",
  (imagePath, imageType, attr1, attr2, attr1Val, done) => {
    cy.fixture(imagePath, "binary").then(imageBin => {
      Cypress.Blob.binaryStringToBlob(imageBin, imageType).then(blob => {
        const xhr = new XMLHttpRequest();
        xhr.withCredentials = true;
        const data = new FormData();
        data.set(attr1, attr1Val);
        data.set(attr2, blob);
        xhr.open("POST", "https://api.teamapp.myhelpling.com/admin/clients");
        xhr.setRequestHeader("accept", "application/json");
        xhr.setRequestHeader("access-token", accesstoken);
        xhr.setRequestHeader("client", client);
        xhr.setRequestHeader("expiry", expiry);
        xhr.setRequestHeader("token-type", tokentype);
        xhr.setRequestHeader("uid", uid);
        xhr.onload = function() {
          done(xhr);
        };
        xhr.onerror = function() {
          done(xhr);
        };
        xhr.send(data);
      });
    });
  }
);


it.only("API POSTing TEST", () => {
    cy.Post_Clients(
      "/images/clients/Golden JPEG.jpeg",
      "image/jpeg",
      "client[name]",
      "client[client_logo_attributes][content]",
      "Test Attr 1 Value is Hi!!!",
      response => {
        cy.writeFile(
          "cypress/fixtures/POST API OUTPUT DATA/Client.json",
          response.
        );
        expect(response.status).to.eq(201);
      }
    );
  });