Skip to content

robbert229/cypress-file-upload

 
 

Repository files navigation

cypress-file-upload

GitHub license npm version CircleCI Status All Contributors

File upload testing made easy.

This package adds a custom Cypress command that allows you to make an abstraction on how exactly you upload files through HTML controls and focus on testing user workflows.

Table of Contents

Installation

The package is distributed via npm and should be installed as one of your project's devDependencies:

npm install --save-dev cypress-file-upload

Usage

cypress-file-upload extends Cypress' cy command. Add this line to your project's cypress/support/commands.js:

import 'cypress-file-upload';

Now you are ready to actually test uploading. Here are some basic examples:

/* Plain HTML input */

const yourFixturePath = 'data.json';
cy.get('[data-cy="file-input"]').attachFile(yourFixturePath);

/* Drag-n-drop component */

cy.get('[data-cy="dropzone"]').attachFile(yourFixturePath, { subjectType: 'drag-n-drop' });

/* You can also attach multiple files by chaining the command */

const yourBestPicture = 'meow.png';
cy.get('[data-cy="file-input"]')
  .attachFile(yourFixturePath)
  .attachFile(yourBestPicture);

/* If your file encoding is not supported out of the box, make sure to pass it explicitly */

const weirdo = 'test.shp';
cy.get('[data-cy="file-input"]').attachFile({ filePath: weirdo, encoding: 'utf-8' });

/* If your input element is invisible or stays within shadow DOM, make sure enforcing manual event triggering */

cy.get('[data-cy="file-input"]').attachFile(yourFixturePath, { force: true });

/* If you want to overwrite the file name */

const data = 'test.json';
cy.get('[data-cy="file-input"]').attachFile({ filePath: data, fileName: 'users.json' });

/* If your file needs special processing not supported out of the box, you can pass fileContent directly */

const special = 'file.spss';
cy.fixtures(special, 'binary')
  .then(Cypress.Blob.binaryStringToBlob)
  .then((fileContent) => {
    cy.get('[data-cy="file-input"]').attachFile({ fileContent, filePath: special, encoding: 'utf-8' });
})

/* when providing fileContent is possible to ignore filePath but fileName and mime type must be provided */

const special = 'file.spss';
cy.fixtures(special, 'binary')
  .then(Cypress.Blob.binaryStringToBlob)
  .then((fileContent) => {
    cy.get('[data-cy="file-input"]').attachFile({ fileContent, fileName: 'special', mimeType: 'application/octet-stream', encoding: 'utf-8' });
})

Trying to upload a file that does not supported by Cypress by default? Make sure you pass encoding property (see API).

See more usage guidelines in recipes.

API

Exposed command in a nutshell:

cySubject.attachFile(fixture, processingOpts);

fixture is a string path (or object with same purpose) that represents your local fixture file and contains following properties:

  • {String} filePath – file path (with extension)
  • {String} fileName - (optional) the name of the file to be attached, this allows to override the name provided by filePath
  • {Blob} fileContent - (optional) the binary content of the file to be attached
  • {String} mimeType – (optional) file MIME type. By default, it gets resolved automatically based on file extension. Learn more about mime
  • {String} encoding – (optional) normally cy.fixture resolves encoding automatically, but in case it cannot be determined you can provide it manually. For a list of allowed encodings, see here

processingOpts (optional) contains following properties:

  • {String} subjectType – target (aka subject) element kind: 'drag-n-drop' component or plain HTML 'input' element. Defaults to 'input'
  • {Boolean} force – (optional) same as for cy.trigger it enforces events triggering on HTML subject element. Usually this is necessary when you use hidden HTML controls for your file upload. Defaults to false
  • {Boolean} allowEmpty - (optional) when true, do not throw an error if fileContent is zero length. Defaults to false

Recipes

Most common frontend UI setups along with Cypress & file upload testing are located at recipes.

Any contributions are welcome!

Caveats

During the lifetime plugin faced some issues you might need to be aware of:

  • Chrome 73 changes related to HTML file input behavior: #34
  • Force event triggering (same as for cy.trigger) should happen when you use hidden HTML controls: #41
  • Binary fixture has a workarounded encoding: #70
  • Video fixture has a workarounded encoding: #136
  • Shadow DOM compatibility: #74
  • Reading file content after upload: #104

It isn't working! What else can I try?

Here is step-by-step guide:

  1. Check Caveats – maybe there is a tricky thing about exactly your setup
  2. Submit the issue and let us know about you problem
  3. In case you're using a file with encoding and/or extension that is not yet supported by Cypress, make sure you've tried to explicitly set the encoding property (see API)
  4. Comment your issue describing what happened after you've set the encoding

Contributors

Thanks goes to these wonderful people (emoji key):


James Hollowell

💻

lunxiao

🐛

Oliver O'Donnell

🐛 💻

Peter Colapietro

📖

km333

🐛

Kevin Mui

💻 🤔 👀

Ben Wurth

🐛 💻

Andreev Sergey

⚠️ 💬 💡 💻

Guts

💬

maple-leaf

💬 💻

Daniel Mendalka

💬

Chris Sargent

💬

Ronak Chovatiya

💬

Jan Hesters

💬 🐛

John Molakvoæ

💬

Phil Jones

🐛

Nicolas Gehring

🐛

David Pertiller

💬 💻

Amy

🐛

Tomasz Szymczyszyn

📖

nitzel

💻

dirk

🤔

Addie Morrison

🐛

Alec Brunelle

🐛

Gleb Bahmutov

🤔

Jesse de Bruijne

📖

Justin Littman

💬

harrison9149

🐛

jdcl32

💬 💻

David Sheldrick

💻

Tom MacWright

💻

Andrew Hoddinott

💻

Eneko Rodríguez

💻

Dmitry Nikulin

💻

Thiago Brezinski

🐛

Jack

💬

Yoni Gibbs

🐛

benowenssonos

🐛

Aymeric

💬

Alfredo Sumaran

🐛

x-yuri

🤔

Tri Q. Tran

💻

Francis Chartrand

📖

This project follows the all-contributors specification. Contributions of any kind welcome!

License

MIT

Packages

No packages published

Languages

  • JavaScript 90.1%
  • HTML 9.9%