Search code examples
node.jsmocha.jschaibookshelf.jschai-http

Random timeout when testing project using Bookshelf with MySQL


The first time I run my test spec all tests passes, however if I go on and run it once more it causes timeout for the tests that checks if an error is returned when the foreign key value is invalid.

Is this an error on my code or a known issue related to Bookshelf or even Mocha?

Here's my test spec:

var _ = require('lodash'),
    ModelsTaskList = require('../../models/taskList'),
    TaskList = ModelsTaskList.TaskList,
    server = require('../../index'),
    chai = require('chai'),
    chaiHttp = require('chai-http'),
    should = chai.should(),
    faker = require('faker');

chai.use(chaiHttp);

describe('TaskLists controller', function() {

    describe('/POST tasklists', () => {
        it('should not POST a tasklist without a status', (done) => {
            var wrong_tasklist = _.clone(test_tasklist);
            wrong_tasklist.statusId = undefined;

            chai.request(server)
                .post('/api/tasklists')
                .send(wrong_tasklist)
                .end((err, res) => {
                    res.should.have.status(200);
                    res.body.should.be.an('object');
                    res.body.should.have.property('error');
                    done();
                });
        });

        it('should not POST a tasklist with an invalid status', (done) => {
            var wrong_tasklist = _.clone(test_tasklist);
            wrong_tasklist.statusId = 99;

            chai.request(server)
                .post('/api/tasklists')
                .send(wrong_tasklist)
                .end((err, res) => {
                    res.should.have.status(200);
                    res.body.should.be.an('object');
                    res.body.should.have.property('error');
                    done();
                });
        });

        it('should not POST a tasklist without a user ID', (done) => {
            var wrong_tasklist = _.clone(test_tasklist);
            wrong_tasklist.createdBy = undefined;

            chai.request(server)
                .post('/api/tasklists')
                .send(wrong_tasklist)
                .end((err, res) => {
                    res.should.have.status(200);
                    res.body.should.be.an('object');
                    res.body.should.have.property('error');
                    done();
                });
        });

        it('should not POST a tasklist with an invalid user ID', (done) => {
            var wrong_tasklist = _.clone(test_tasklist);
            wrong_tasklist.createdBy = 99;

            chai.request(server)
                .post('/api/tasklists')
                .send(wrong_tasklist)
                .end((err, res) => {
                    res.should.have.status(200);
                    res.body.should.be.an('object');
                    res.body.should.have.property('error');
                    done();
                });
        });

        it('should not POST a tasklist with an estimated end date before the start date', (done) => {
            var wrong_tasklist = _.clone(test_tasklist);
            wrong_tasklist.startDate = faker.date.recent(1);
            wrong_tasklist.estimatedEndDate = faker.date.recent(2);

            chai.request(server)
                .post('/api/tasklists')
                .send(wrong_tasklist)
                .end((err, res) => {
                    res.should.have.status(200);
                    res.body.should.be.an('object');
                    res.body.should.have.property('error');
                    done();
                });
        });
    })

});

The first execution I get:

/POST tasklists ✓ should not POST a tasklist without a status (49ms) ✓ should not POST a tasklist with an invalid status ✓ should not POST a tasklist without a user ID ✓ should not POST a tasklist with an invalid user ID ✓ should not POST a tasklist with an estimated end date before the start date

And the next executions:

    /POST tasklists
      ✓ should not POST a tasklist without a status
      1) should not POST a tasklist with an invalid status
      ✓ should not POST a tasklist without a user ID
      2) should not POST a tasklist with an invalid user ID
      ✓ should not POST a tasklist with an estimated end date before the start date


  4 passing (8s)
  2 failing

  1) TaskLists controller /POST tasklists should not POST a tasklist with an invalid status:
     Error: Timeout of 4000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.


  2) TaskLists controller /POST tasklists should not POST a tasklist with an invalid user ID:
     Error: Timeout of 4000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.

And here's the code executed when POSTing to /api/tasklists:

var ModelsTaskList = require('../models/taskList'),
    TaskList = ModelsTaskList.TaskList,
    moment = require('moment'),
    ctlr;

var handleError = function (res, message) {
    res.json({
        status: false,
        tasklist: null,
        error: message
    });
};

ctlr = {

    create: function (req, res) { 
        if (req.body.statusId === undefined) {
            handleError(res, 'ID do status não informado');
        } 
        else if (req.body.createdBy === undefined) {
            handleError(res, 'ID do usuário não informado');
        }
        else if (req.body.startDate !== undefined) {
            var startDate = moment(req.body.startDate);

            if (req.body.estimatedEndDate !== undefined) {
                if (moment(req.body.estimatedEndDate).isBefore(startDate)) {
                    handleError(res, 'Data estimada de conclusão deve ser maior que a data de início');
                }
            }
        }            
        else {
            TaskList.forge(req.body)
                .save({ method: 'insert', require: true })
                .then(result => {
                    res.json({
                        status: true,
                        tasklist: result,
                        error: null
                    });
                })
                .catch(err => {
                    handleError(res, err.message);
                });
        }

    },

    read: function (req, res) {

    }
};

module.exports = ctlr;

Solution

  • It was a mistake in my code. Depending on the database condition and the data being sent, the following else if statement is not sending any response, causing the timeout:

        else if (req.body.startDate !== undefined) {
                    var startDate = moment(req.body.startDate);
    
                    if (req.body.estimatedEndDate !== undefined) {
                        if (moment(req.body.estimatedEndDate).isBefore(startDate)) {
                            handleError(res, 'Data estimada de conclusão deve ser maior que a data de início');
                        }
                    }
                    // I MISSED AN ELSE HERE
                }
    

    It was my fault.