How can you chain supertest requests when one is dependent on the other?

11.9k Views Asked by At

So right now the output is:

Warning: superagent request was sent twice, because both .end() and .then() were called. Never call .end() if you use promises
Warning: .end() was called twice. This is not supported in superagent
GET /api/things 200 3.009 ms - 2414
superagent: double callback bug
WARNING

The thing is, I need the res object that I get back from calling .end() in order to test the ETag functionality. It never goes into the second .end() and doesn't print out that console log.

The innermost .catch(done) is the one that's being called.

it('should return things', done => {
  const promises = [];

  promises.push(Thing.create(testThing));
  promises.push(Thing.create(testThing));

  Promise.all(promises)
    .then(things => {
      request(app)
        .get('/api/things')
        .expect(200)
        .end((err, res) => {
          const etag = res.get('ETag')
          if (err)
            return done(err);
          request(app)
            .get('/api/things')
            .set('If-None-Match', etag)
            .expect(304)
            .end((err, res) => {
              console.log('are we able to make it back here?');
              expect(err).to.not.exist;
              expect(res.body.data).to.be.undefined;
              expect(res.get('ETag')).to.be.equal(etag);
              return done(err);
            })
        })
        .catch(done);
    })
    .catch(done);
});
});

Does anyone have any ideas on why this might be happening, and how to go about testing such a thing?

2

There are 2 best solutions below

1
On BEST ANSWER

I figured it out, I was doing the following:

if (req.header('If-None-Match') === allThingsEtag) {
    // dont send allThings
    res.status(304);
}

I needed to actually set the body of the response so it knew to return it, like so:

if (req.header('If-None-Match') === allThingsEtag) {
    // dont send allThings
    res.status(304);
    res.json();
}

I know this is incredibly specific to my case, but in the off chance that anyone runs into this as well, that's the solution I had to come up with. So maybe check your api code.

In order to get around the .end() being called twice problem, I changed my tests to use .then().

0
On

Wasted 1 hour on this.

Official documentation is not very good:
https://www.npmjs.com/package/supertest

Below worked correctly:

let request = require("supertest");
var assert = require("assert");
// const chai = require("chai");                     // can be chai instead of assert

describe("Run tests", () => {
  request = request("http://localhost:3001");        // must be here

  it("get", async () => {

    request
      .get("/")
      .expect("Content-Type", /json/)
      .expect(200)
      .then((response) => {                          // must be then, not a callback
        assert(response.body.data !== undefined);
      })
      .catch((err) => {
        assert(err === undefined);
      });

  });

});