'How to pass in the done() parameter on an async jest test.each case

I'm trying write a jest test case that tests an async method, I want to pass in the done() parameter so jest waits for it to be fired before it ends the test, however, I'm not sure where to put it.

Any ideas?

const testcases = [
        [
            'Crew',
            [1,2,3],
            Enum.Level1
        ],
        [
            'Staff',
            [4,5,6],
            Enum.Level2
        ]
    ];
test.each(testcases )(
        'Should be able to load differing cases %p',
        (
            typeName: string,
            initalVals: string[],
            type: LevelType
        ) => {
            // some call that updates mobx store state

            when(
                () => mobxstoreProperty.length == initalVals.length,
                () => {
                    // my assertions

                    done();
                }
            );
        }
    );

For a single jest test I can do this:

test('my single test', done => {
  // some call that updates mobx store state

     when(
       () => mobxstoreProperty.length == initalVals.length,
       () => {
         // my assertions
         done();
       }
    );
});

Just unsure how to do it for when I use the test.each method.



Solution 1:[1]

I use named parameters and I can add the done() method as the last function parameter. For example like so:

const testcases: {
    typeName: string;
    initalVals: string[],
    type: LevelType
}[] = [
    {
        typeName: 'Crew',
        initalVals: [1,2,3],
        type: Enum.Level1
    },
    {
        typeName: 'Staff',
        initalVals: [4,5,6],
        type: Enum.Level2
    },
];
test.each(testcases)(
    'Should be able to load differing cases %p',
    // Must use `any` for `done`, as TypeScript infers the wrong type:
    ({typeName, initalVals, type}, done: any) => {
        // some call that updates mobx store state
        when(
            () => mobxstoreProperty.length == initalVals.length,
            () => {
                // my assertions

                done();
            }
        );
    }
);

I haven't tested if you can just add the done() method as last parameters with array arguments, but maybe that works, too.

Solution 2:[2]

to pass and evaluate done, the done callback should be very last argument in the function for test case arguments.

also, here's how to deal with typings, when you use the test.each method in typescript:

// found at https://github.com/DefinitelyTyped/DefinitelyTyped/issues/34617

it.each<number | jest.DoneCallback>([1, 2, 3])(
    'dummy: %d',
    (num: number, done: jest.DoneCallback) => {
        done();
    },
);

Solution 3:[3]

There is no perfect answer at the moment, as there is an issue in the Jest library with the templated types of test.each()

So for now, all solutions to achieve what you want, require to do some tricks with the types.

A solution for complex test parameters, with the light array syntax definition:

test.each<any>([
  ["Crew", [1, 2, 3], LevelType.Level1],
  ["Staff", [4, 5, 6], LevelType.Level2],
])(
  "Should be able to load differing cases %p",
  (
    typeName: string,
    initalVals: string[],
    type: LevelType,
    done: jest.DoneCallback
  ) => {
    // some test code
  }
);

The trick in this solution is the use of test.each<any> that bypasses the templated type issue.

The use of the any type is not the best, so I'm waiting for a library update.

For more information, see the opened issues https://github.com/DefinitelyTyped/DefinitelyTyped/issues/34617 and https://github.com/facebook/jest/issues/8518

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 schemar
Solution 2 voznik
Solution 3