0

I am having a similar issue to Test functions cannot both take a 'done' callback, but none of the solutions are working or applicable to me: I have a test file which needs to run done() in order to setup an async test, but am getting the error:

Test functions cannot both take a 'done' callback and return something. Either use a 'done' callback, or return a promise.

Returned value: Promise {}

Because I am using jest v28.1.3.

In order to setup my environment, I run a recursive async function which looks like the following:

const iAmReady = async (done) => {
  setTimeout(async () => {
    try {
      await request.get({ uri: 'http://localhost:7575/ready' })
      done()
    } catch (err) {
      attempts += 1
      if (attempts > 10) {
        throw new Error('Failed to connect.')
      }
      iAmReady(done)
    }
  }, 500)
}

I then set this function to run in the beforeAll:

  beforeAll(async (done) => {
    await iAmReady(done)
  })

  it('test', () => {
    // test stuff
  })

Unfortunately when I pass in the done as shown here, although it works an my environment is set up I get the error I stated above.

If I don't pass in the done and remove its usage from iAmReady, the setup is ignored and done only after the tests run.

What can I do to replace the done and make this work?

theJuls
  • 6,788
  • 14
  • 73
  • 160

1 Answers1

0

Are you sure that requestlib returns a promise? I think it accepts a callback instead.

And the reason jest is complaining is that you use done and async flag at the same time. If you return the promise then do not use done. When it has async flags it's already a promise.

This code should work for you with axios

function ready(attempts = 0) {
  return axios
    .get('http://localhost:3000/api/health')
    .then(() => 'ok')
    .catch(() => {
      if (attempts > 10) return Promise.reject('failed to connect');
      const delay = attempts * 10;
      console.log(`Waiting ${delay}ms...`);
      return new Promise((resolve) => setTimeout(() => resolve(ready(attempts + 1)), delay));
    });
}

beforeAll(() => ready()); // Since it returns a promise no need async flag

p.s.

If you are using built-in http.request this is how to make it promise-based. source

n1md7
  • 2,854
  • 1
  • 12
  • 27