ladjs / supertest

🕷 Super-agent driven library for testing node.js HTTP servers using a fluent API. Maintained for @forwardemail, @ladjs, @spamscanner, @breejs, @cabinjs, and @lassjs.
MIT License
13.75k stars 758 forks source link

Feature: chaining #14

Closed hunterloftis closed 10 years ago

hunterloftis commented 12 years ago

It would be awesome to be able to do this:

request(app)
  .get('/signin')
  .expect(200)
  .post('/signin')
  .send({ user: 'foo', pass: 'bar' })
  .expect(200)
  // ...etc...
tj commented 12 years ago

hmm yeah maybe, but at that point they should probably be in separate cases since you're describing multiple behaviours

hunterloftis commented 12 years ago

Frequently, but not always. Just came up because I've got something like this:

describe('user controller' ...
  describe('landing page' ...
    it('should redirect to dashboard if the user is logged in' ...
      // would be awesome to go through a quick login process here without having to add a bunch of extra steps, in-line with the response test.
tj commented 12 years ago

ah, yeah hmm, personally I try to do something like beforEach(user.login) and then the regular test instead of inlining a bunch of stuff

hunterloftis commented 12 years ago

hmm, I could do something like that. Do you just write some named functions and use them in multiple places?

function loginUser(done) {
  // ...
}

before(loginUser);
it('should redirect a logged-in user' ...
// ...
describe('signin' ...
  it('should authenticate a user with valid credentials', loginUser);
hunterloftis commented 12 years ago

Also - any way to get supertest to work with sessions / store cookies? Or is that entering the realm of something like zombie?

stereosteve commented 12 years ago

+1 for a cookie session example. Haven't found a way yet to test authenticated actions with supertest

hunterloftis commented 12 years ago

I've got a pull request in for this right now:

https://github.com/visionmedia/superagent/pull/110

working with authenticated actions: https://github.com/hunterloftis/superagent

emostar commented 12 years ago

@stereosteve This is a quick hack, but to get cookie support you can do something like this:

   describe('for logged in user', function() {
      var cookie

      beforeEach(function(done) {
        request(app)
          .post('/auth/login')
          .send(fixture.User.test)
          .expect(200)
          .end(function(err, res) {
            cookie = res.headers['set-cookie']
            done()
          })
      })

      it('should get a token', function(done) {
        request(app)
          .get('/token')
          .set('cookie', cookie)
          .expect(200, done)
      })
    })
Rafe commented 12 years ago

+1 for a better way to keep cookie between requests

donpark commented 11 years ago

+1 for cookie support not only between requests from:

  1. same instance of supertest
  2. between instances of supertest

Second use-case is to support unit tests that creates new instance of app per test since instance of supertest appears to be app instance specific.

em-cliqz commented 11 years ago

Perhaps just the "agent()" functionality from superagent should be exposed via supertest.

Hoverbear commented 11 years ago

+1 I'd also like to see this.

stereosteve commented 11 years ago

@em-cliqz you can indeed use agent with supertest for cookie support:

var request = supertest.agent(server)

With this I don't have any need for "chaining"

Hoverbear commented 11 years ago

@stereosteve That's exactly how I solved my need for cookies.

tj commented 11 years ago

haven't really wanted this until now, this is lame:

it('should cascade properly', function(done){
    var app = koa();
    var a = koa();
    var b = koa();
    var c = koa();

    a.use(function(next){
      return function *(){
        yield next;
        if (!this.body) this.body = 'foo';
      }
    });

    b.use(function(next){
      return function *(){
        yield next;
        if (!this.body) this.body = 'bar';
      }
    });

    c.use(function(next){
      return function *(){
        yield next;
        this.body = 'baz';
      }
    });

    app.use(mount('/foo', a));
    a.use(mount('/bar', b));
    b.use(mount('/baz', c));

    request(app.listen())
    .get('/')
    .expect(404)
    .end(function(err){
      if (err) return done(err);

      request(app.listen())
      .get('/foo')
      .expect('foo')
      .end(function(err){
        if (err) return done(err);

        request(app.listen())
        .get('/foo/bar')
        .expect('bar')
        .end(function(err){
          if (err) return done(err);

          request(app.listen())
          .get('/foo/bar/baz')
          .expect('baz', done);
        });
      });
    });
  })

haha

Hoverbear commented 11 years ago

That's some gorgeous code right there @visionmedia... I had something that looked similar.

gjohnson commented 10 years ago

Maybe one day haha... This would require a bit too much refactoring now. :-) However, for those that are interested, @hunterloftis's .agent() is exposed in supertest these days.

piranna commented 6 years ago

Has there been any improvement regarding chaining? I'm having a similar code than @tj and I think it would be useful to be able to chain requests if you need to do several of them without needed to check for failure for each of them but instead doing so globally... :-/