I spent most of the weekend on this so will post the solution that works for me.
I couldn't get the example in the NPM package cypress-upload-file-post-form to work as it is written. Specifically I got a function not found error on Cypress.Blob.binaryStringToBlob.
Step 1
In support/commands.js add this function
Cypress.Commands.add('multipartFormRequest', (method, url, formData, done) => {
const xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.onload = function () {
done(xhr);
};
xhr.onerror = function () {
done(xhr);
};
xhr.send(formData);
});
Step 2
Add a file called Base64TestCV.rtf to the fixtures folder.
I wanted a .rtf file but obviously you can make a .txt file - whatever you do it must be encoded in base64 by using an online converter or the base64 command in Linux.
For testing purposes, make sure it contains the text MyCypressTestCV (encoded in base64 obviously).
Step 3
Create and run your test. In this example my .rtf file contains the text MyCypressTestCV which is reflected back by httpbin.org so it proves it was decoded from base64 correctly and uploaded.
describe('Upload a file to a multipart form using cy.request', function () {
it('Performs a multipart post to httpbin.org', function () {
const baseUrl = 'http://httpbin.org';
const postUrl = `${baseUrl}/post`;
cy.visit(baseUrl); // Cypress will be very buggy if you don't do at least one cy.visit
cy.request(baseUrl).as('multipartForm'); // pretend we are doing the GET request for the multipart form
const base64FileName = 'Base64TestCV.rtf';
const postedFileName = 'TestCV.rtf';
const method = 'POST';
const mimeType = 'application/rtf';
cy.fixture(base64FileName).as('base64File'); // file content in base64
cy.get('@multipartForm').then((response) => {
const formData = new FormData();
formData.append('firstFormField', 'Hello');
formData.append('secondFormField', '25');
const blob = Cypress.Blob.base64StringToBlob(this.base64File, mimeType);
formData.append('uploadFile', blob, postedFileName);
cy.multipartFormRequest(method, postUrl, formData, function (response) {
expect(response.status).to.eq(200);
expect(response.response).to.match(/MyCypressTestCV/); // http://httpbin.org/post reflects what you post
});
});
});
});