0

Preamble: I'm aware of this question, but found no useful answers there. The accepted answer there suggests that using async and await should address the issue, but it doesn't.


I've written this test in TypeScript using Mocha and Supertest:

it('returns 400 when redirectURL is missing', async () => {
  const isAuthorized = (_req: Request) => true;
  const hooks = { onPostAuth: async (_req: Request) => {} };
  const app = createApp(isAuthorized, hooks);

  await request(app)
    .post('/')
    .set('Content-Type', 'application/json')
    .send({ }) // Body is missing redirectURL

    .expect(400);
});

When I run it, as expected the test fails:

  1) POST
       returns 400 when redirectURL is missing:
     Error: expected 400 "Bad Request", got 200 "OK"

At this point, the HTTP API looks like this:

export function createApp(
  isAuthorized: (_: Request) => boolean,
  hooks: { onPostAuth: (_: Request) => any; })
{
  const app = express();
  const authorize = createAuthorizationHandler(isAuthorized);

  app.post("/", authorize, async (req, res) => {
    const result = await hooks.onPostAuth(req);
    return res.send(result);
  })

  return app;
}

All good. I now add an if statement in the code to return 400 Bad Requst if the required property is missing:

app.post("/", authorize, async (req, res) => {
  if (!req.body.redirectURL) {
    return res.status(400).send();
  }

  const result = await hooks.onPostAuth(req);
  return res.send(result);
})

While I expect the test to pass, it now fails with this error message:

  3) POST
       returns 400 when redirectURL is missing:
     Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (C:\Users\mark\Documents\Criipto\fusebit-extensibility\tests\index.test.ts)
      at listOnTimeout (internal/timers.js:531:17)
      at processTimers (internal/timers.js:475:7)

Why does it do that, and what can I do to rectify the problem?


Actually, just reading req.body.redirectURL is enough to trigger that behaviour:

app.post("/", authorize, async (req, res) => {
  if (!req.body.redirectURL) {
  }

  const result = await hooks.onPostAuth(req);
  return res.send(result);
})

Although it doesn't do anything inside of that if statement, the test still times out and hangs, as described above.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • 1
    Could it be that `req.body.redirectURL` is throwing an error which means the rest of the code does not execute, resulting in the timeout as no response is returned? Have you correctly set up Express body parsing? – cdimitroulas Jun 24 '21 at 19:24
  • @cdimitroulas *"Have you correctly set up Express body parsing?"* Most likely not, then. I'm completely new to this ecosystem. How do I do that? – Mark Seemann Jun 24 '21 at 19:36

1 Answers1

1

Thanks to the comment from cdimitroulas, it turns out that I had, indeed, not set up Express for body parsing. Adding this:

app.use(express.json());

solved the problem.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • 1
    Glad you figured it out :) The req.body property won't exist unless you use some kind of body parsing middleware such as express.json() – cdimitroulas Jun 24 '21 at 21:11