cypressreact-dropzone

Testing react-dropzone with cypress, `isDragActive` behaves differently from real usage


I'm trying to test an application using react-dropzone. I'm using something like the following code:

    const {getRootProps, getInputProps, isDragActive} = useDropzone({onDrop, noClick: true})

    return (
        <div
            {...getRootProps()}
            aria-label='file-upload-dropzone'
        >
            <input
                {...getInputProps()}
            />
            <div>
                {(isDragActive) ?
                    <span>Drop the files here...</span> :
                    <span>Drag and drop the files here</span>
                }
            </div>
        </div>
    )

The problem here is that:

When trying to test with the following cypress test:

            cy.get('[aria-label=file-upload-dropzone]')
                .selectFile(
                    {
                        contents: Cypress.Buffer.from('file contents'),
                        fileName: 'file.e37',
                        mimeType: 'text/plain',
                        lastModified: Date.now(),
                    },
                    {action: 'drag-drop'},
                )
            // the test fails here
            cy.contains('div', /Drag and drop the files here/).should('exist')

the UI is stuck with "Drop the files here...". The reason seems to be that isDragActive never goes back to false, after cy.get(...).selectFile(...) has been called. This is different from when I test the exact same code from the browser - there, isDragActive is false AND "Drag and drop the files here" is displayed when I'm finished dragging the file.

Is there any way I can get the cypress test and a real user test to behave the same for this scenario?


Solution

  • Since you're using a hook, try adding cy.wait(0) or setTimeout(() =>{},0) before the failing line.

    This would allow the hook to complete any background action - presuming the problem is that Cypress is hogging the thread


    Triggering "change" or "drop"

    The following seems to be a working sequence of events.

    cy.get('[aria-label=file-upload-dropzone]')
      .selectFile(
        {
            contents: Cypress.Buffer.from('file contents'),
            fileName: 'file.e37',
            mimeType: 'text/plain',
            lastModified: Date.now(),
        },
        {action: 'drag-drop'},
      )
    
    cy.contains('div', /Drop the files here.../)         // passes
    
    cy.get('[aria-label=file-upload-dropzone]')
      .find('input').trigger('change', {force:true})     // without this trigger
                                                         // the next line fails
    
    cy.contains('div', /Drag and drop the files here/)   // passes
    

    I added a simple onDrop()

    const onDrop = useCallback(acceptedFiles => {
      console.log('acceptedFiles', acceptedFiles)
    }, [])
    

    and from this can see two console logs - the first has the file in acceptedFiles, the second has an empty array in acceptedFiles.