Jest's `it.each()` description to render arrow function source code when referred as $predicate

11,251

When you use the tagged template literal version for the table parameter of it.each, jest is using the pretty-format library behind the scenes to generate the title from the test data (if the test data is not a primitive type).

Unfortunately for your purposes, the pretty-format library does not seem to use the toString method from functions in order to format them.

As an alternative solution, you can use the array version for the table parameter:

it.each([
    [ [1, 2], [1, 2, 3], (l, r) => l === 1 ],
    [ [1, 2], [1, 2, 3], (l, r) => r === 2 ],
    [ [2, 3], [1, 2, 3], (l, r) => r === 3 ],
    [ [2, 3], [1, 2, 3], (l, r) => l + r === 5 ],
    [ [undefined, undefined], [1, 2, 3], (l, r) => l === r ],
])
('should return %p for %p and %s', (expected, array, predicate) => {
    expect(findPairwise(array, predicate)).toEqual(expected);
});

Note that I have changed the order of the parameters so that the expected value is on the first place. That's because the mapping between the test data and the placeholders in the title is based on order in the array version of table for it.each.

Share:
11,251
Igor Soloydenko
Author by

Igor Soloydenko

24/7: Loving husband, Dog friend, Critic Software Developer C# and TypeScript code reviewer @ CR.SEm

Updated on June 04, 2022

Comments

  • Igor Soloydenko
    Igor Soloydenko almost 2 years

    Problem definition

    Jest allows the test case's data to be used in it.each's name via $-prefixed variables.

    The code below results in the output like this:

     PASS  src/array-functions/find-pairwise.spec.ts
      findPairwise
        √ should return [1, 2] for [1, 2, 3] and [Function anonymous] (7ms)
        √ should return [1, 2] for [1, 2, 3] and [Function anonymous] (1ms)
        √ should return [2, 3] for [1, 2, 3] and [Function anonymous]
        √ should return [2, 3] for [1, 2, 3] and [Function anonymous] (1ms)
        √ should return [undefined, undefined] for [1, 2, 3] and [Function anonymous]
    
    Test Suites: 1 passed, 1 total
    Tests:       5 passed, 5 total
    Snapshots:   0 total
    Time:        4.061s
    Ran all test suites related to changed files.
    

    As you can see, the $expected and $array variables are rendered in human-friendly form (basic JavaScript arrays, in this case). However, the $predicate shows a generic text [Function anonymous] instead of it's actual code. I know that both regular functions and arrow functions in JS can expose their source code if you call .toString() on them. Is there a way to instruct Jest render the result of that toString() call? I did try $predicate.toString() and $(predicate.toString()) but neither of them worked.

    enter image description here

    Code

    import { findPairwise } from './find-pairwise';
    
    describe(findPairwise.name, () => {
      it.each`
        array        | predicate                                | expected
        ${[1, 2, 3]} | ${(l: number, r: number) => l === 1}     | ${[1, 2]}
        ${[1, 2, 3]} | ${(l: number, r: number) => r === 2}     | ${[1, 2]}
        ${[1, 2, 3]} | ${(l: number, r: number) => r === 3}     | ${[2, 3]}
        ${[1, 2, 3]} | ${(l: number, r: number) => l + r === 5} | ${[2, 3]}
        ${[1, 2, 3]} | ${(l: number, r: number) => l === r }    | ${[undefined, undefined]}
      `
      ('should return $expected for $array and $predicate', ({ array, predicate, expected }) => {
    //                                         ^^^^^^^^^^
    //                                         ||||||||||
    //                                         I'd like this to be rendered
    //                                         as the code of the arrow function.
    //                                         E.g. "(l: number, r: number) => l === 1"
    //                                         ...or something close to it.
    
        expect(findPairwise(array, predicate)).toEqual(expected);
      });
    });