Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JEST: "Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.", despite it being already configured

Before you point it out, yes, I know this seems like a likely duplicate of multiple questions like;

  • JEST: Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout
  • Got Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout

However, I implemented all 3 fixes suggested;

  • Use jest.setTimeout() inside the test to set the async timeout
  • Use the third parameter of test() to pass in an extended async timeout limit
  • Call the done function when complete

However, when running my jest test on an automated linux machine (Jenkins), it's still throwing the same error. Also, it's worth mentioning this works fine on my MacOS machine running NodeJS v10, while the automated linux machine runs NodeJS V8.8.3 (the latest LTS version)

This is what my jest test looks like;

const webdriverio = require('webdriverio');
const options = {
    desiredCapabilities: {
        browserName: 'chrome',
        chromeOptions: {
            args: ["--no-sandbox", "disable-web-security", "--disable-dev-shm-usage"]
        } 
    } 
};
const client = webdriverio.remote(options);

beforeEach(async () => {
    await client.init();
})

test('Google Search for WebdriverIO has correct title', async (done) => {
    jest.setTimeout(30000)
    await client.url('https://www.google.com/ncr');
    await client.setValue('input[name=q]', 'WebdriverIO');
    await client.click('input[value="Google Search"]');
    const title = await client.getTitle();
    expect(title).toBe('WebdriverIO - Google Search');
    done();
}, 30000);

afterEach(async () => {
    await client.end();
});

And here is the log I get when I try to run the test;

09:57:19 > jest --config jest.config.js
09:57:19 
09:57:20 Installing selenium server ...
09:57:22 Starting selenium server ...
09:57:23 Selenium server started ...
09:57:29 FAIL jest/test/google.spec.js (5.874s)
09:57:29   ��� Google Search for WebdriverIO has correct title (5016ms)
09:57:29 
09:57:29   ��� Google Search for WebdriverIO has correct title
09:57:29 
09:57:29     Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.
09:57:29 
09:57:29       at mapper (node_modules/jest-jasmine2/build/queue_runner.js:41:52)
09:57:29 
09:57:29   ��� Google Search for WebdriverIO has correct title
09:57:29 
09:57:29     A session id is required for this command but wasn't found in the response payload
09:57:29 
09:57:29       at new RuntimeError (node_modules/webdriverio/build/lib/utils/ErrorHandler.js:143:12)
09:57:29       at RequestHandler.createOptions (node_modules/webdriverio/build/lib/utils/RequestHandler.js:121:23)
09:57:29       at RequestHandler.create (node_modules/webdriverio/build/lib/utils/RequestHandler.js:212:43)
09:57:29       at Object.url (node_modules/webdriverio/build/lib/protocol/url.js:24:32)
09:57:29       at Object.exec (node_modules/webdriverio/build/lib/helpers/safeExecute.js:28:24)
09:57:29       at Object.resolve (node_modules/webdriverio/build/lib/webdriverio.js:191:29)
09:57:29       at lastPromise.then.resolve.call.depth (node_modules/webdriverio/build/lib/webdriverio.js:486:32)
09:57:29       at _fulfilled (node_modules/q/q.js:854:54)
09:57:29       at self.promiseDispatch.done (node_modules/q/q.js:883:30)
09:57:29       at Promise.promise.promiseDispatch (node_modules/q/q.js:816:13)
09:57:29 
09:57:29 Test Suites: 1 failed, 1 total
09:57:29 Tests:       1 failed, 1 total
09:57:29 Snapshots:   0 total
09:57:29 Time:        5.988s, estimated 7s
09:57:29 Ran all test suites.
09:57:29 Killing selenium server ...

Any thoughts on why this could fail while it works fine on my local machine would be greatly appreciated. Also, I tried setting jest.setTimeout inside my Jest global setup file, but it throws jest.setTimeout is not a function;

https://github.com/facebook/jest/issues/3788

like image 591
sgarcia.dev Avatar asked Jun 26 '18 17:06

sgarcia.dev


People also ask

How do I change jest timeout?

Use jest. setTimeout(newTimeout) to increase the timeout value, if this is a long-running test." 1)Increased jest. setTimeout(30000) from 30000 to 60000.

What does jest setTimeout do?

setTimeout(timeout) Set the default timeout interval for tests and before/after hooks in milliseconds.

How do you wait in jest test?

Jest will wait until the done callback is called before finishing the test. fetchData(callback); }); If done() is never called, the test will fail (with timeout error), which is what you want to happen.


Video Answer


1 Answers

I had something similar in my tests. My tests passed fine locally but failed on GitHub Actions.

My problem was that locally, Test tools were already downloaded (in my case, in-memory MongoDB. In your case, the chrome browser), but on the remote environment, they had to download first.

Check your Jenkins logs for your environment downloading chrome, and the test fails before the download reaches 100%. Even if you don't find that, the logs you published in the question kinda hint in that direction, because the log prints out that the timeout is set to 5000ms, even though you set the timeout for the first test to a different value:

Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.

This tells me that the part of the test that timed-out, was the part before the test.

To solve this, you need to specifically add a longer timeout to the beforeEach function, where you initialize webdriver. This way, on the first test, when chrome is being downloaded, you'll get enough time to finish downloading chrome. On the next tests, this should not be an issue since chrome is already available. It's also recommended to actively download the chrome\chromium browser in Jenkins so it will be available even before the test run starts.

So, I suggest you try this:

const webdriverio = require('webdriverio');
const options = {
    desiredCapabilities: {
        browserName: 'chrome',
        chromeOptions: {
            args: ["--no-sandbox", "disable-web-security", "--disable-dev-shm-usage"]
        } 
    } 
};
const client = webdriverio.remote(options);

beforeEach(async () => {
    await client.init();
}, 30000) // <-- This is what you need. not the timeout in the actual test

test('Google Search for WebdriverIO has correct title', async () => {
    jest.setTimeout(30000); // you can keep this if you think is needed,
                            // but I'm pretty sure it's not
    await client.url('https://www.google.com/ncr');
    await client.setValue('input[name=q]', 'WebdriverIO');
    await client.click('input[value="Google Search"]');
    const title = await client.getTitle();
    expect(title).toBe('WebdriverIO - Google Search');
});

afterEach(async () => {
    await client.end();
});

Here's an example of an old run, failing because the in-memory db didn't finish downloading before the timeout. This results in the tests starting even though the database isn't ready yet for use.

After adding the timeout to my beforeEach functions, it stopped happening.

If you're still facing the problem after the suggested fix, feel free to comment on this answer. If this was the correct answer, please don't forget to mark the answer :-)

like image 198
Thatkookooguy Avatar answered Oct 22 '22 07:10

Thatkookooguy