Code Monkey home page Code Monkey logo

cypress-upload-file-post-form's Introduction

cypress-upload-file-post-form

Solution for two Cypress testing use-cases I came across with: perform a direct http FORM request to the server containing a file and other parameters and upload a file into a form before submission. It works for excel files.

For both cases, the file to be uploaded / sent in the form will be placed in fixtures folder so it can be loaded by cypress.

To build these workarounds, I found useful these two links:

Cypress Issue #170 StackOverflow

First scenario (upload_file_to_form_spec.js):

I want to test a UI where a file has to be selected/uploaded before submitting the form.

Include the following code in your "commands.js" file within the cypress support folder, so the command cy.upload_file() can be used from any test:

Cypress.Commands.add('upload_file', (fileName, fileType = ' ', selector) => {
    cy.get(selector).then(subject => {
      cy.fixture(fileName, 'base64')
        .then(Cypress.Blob.base64StringToBlob)
        .then(blob => {
          const el = subject[0]
          const testFile = new File([blob], fileName, { type: fileType })
          const dataTransfer = new DataTransfer()
          dataTransfer.items.add(testFile)
          el.files = dataTransfer.files
        })
    })
  })

Then, in case you want to upload an excel file, fill in other inputs and submit the form, the test would be something like this:

describe('Testing the excel form', function () {
    it ('Uploading the right file imports data from the excel successfully', function() {

        const testUrl = 'http://localhost:3000/excel_form';
        const fileName = 'your_file_name.xlsx';
        const fileType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
        const fileInput = 'input[type=file]';

        cy.visit(testUrl);
        cy.upload_file(fileName, fileType, fileInput);
        cy.get('#other_form_input2').type('input_content2');
        .
        .
        .
        cy.get('button').contains('Submit').click();

        cy.get('.result-dialog').should('contain', 'X elements from the excel where successfully imported');
    })
})

Second scenario (send_form_data_with_file_in_post_request_spec.js):

I want to build up the FormData myself( new FormData(), formData.append/formData.set ) and send it directly with a POST request to the backend or submit the form with the FormData I have created.

For this case, the transmitted data must be in the same format as the form's submit(), which type is set to "multipart/form-data". Having a look at the MDN web docs to see how you can build a FormData: Using FormData Objects, and knowing that at this very moment (Cypress 2.1.0) cy.request doesn't support FormData (multipart/form-data) so we will need a XMLHttpRequest, the test can be performed as follows.

Include the following code in your "commands.js" file within the cypress support folder, so the command cy.form_request() can be used from any test:

// Performs an XMLHttpRequest instead of a cy.request (able to send data as FormData - multipart/form-data)
Cypress.Commands.add('form_request', (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);
})

Then, in case you want to send the same form as before (form containing an excel file and other plain inputs) but build it by yourself and send it directly to the server, the test would be something like this:

describe('Testing the API', function () {
     
    it('Receives valid FormData and proccesses the information correctly', function () {

        /*
        The reason why this test may look a bit tricky is because the backend endpoint is expecting the 
        submission of a web Form (multipart/form-data), not just data within a POST. The "cy.request()" 
        command doesn't support sending a web Form as a body in a POST request, so the test uses a support 
        command that has been created to perform a genuine XMLHttpRequest where a web Form can be placed.
        */

        //Declarations
        const fileName = 'your_excel_file.xlsx';
        const method = 'POST';
        const url = 'http://localhost:3000/api/excel_form';
        const fileType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
        const inputContent2 = 'input_content2';
        const expectedAnswer = '{"msg":"X elements from the excel where successfully imported"}';

        // Get file from fixtures as binary
        cy.fixture(fileName, 'binary').then( (excelBin) => {

            // File in binary format gets converted to blob so it can be sent as Form data
            Cypress.Blob.binaryStringToBlob(excelBin, fileType).then((blob) => {

                // Build up the form
                const formData = new FormData();
                formData.set('file', blob, fileName); //adding a file to the form
                formData.set('input2', inputContent2); //adding a plain input to the form
                .
                .
                .
                // Perform the request
                cy.form_request(method, url, formData, function (response) {
                    expect(response.status).to.eq(200);
                    expect(expectedAnswer).to.eq(response.response);
                });
                
            })
            
        })
        
    })
      
})

cypress-upload-file-post-form's People

Contributors

javieraviles avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

cypress-upload-file-post-form's Issues

Is there a way to change download location from cypress/downloads to Fixtures folder??

Hi I'm downloading a file from a site and uploading the same downloaded file in the same test run. But In order to upload the file, it asks me to have the file in the fixture folder.

Is there a way for me to change the default download location to fixtures and if that's not possible, how can I upload a file from my cypress/downloads folder. When I use the filepath from there, it gives me the following error:

"A fixture file could not be found at any of the following paths:

apps/mosaic-e2e/src/fixtures/.../cypress/downloads/test-non-date-based.json
apps/mosaic-e2e/src/fixtures/.../cypress/downloads/test-non-date-based.json{{extension}}

Cypress looked for these file extensions at the provided path:

.json, .js, .coffee, .html, .txt, .csv, .png, .jpg, .jpeg, .gif, .tif, .tiff, .zip

Provide a path to an existing fixture file."

Is there a way to move a file from downloads to fixtures as the test runs?? < one other way i was thinking

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.