supertest icon indicating copy to clipboard operation
supertest copied to clipboard

Add async/await examples to documentation

Open JeremyLoy opened this issue 5 years ago • 4 comments

I didn't realize until after using this library for a few days that supertest.Test (the return value for .get, .expect etc) extends Promise<Response> after a few generations of inheritance.

This means that you can do the following:

import request from 'supertest'
const response = await request.get('/').expect(200)

One key thing to note is that .end should NOT be called when using async/await

JeremyLoy avatar Jun 26 '20 17:06 JeremyLoy

Something like this make jest complains.

describe('/iam/users (GET)', () => {
        test('Return 403 if the user is not authenticated', async () => {
            expect.assertions(1)
            const response = await request(server)
                .get('/iam/users')
                .set('x-tenant', '1')

            expect(response.status).toBe(404)
        })
    })
Jest has detected the following 1 open handle potentially keeping Jest from exiting:

  ●  TCPSERVERWRAP

      37 |             expect.assertions(1)
      38 |             const response = await request(server)
    > 39 |                 .get('/iam/users')
         |                  ^
      40 |                 .set('x-tenant', '1')
      41 | 
      42 |             expect(response.status).toBe(404)

      at Test.Object.<anonymous>.Test.serverAddress (node_modules/supertest/lib/test.js:59:33)
      at new Test (node_modules/supertest/lib/test.js:36:12)
      at Object.obj.<computed> [as get] (node_modules/supertest/index.js:25:14)
      at Object.<anonymous> (test/user.e2e-spec.ts:39:18)

adrianwix avatar Oct 30 '20 14:10 adrianwix

This is a pretty big problem! A lot of people use Jest with SuperTest. But currently Jest's --detectOpenHandles doesn't work for a big chunk of its users (see here). So they're stuck with the dreaded Jest did not exit one second after the test run has completed but without any error logging or documentation. `

tgiardina avatar Nov 27 '20 18:11 tgiardina

https://github.com/visionmedia/supertest/issues/659#issuecomment-719601457

This is not because you're asing async/await, it's because you're not closing server after test finishes.

Do it like that:


let server: Server;
beforeEach(() => {
  server = app.listen();
});
afterEach(() => {
  server.close();
});

jtomaszewski avatar Apr 07 '21 23:04 jtomaszewski

there's a real issue here that can be easily addressed in the documentation... here's how I understood supertest worked in trying it for the first time:

import express from 'express'
import request from 'supertest'
describe('foo', () => {
  const app = express()
  it('bar', async () => {
    const resp = await request(app).post('/').send()
    expect(resp.status).toStrictEqual(200)
  }
}

Turns out, what I actually needed to do with my tests were this:

import express from 'express'
import request from 'supertest'
describe('foo', () => {
  const app = express()
  const server = app.listen()
  afterAll(async () => { server.close() })
  it('bar', async () => {
    const resp = await request(server).post('/').send()
    expect(resp.status).toStrictEqual(200)
  }
}

While SuperTest /appears/ to work while passing in the express app, passing in the server returned by the app.listen() method (rather than the app itself) looks to be the /right/ way.

Does this analysis ring true to anyone else?

bejoinka avatar Oct 14 '21 04:10 bejoinka