Jest: is it possible to loop its in Jest

Created on 6 Sep 2016  路  21Comments  路  Source: facebook/jest

Do you want to request a _feature_ or report a _bug_?
feature

What is the expected behavior?
is it possible to loop its in Jest

describe('...', () => {
    // first way
    for (let test in tests) {
        it('...', () => {
            expect(...).toBe(...)
        })
    }
    // second way
    tests.forEach((test) => {
        it('...', () => {
            expect(...).toBe(...)
        })
    })
})

Most helpful comment

yes it is, just do it like you wrote.

All 21 comments

yes it is, just do it like you wrote.

but I got this error: JavaScript heap out of memory

const testcases = require('./testcases.data') // it's JSON
describe('...', () => {
    testcases.forEach((test) => {
         it('...', () => {
             expect(...).toBe(...)
         })
    })
})

screen shot 2559-09-06 at 16 51 03

that means it is very likely you have an infinite loop somewhere and node just crashes.

Thank @cpojer maybe I do thing wrong

You don't get the before/after hooks making tests dynamically for some reason. I'm guessing the dynamic functions are out of scope.

@cpojer is it also doable with forEach? I'm encountering a race to the finish situation

I have a beforeAll() that fetches info from a local API endpoint.

the it() inside my forEach seems to sometimes run before the done() is called in the beforeAll()

What you can't do unfortunately is create tests dynamically where you have to do some async setup work, eg:

const createTest = async (config) => {
   const foo = await api(config.url)

   for (let test in config.tests) {
        it('...', () => {
            expect(...).toBe(...)
        })
    }
}

createTest(config)

That would work if there was no async/await.

I am running into the same problem with Puppeteer and Jest.

I just ran into this same issue. My setup needs to be async, but I guess jest needs to discover all the it blocks ahead of time

The same here, we need to call beforeAll to upload a files to S3 bucket. However, a dynamically created it(...) is called before result from beforeAll resolves.

All describes, its and tests must be defined synchronously. Doing async work in hooks is possible though, and to use that inside tests. You cannot use it to _define_ tests, though.

Neither for loop nor forEach are working. Jest is not able to see any test!

fs.readdir('./testingImages/', async (err, images) => {
    if (err) {
      throw err;
    }
    for (const image in images) {
      if (image) {
        const imagePath = './testingImages/' + image;
        it(`convertor should validate the image ${image}`, async () => {
          const convert: any = await imageConvertor(imagePath);
          expect(typeof convert).toBe('string');
          fs.unlinkSync(convert); // clean up
        });
      }
    }
  });

Jest error:

Your test suite must contain at least one test.

@thymikee OK, so there is no way then?

There's always a way! You have at least 2 options:
1) generate tests based on the testingImages/ using a script.
2) put everything in one test statement

I lean towards 1) because it will result in better test parallelization, while solution 2) will always run tests one-by-one

@thymikee can you give me a small example of the first 馃榿

No time for that. I'm sure you'll figure it out :)

You can use fs.readdirSync as well, that should be possible

@thymikee I did it 馃槇
@SimenB Thanks!

@A-Atrash Care to share your solution to dynamically creating tests?

Dirty hack:

Run your tests via runCLI. Before the call you can do you async requests and wait for it. Then you pass in a static data to you Jest config as global:

test.ts

import {runCLI} from 'jest';
import projectConfig from '../../../jest.config.js';

export const test = async (specs: string) => {
        // Do your async preparation
        const requests = await dereference(specs);
        // Run jest
        const result = await runCLI({
            ...projectConfig,
            globals: JSON.stringify({requests}) // <--- Here we pass it in
        }, [join(__dirname, '../project/root/')]);
}

mydynamic.test.ts

// Write your test
describe(`Test endpoints of ${specsPath}`, () => {
    // @ts-ignore
    const requests = global.requests; // <--- Here you go. Your async data
    for (const request of requests) {
        it(`${request.method} ${request.path}`, async () => {
             // Yeah, now you can access even everything initialized in beforeAll() :-)
        });
    }
});


Was this page helpful?
0 / 5 - 0 ratings