I know that there is a plugin for doing this in cypress already. However using it with jar files just corrupts the file and therefore it is useless in my usecase. This is really weird because i tried it with every combination of encoding and it still does not work. Works perfectly fine with other filetypes however.

This is the code i am using (works except with jar files).

 cy.fixture('test.jar', 'binary')
            .then(Cypress.Blob.binaryStringToBlob)
            .then(fileContent => {
                cy.get('[data-cy="dropzone"]')
                    .contains('Jar file')
                    .parent()
                    .find('div')
                    .attachFile({
                        fileContent,
                        filePath: 'test.jar',
                        mimeType: 'application/java-archive',
                        encoding: 'binary',
                        lastModified: new Date().getTime(),
                        subjectType: 'drag-n-drop',
                        force: true
                    });
            });

I know that you can perform post requests in cypress. Is it possible to perfom the file upload with it after clicking the dropzone element?


Solution 1:

cypress-file-upload lacks explicit support for .jar extension, this is the current list of supported extensions

const FILE_EXTENSION = Object.freeze({
  JSON: 'json',
  JS: 'js',
  COFFEE: 'coffee',
  HTML: 'html',
  TXT: 'txt',
  CSV: 'csv',
  PNG: 'png',
  JPG: 'jpg',
  JPEG: 'jpeg',
  GIF: 'gif',
  TIF: 'tif',
  TIFF: 'tiff',
  ZIP: 'zip',
  PDF: 'pdf',
  VCF: 'vcf',
  SVG: 'svg',
  XLS: 'xls',
  XLSX: 'xlsx',
  DOC: 'doc',
  DOCX: 'docx',
  MP3: 'mp3'
});

The default encoding used is therefore utf8. To explicitly pass in the encoding as an option, you need to use raw mode

cy.fixture('sample.jar', 'binary')
  .then(Cypress.Blob.binaryStringToBlob)
  .then(fileContent => {
    cy.get('[data-cy="dropzone"]').attachFile({
      fileContent,
      filePath: 'sample.jar',
      mimeType: 'application/java-archive',
      encoding: 'binary',
      lastModified: new Date().getTime(),
    },
    { 
      subjectType: 'drag-n-drop', 
      force: true
    });
  });    

Note you need to try both subjectType values, as they trigger different events.

Here's the code that shows which shows which events are triggered with force option

export const EVENTS_BY_SUBJECT_TYPE: Record<Required<HtmlSubjectType>, string[]> = {
  [HtmlSubjectType.input]: ['change'],
  /**
   * @see https://developer.mozilla.org/en-US/docs/Web/API/DragEvent
   */
  [HtmlSubjectType.dragAndDrop]: ['dragstart', 'drag', 'dragenter', 'drop', 'dragleave', 'dragend'],
};

If you still get no action, you will need to manually trigger events, e.g chain .trigger('change') after attachFile(). Ideally you can figure out which events from the app source code.


The workaround given by abramenal is incorrect, this is the part of cypress-file-upload that handles the options parameter. If you pass fixture as a string, encoding is ignored

function getFixtureInfo(fixtureInput) {

  // Normal mode
  // fixture name and options passed separately.
  if (typeof fixtureInput === 'string') {
    return {
      filePath: fixtureInput,
      encoding: '',
      mimeType: '',
      fileName: getFileName(fixtureInput)
    };
  }

  // Raw mode
  // If you pass an object, encoding can be specified
  return {
    filePath: fixtureInput.filePath,
    encoding: fixtureInput.encoding || '',
    mimeType: fixtureInput.mimeType || '',
    fileName: fixtureInput.fileName || getFileName(fixtureInput.filePath),
    fileContent: fixtureInput.fileContent,
    lastModified: fixtureInput.lastModified
  };
}