WhoopInc / supertest-as-promised

Supercharge supertest with a promise interface

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Question - Can supertest be promisified simply using PromisifyAll?

nareshbhatia opened this issue · comments

I am wondering if there is the difference between supertest-as-promised vs. the following 3 lines of code:

var request = require('supertest');
var Promise = require('bluebird');
Promise.promisifyAll(request);

I am sure I am missing something. Would really appreciate some clarification.

Interesting question. At least this super-basic example works:

const request = require('supertest');
const Bluebird = require('bluebird');

Bluebird.promisifyAll(request);

const app = require('express')();

app.get('/', (req, res) => { res.send('Hello World'); });

describe('promisify supertest', () => {

  it('works', () => {

    return request(app)
      .get('/')
      .expect(200, 'Hello World');
  });

});

@thebearingedge that's actually default behavior shipped by SuperTest these days! For example, the following works:

describe('promisify supertest', () => {                                                                 
  it('works', () => require('supertest')('https://google.com').get('/').expect(301));                                                                 
});  

See ladjs/supertest#722 for the gory details—the tl;dr is that all Test instances have a .then() method for Promise interop. If all you want is the ability to return SuperTest instances from within a Mocha spec and have everything Just Work, you don't need this library at all (with sufficiently recent versions of Mocha and SuperTest). But if you want all the great functions that real promise objects ship with, you'll still need SuperTest as Promised:

request(app)
  .get("/kittens")
  .expect(201)
  .toPromise()
  // I'm a real promise now! You don't get .toPromise with plain ol' SuperTest.
  .delay(function (res) { /* ... */ })
  .then(function (res) { /* ... */ })

@nareshbhatia, to answer your original question, Bluebird's promisifyAll is incredibly annoying with SuperTest's API. You need to make sure to promisifyAll in exactly the right place:

var request = require('supertest')('https://google.com');
require('bluebird').promisifyAll(request.get('/'))
     .expect('Content-Type', /text/)
     .expectAsync(200)
     .then(/*...*/)

With just Bluebird, you need a call to promisifyAll for each test, and you need to always make your last assertion expectAsync instead of expect, or you won't coerce the Test instance to a promise, and the request won't ever get sent. SuperTest as Promised hides all this complexity from you.

Oh, HA! You're right. I didn't call expectAsync.
Duh. 😞
Well cool. I never remember how promisifyAll works. Apparently I never use it. Thanks for your time and knowledge, @benesch

Of course! Happy to see this library getting some use. Cheers!

@thebearingedge, @benesch - thank you for your insights. This is SuperHelpful 👍. Will start tinkering with supertest-as-promised.

P.S. BTW you folks are using node 4.0.x? How has your experience been? Do you recommend switching to it?

Awesome!

I am retired from the Node ecosystem with the exception of a few JS packages I maintain, like this one. So I am not the right person to ask for Node 4.0.x advice! I will say that I find the new => function syntax an extremely compelling reason to upgrade.

I'm loving v4 and highly recommend it. I have been wanting the ES6 features but don't want to sacrifice test speed or add complexity to testing with a compile step. If you use nvm you can try it out pretty painlessly. Cheers 🍻

I am retired from the Node ecosystem

Did I miss that the last time we talked? Where'd you go?

Systems programming, it seems! School is keeping me busy with a healthy smattering of C and OCaml.