Last active
May 2, 2023 20:31
-
-
Save ZwaarContrast/00101934954980bcaa4ae70ac9930c60 to your computer and use it in GitHub Desktop.
Using cypress with react-dropzone to upload a file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// your react component | |
import * as React from 'react' | |
import Dropzone from 'react-dropzone' | |
// apply your own styling and stuff, should probably also show the files when uploaded | |
const Upload = () => { | |
return (<Dropzone data-cy="drag-and-drop">Drag and Drop here</Dropzone>) | |
} | |
export default Upload |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// cypress test | |
describe('Test', function() { | |
it('Should be able upload', function() { | |
// upload file using drag and drop using a fixtue | |
cy.fixture('files/file.pdf', 'base64').then(content => { | |
cy.get('[data-cy=drag-and-drop]').upload(content, 'filename.pdf') | |
}) | |
// assert succesful upload and continue testing | |
}) | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Custom comand to handle uploading a file using react-dropzone | |
// Should probably be placed somewhere in /support/ | |
Cypress.Commands.add( | |
'upload', | |
{ | |
prevSubject: 'element', | |
}, | |
(subject, file, fileName) => { | |
// we need access window to create a file below | |
cy.window().then(window => { | |
// line below could maybe be refactored to make use of Cypress.Blob.base64StringToBlob, instead of this custom function. | |
// inspired by @andygock, please refer to https://github.com/cypress-io/cypress/issues/170#issuecomment-389837191 | |
const blob = b64toBlob(file, '', 512) | |
// Please note that we need to create a file using window.File, | |
// cypress overwrites File and this is not compatible with our change handlers in React Code | |
const testFile = new window.File([blob], fileName) | |
cy.wrap(subject).trigger('drop', { | |
dataTransfer: { files: [testFile] }, | |
}) | |
}) | |
} | |
) | |
// Code stolen from @nrutman here: https://github.com/cypress-io/cypress/issues/170 | |
function b64toBlob(b64Data, contentType = '', sliceSize = 512) { | |
const byteCharacters = atob(b64Data) | |
const byteArrays = [] | |
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) { | |
const slice = byteCharacters.slice(offset, offset + sliceSize) | |
const byteNumbers = new Array(slice.length) | |
for (let i = 0; i < slice.length; i++) { | |
byteNumbers[i] = slice.charCodeAt(i) | |
} | |
const byteArray = new Uint8Array(byteNumbers) | |
byteArrays.push(byteArray) | |
} | |
const blob = new Blob(byteArrays, { type: contentType }) | |
return blob | |
} |
For anyone else running into this problem, I would like to share my solution which is an amalgamation of everything suggested here.
For an image e.g. image/jpeg
, I used OP's @ZwaarContrast b64toBlob
:
cy.fixture('image_file.jpg')
.then(fileContent => {
cy.get('input[type="file"]')
.attachFile({
fileContent: b64toBlob(fileContent),
fileName: 'image_file.jpg',
mimeType: 'image/jpeg',
});
});
For a video file e.g. video/mp4
, I used Cypress's Cypress.Blob.binaryStringToBlob
to get the blob:
cy.fixture('video_file.mp4', 'binary')
.then(Cypress.Blob.binaryStringToBlob)
.then(blob => {
cy.get('input[type="file"]').attachFile({
fileContent: blob,
fileName: 'video_file.mp4',
mimeType: 'video/mp4',
encoding: 'utf8',
});
});
For a audio file e.g. .mp3
/audio/mpeg
, I also used Cypress's Cypress.Blob.binaryStringToBlob
:
cy.fixture('audio_file.mp3', 'binary')
.then(Cypress.Blob.binaryStringToBlob)
.then(blob => {
cy.get('input[type="file"]')
.attachFile({
fileContent: blob,
fileName: 'audio_file.mp3',
mimeType: 'audio/mpeg',
});
});
Lastly, for CSV files, the following worked via drag and drop:
cy.get('.dropzone').attachFile('csv_file.csv', { subjectType: 'drag-n-drop' })
I am using the following package versions:
"cypress": "^11.2.0",
"react": "17.0.2",
"react-dropzone": "^11.3.4",
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Can confirm this works with CSV files as well. Thanks!