Search code examples
node.jsmocha.jssinoncompoundjssupertest

Using supertest to check didFlash after a redirect


I'm trying to test what happens when the user destroy callback receives an error for the user controller. When destroy receives an error, it does the following:

flash('error', 'Can not destroy user');
redirect(path_to.users);

This is the test so far:

it('should fail on DELETE /users/:id if destroy receives an error', function (done) {
    var User = app.models.User;
    var user = new UserStub();

    User.find = sinon.spy(function (id, callback) {
        callback(null, user);
    });

    user.destroy = sinon.spy(function (callback) {
        callback(new Error());
    });

    request(app)
        .del('/users/55')
        .end(function (err, res) {
            res.header.location.should.include('/users');
            app.didFlash('error').should.be.true;

            done();
        });
});

I've seen this question and the res.header.. portion works as expected. However, I'm still confused on how I can test the flash that happens after that redirect.


Solution

  • I ended up changing the users_controller to use the following code for a destroy callback (the redirect was having other issues):

    if (error) {
        flash('error', 'Can not destroy user');
    } else {
        flash('info', 'User successfully removed');
    }
    send(302, "'" + pathTo.users + "'");
    

    The init.js file used with mocha.js has a few pieces in it when initializing the app object (some irrelevant code was omitted):

    global.getApp = function(done) {
        var app = require('compound').createServer();
    
        app.renderedViews = [];
        app.flashedMessages = {};
    
        app._render = app.render;
        app.render = function (viewName, opts, fn) {
            app.renderedViews.push(viewName);
    
            // Deep-copy flash messages
            var flashes = opts.request.session.flash;
            for(var type in flashes) {
                app.flashedMessages[type] = [];
                for(var i in flashes[type]) {
                    app.flashedMessages[type].push(flashes[type][i]);
                }
            }
    
            return app._render.apply(this, arguments);
        };
    
        app.use(function (req, res, next) {
            app._request = req;
            next();
        });
    
        app.didFlash = function (type) {
            var flashes = app._request.session.flash;        
            return !!(app.flashedMessages[type] || (flashes && flashes[type]));
    
        };
    
        return app;
    };
    

    The original way of checking for didFlash was limited to only rendering, but this checks if a flash message is created before a redirect or send.