Search code examples
node.jsvue.jsmocha.jsform-datasupertest

Request body is undefined when submitting Form Data object using supertest


I have a web application in Vue which talks with a REST API written in NodeJS. In the web application, user can submit a file aside with it's information. The web passes this information to the backend using the REST API. The code in the web side:

var formData = new FormData();
formData.append("number", this.number);
formData.append("file", this.file);
// More fields inside the Form Data object

this.$http.post('http://localhost:8081/api/new',formData,{emulateJSON: true},{
    header:{ "Content-Type":"multipart/form-data" },
}).then(function(response) {
    if (response.status == 200) {
        this.handleClose();
    } else {
        console.log("Failed to submit new report");
    }
}).catch((err) => {
    console.log("Failed to submit new report");
});

In the backend side, I have:

const router = require('express').Router();

router.post('/new', function(request, response) {
  console.log("New Report");
  console.log(request.body);

  var info = {
    "number": request.body.number,
    // More fields
  };
  var file = request.files.file;

  // More Code
  
});

It works great but now I want to create tests for the REST API. I have the following code:

const chai     = require('chai');
const nock     = require('nock');
const FormData = require('form-data');
const request  = require('supertest');

run_new_report_test: function(server) {
    describe('Test: New report check', function() {
        it('should return status 200', function(done) {
            var formData = new FormData();
            formData.append("number", "55555");
            // More fields
            request(server)
                .post('/api/new')
                .set("Content-Type", "multipart/form-data")
                .attach(formData)
                .expect(200)
                .end(function(err, res) {
                    expect(err).to.equal(null);
                    expect(res.body).to.be.an('object').that.is.not.empty;
                    expect(res.body.message).to.be.equal('success');
                    done();
                });
        });
    });
},

But when I run the test using mocha, I get:

New Report
undefined

For some reason request.body is undefined. I don't understand where the FormData fields are located in request. Why it works when I make a request from the web but not from the test?


Solution

  • instead of form-data, you need to use .field(for req.body), and .attach(for file) methods. check the docs: https://visionmedia.github.io/superagent/#multipart-requests

    also, you can mock file with buffer, you need to add some file info as well, try this:

    describe('Test: New report check', function() {
    
        it('should return status 200', function(done) {
    
            const testFile = 'test file';
    
            request(server)
                .post('/api/new')
                // add each filed for req.body
                .field('number', '99999')
                // mock file
                .attach('file', Buffer.from(testFile, 'utf-8'), {
    
                    // add file info accordingly
                    filename: 'file.txt',
                    contentType: 'text/plain',
                    knownLength: testFile.length
    
                })
                .expect(200)
                .end(function(err, res) {
                    expect(err).to.equal(null);
                    expect(res.body).to.be.an('object').that.is.not.empty;
                    expect(res.body.message).to.be.equal('success');
                    done();
                });
        });
    });