How do I wait for an exec process to finish in Jest?

Viewed 1932

I have the following test, but I can't seem to get Jest to wait for my exec call to finish running:

var exec = require('child_process').exec

test('render', async () => {
    await exec('./render.local.sh', (err, out) => {
        console.log(err, out)
        expect(...some file to be created)
    });
})

What should I do to make jest wait for the exec callback to be called?

3 Answers

You need to call done() after your assertion.

test('render', async (done) => {
    await exec('./render.local.sh', (err, out) => {
        console.log(err, out);
        expect(...some file to be created);
        done();
    });
})

Which will mark the test to complete.

Instead of putting the test in a function with an empty argument, use a single argument called done. Jest will wait until the done callback is called before finishing the test.

test('render', done => {
    exec('./render.local.sh', (err, out) => {
        console.log(err, out);
        try {
            expect('what you want to check').toBe('expected result');
            done();
        } catch (e) {
            done(e);
        }
    });
});

If done() is never called, the test will fail (with timeout error), which is what you want to happen.

If the expect statement fails, it throws an error and done() is not called. If we want to see in the test log why it failed, we have to wrap expect in a try block and pass the error in the catch block to done. Otherwise, we end up with an opaque timeout error that doesn't show what value was received by expect(data).

According to the official Jest docs.

Another possibility I found that works with async

const util = require('util');
const exec = util.promisify(require('child_process').exec);

test('render', async () => {
    const { stdout, stderr } = await exec('./render.local.sh');

    console.log(stdout, stderr);
})  
Related