Search code examples
expressmocha.jssupertestnode-asyncsuperagent

mocha and supertest.agent not working as expected


I'm trying to write some tests where I need to authenticate first. If I make multiple requests in "before()" I get connection refused. If I split it between "before()" and "it()" it works but I cannot acheive what I want.

Code I want to work:

var agent = request.agent(myExpressApp),
      token;
    before(function(done) {
      async.series([
        function(cb) {
          agent
            .post('/1/auth/login')
            .send({
              email: 'john@smith.com',
              password: 'j0hn_Sm1TH'
            })
            .expect(200)
            .end(cb);
        }, function(cb) {
          agent
            .get('/1/auth/authorize')
            .query({
              response_type: 'token',
              client_id: 'some id',
              redirect_uri: 'http://ignore'
            })
            .expect(302)
            .end(function(err, res) {
              /* console.log(arguments) = { '0': 
                { [Error: connect ECONNREFUSED]
                  code: 'ECONNREFUSED',
                  errno: 'ECONNREFUSED',
                  syscall: 'connect' } }*/
              if (err) return cb(err);
              cb();
            });
        }
      ], done);
    });
    it('some authenticated task', function(done) {
      // do something else
      done();
    });

Code that is working:

var agent = request.agent(myExpressApp),
      token;
    before(function(done) {
      async.series([
        function(cb) {
          agent
            .post('/1/auth/login')
            .send({
              email: 'john@smith.com',
              password: 'j0hn_Sm1TH'
            })
            .expect(200)
            .end(cb);
        }, function(cb) {
          cb();
        }
      ], done);
    });
    it('some authenticated task', function(done) {
      agent
        .get('/1/auth/authorize')
        .query({
          response_type: 'token',
          client_id: 'some id',
          redirect_uri: 'http://ignore'
        })
        .expect(302)
        .end(function(err, res) {
          if (err) return done(err);
          done();
        });
    });

Solution

  • You have encountered issue 153 with superagent. Annoyingly and magically, superagent looks at the arity of the callback function you pass to it. If the function is declared accepting 2 arguments, superagent conforms to the node convention of (error, result), however, if the callback function looks like it expects any other number of arguments (zero in the case of use with async.js), it invokes the function as just callback(res) which I guess TJ thought would be nice for the browser, but for node it totally breaks convention.

    The exact line of code in question is here