Mocha test not running the `try..finally` clause - javascript

I am running my Node.js tests with Mocha. When I add a try..finally clause I expect that Mocha will run the finally bit after the test. It works with errors and exceptions, but not when the test times out.
The tests below show the issue in detail.
describe('try-finally', () => {
it('should run finally with an error', async() => {
console.log('starting')
try {
console.log('started')
throw new Error('Error!')
console.log('finished')
} finally {
console.log('finally!')
}
});
it('should run finally with a timeout', async() => {
console.log('starting')
try {
console.log('started')
await timeout()
console.log('finished')
} finally {
console.log('finally!')
}
});
});
function timeout() {
return new Promise(ok => {
setTimeout(ok, 10*1000)
})
}
To run the test: save into a file try-finally.js, install Mocha with npm install -g mocha and then run test with mocha --exit try-finally.js. Output:
$ mocha --exit try-finally.js
try-finally
starting
started
finally!
1) should run finally with an error
starting
started
2) should run finally with a timeout
0 passing (2s)
2 failing
1) try-finally
should run finally with an error:
Error: Error!
at Context.it (try-finally.js:9:13)
2) try-finally
should run finally with a timeout:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. /home/alex/devo/batrasio/try-finally.js)
Both tests fail; the first one runs the finally clause and displays "finally!", while the second times out (waits for 10s when the test default timeout is 2s) and does not run the finally clause.
A couple of searches on Google and here on Stack Overflow yielded nothing. What am I doing wrong? Is this even possible, or do I need to use the obnoxious beforeEach() and afterEach() functions?

The finally block will run after the contents of the try block, not necessarily the whole test. Things like errors and exceptions are meant to be caught in the try block but with a timeout, the error is thrown by mocha (so outside of your try block).
If you need to run the finally block after the test is finished and it is taking too long, you can change the default timeout by putting
this.timeout(<insert time in ms>);
inside of your it function (or the describe function if you want it to apply to everything).
If you are wanting to do the same thing after every test, then yes the afterEach() function is the way to go.

Related

JSZip generateAsync times out when run in jest

Very strange issue when I try to upgrade jest from v26 to v29.
A test executes
console.log("before fzip", JSZip.support.blob);
const fzip = await zip.generateAsync({ type: "blob" });
console.log("fzip", fzip);
If I run jest v26.6.x, it succeeds as long as I have jest-environment-jsdom v26.5.x in `package.json'
If I remove jest-environment-jsdom, the call fails (goes to catch):
error! TypeError: this._timerAPIs.setImmediate is not a function
at FakeTimers._fakeSetImmediate
If I upgrade jest and jest-environment-jsdom to v29.0.x, the call times out. I can see the first log message but not the second.
Any ideas are greatly appreciated!
Just in case someone is interested.
Apparently, JSZip.generateAsync calls setImmediate internally, so the following works:
import {setImmediate} from “timers”
…
global.setImmediate = setImmediate
(jest v27 was failing as it had an issue with setImmediate)

Pending operations in playwright on nodejs

I'm trying to get a new page at the moment of clicking on the link:
await test.step(`Step name`, async () => {
const [newPage] = await Promise.all([
context.waitForEvent('page'),
page.click('//span[normalize-space(#title)=\'Bup\']')
]);
}
And I get this page. Further operations with this instance are successful. But after 30 seconds the test ends with the following error:
Timeout of 30000ms exceeded.
Pending operations:
- browserContext.waitForEvent at "path to the file":48:21
- at <unknown>
I will assume that it is related to a promise, but I do not understand what exactly the problem is. Help is needed.
Playwright v14.0, nodejs v16.7.0.
I run the tests with the following command: npx playwright test tests/diag.spec.mjs --headed
A strange observation. When I run it in debug mode, there is no such error
:
PWDEBUG=1 npx playwright test tests/diag.spec.mjs
Ok, I found the answer, but it's a little weird. You need to increase the timeout in the playwright config:
https://github.com/microsoft/playwright/issues/8268
Also you can add test.slow() https://playwright.dev/docs/api/class-test#test-slow

Jest gives "Your test suite must contain at least one test" when certain file is imported even though there is a valid test

Whenever I import a certain file from my test file, Jest produces an error that I do not have any tests in the test file, even though there is one with just constants that should pass.
This is running inside a create-react-app folder, but I am using a global install of Jest for the server-side testing.
The Error
FAIL server/__tests__/server.test.js
● Test suite failed to run
Your test suite must contain at least one test.
at onResult (../../../../usr/lib/node_modules/jest/node_modules/#jest/core/build/TestScheduler.js:173:18)
A simplified version of the test file:
const timer = require("./timer.js");
test("should pass", () => {
expect(1 + 2).toBe(3);
});
A simplified version of timer.js:
class Timer {
constructor(ms, onCompleteFunction) {
this.ms = ms;
this.startTime = Date.now();
setTimeout(onCompleteFunction, ms);
}
}
test = () => {
let timer = new Timer(5000, () => console.log("Test Done!"));
};
test();
module.exports = Timer;
(This is a self-answer)
Before adding real testing with Jest, in the Timer.js file I had added a quick test function, just to verify that it was working without running the whole app.
Unfortunately, the function, named test, was not prefixed with var, let, or const. From what I can tell, it overrode the test function from the Jest library, and this error message was the result. When test = 1 or similar was present, the error was
TypeError: test is not a function
This is an extreme edge case due to poor coding practices and something I would have thought was a syntax error on my part, so I don't fault the error message for being unhelpful. I hope this can help someone in the future anyways.

Jest Call retries were exceeded

I have error in the following below test. My node version is : v12.10.0. is there any alternative of setTimeout?
test('demo code', async () => {
const cc = await projectSetup(project);
const onNotification = jest.fn();
cc.sendNotification();
await waitForExpect(() => {
expect(onNotification).toHaveBeenCalledTimes(2);
});
});
The Error log is as
Call retries were exceeded
at ChildProcessWorker.initialize (../../../node_modules/jest-worker/build/workers/ChildProcessWorker.js:230:21)
just add jest.useFakeTimers(); after your imports
...
jest.useFakeTimers();
test('demo code', async () => {
const cc = await projectSetup(project);
const onNotification = jest.fn();
cc.sendNotification();
await waitForExpect(() => {
expect(onNotification).toHaveBeenCalledTimes(2);
});
});
it works in my code
In my case, the actual problem was with the promise handling.
I got the same issue when I was running all my test cases in one go with the jest.
Solution:
Try running one test separately then see what error is coming.
I got the below error after running one problematic test separately where earlier I was getting the Call retries were exceeded:
[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "TypeError: Cannot read property 'code' of undefined".] {
code: 'ERR_UNHANDLED_REJECTION'
}
With this, I was sure that the problem is with the catch block and when I added it in the async service API function then the test case worked perfectly fine.
Maybe you can also try the same and see if it works for you or not.
I am using the below config:
node: 15.13.0
npm: 7.8.0
jest: 26.6.3
Try running npm doctor using the latest npm version. It's a great tool and it helped me diagnose permission and ownership issues right away.
Takeaway:
Verify File/Folder Permissions & Ownership
Encountered same error when updating the vue-jest version to below listed versions
#vue/vue3-jest: ^27.0.0-alpha.4
#vue/cli-plugin-unit-jest: ~5.0.0,
node: v17.9.0 or v16.14.2
Error disappeared, once downgraded it to node version v14.x.x
Hunch is - the latest node versions are not compatible with the dependencies.
I was able to run the test's successfully doing the following;
Install npm i -D jest-canvas-mock
Update the jest.config.ts file to have:
export default {
...
testEnvironment: "jsdom",
setupFiles: ["jest-canvas-mock"],
}

Mocha: Error Timeout of 2000ms exceeded

I am trying to seed the database for unit test.
Below is the seed.js file:
.......
const app = require('./app')
const db = app.get('db')
const saveUsersToDB = (done) => {
db.User.bulkCreate(users)
.then(() => (done))
}
module.exports = {saveUsersToDB};
My app.test.js file:
.......
const expect = require('expect')
const request = require('supertest')
const {saveUsersToDB} = require('./seed/seed');
before(saveUsersToDB)
When I run the test below is the error I get:
Express listening on port 3000!
1) "before all" hook: saveUsersToDB
0 passing (2s)
1 failing
1) "before all" hook: saveUsersToDB:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
npm ERR! Test failed. See above for more details.
I thought returning .then(() => (done)) was enough? What am I doing wrong?
By default, Mocha tests have a 2 second timeout (which means that the test needs to be completed in 2 seconds).
You can increase it (in milliseconds) as follows:
this.timeout(5000); // this test can take up to 5 seconds
https://mochajs.org/#timeouts
Because (done) will actually return the function instead of invoking it. In order to call done, you need to write it this way.
.then(() => done())
However, I don't recommend using done along with promises. You just simply need to return the promise then mocha will handle it automatically.
const saveUsersToDB = () => db.User.bulkCreate(users)
I had the same isue. This error promps because the 2 seconds timeout, so if your test needs to connect to ddbb it will most provably surpas it.
What I did was to separate all my tests that needed somme kind of connection to external resources into my integration tests folder and then added the next flag in my package.json test script:
"int-test": "mocha --timeout 15000 tests/integration/**/*.test.js --compilers js:babel-register "
Follow this link for other ways to increase the timeout: mocha timout

Categories