ladjs/supertest

How to Persist a request (with cookies, ie sessions) Like super-agent

Opened this issue Β· 15 comments

To access some urls in application, one must login first. I must go back to use super-agent to unit test these urls. Can supertest do thing like this?

server = require './testServer'
request = require 'superagent'

r = request.agent()
server.start 3002

fakeUser = 
  username:'tj',
  password:'foobar'

describe 'after login', ->
      beforeEach (done)  ->
        r
          .post("http://localhost:3002/login") 
          .send(fakeUser) 
          .end (err, res) ->
            assert res.statusCode is 200
            done()

      it 'can show restricted page', (done) ->
         r
          .get("http://localhost:3002/restricted")
          .end (err, res) ->
             assert.include res.text,'Wahoo!'
             assert res.statusCode is 200
             done()

@FZX As discussed in #26, it seems supertest has no support for agent yet.

Though not optimal at all, here's how I dealt with the case :[

describe "Login", ->

  # Login first
  beforeEach ( done )->

    @agent = superagent.agent()
    request( app ).post( '/login' )
      .send( { username: 'myname', password: 'secur1ty' } )
      .end ( err, res ) =>
        @agent.saveCookies( res )   # Store cookies to `@agent`
        done()


  # Now you can test :)
  describe 'GET /admin/articles', ->

    beforeEach ( done )->

      req = request( app ).get( '/admin/articles' )
      @agent.attachCookies( req )  # Attach cookies (session info) to the request
      req.end ( err, res )=>
        @res = res
        done()

    it 'should render Hello', ->

        @res.should.have.status( 200 )
        @res.text.should.include( 'Hello' )

@mnmly,thank you very much, your code is very helpful!

@mnmly Best method I've seen so far to get the niceties of both supertest and superagent. Thx.

@mnmly Login session without the agent https://gist.github.com/joaoneto/5152248

@joaoneto this is much better and cleaner πŸ‘

vjpr commented

Would be really great if this got resolved - such a common use case.

vjpr commented

Using @mnmly approach you can then monkey patch supertest and chain on the agent.

supertest = require('supertest')
supertest.Test::agent = (agent) ->
  agent.attachCookies @
  return @

request.post('/api/collections').agent(@agent).send(...).expect(200).end ...

neither the agent nor cookies solution seems to work with express 3.2.6.

Ah, the cookies solution works fine if I set the Cookie header instead of the cookies property.

req.set( 'Cookie', cookies )

thanks @timmywil, it's weird, but really works!

var supertest = require('supertest');
var app = express();

var agent = supertest.agent(app);

// then you can persist cookie

For the records, full example for @alsotang suggest:

(this is a login form, not an API request)

var supertest = require('supertest');
var app       = require('../path_to_my/app')
var agent     = supertest.agent(app);

describe('Login', function () {
  it('should login superadmin', function(done) {
    agent
      .post('/login')
      .type('form')
      .send({ email: 'email' })
      .send({ password: 'password' })
      .expect(302)
      .expect('Location', '/')
      .expect('set-cookie', /connect.sid/)
      .end(function(err, res) {
        if (err) return done(err);
        agent.saveCookies(res);
        return done();
      });
  };
});

In my case,
agent.saveCookie(res); (version 1.x)

was smoothly replaced by

agent.jar.setCookie(res.headers['set-cookie'][0]);(version 2.x)

For the records, full example for @alsotang suggest:
You don't need do anything more with the agent.

var supertest = require('supertest');
var agent     = supertest.agent('localhost/api');

describe('Login', function () {
  it('should login superadmin', function(done) {
    agent
      .post('/login')
      .type('form')
      .send({ email: 'email' })
      .send({ password: 'password' })
      .expect(302)
      .expect('Location', '/')
      .expect('set-cookie', /connect.sid/)
      .end(function(err, res) {
        if (err) return done(err);
        // agent.saveCookies(res); donβ€˜t need this line 
        return done();
      });
  };


it('get user info', function(done) {
// don't need do anything with cookies, agent will  attached cookies automatically based on login above
    agent
      .get('/userinfo')
      .expect(200)
      .end(function(err, res) {
        if (err) return done(err);
        return done();
      });
  };
});