jest method done() is not defined - jestjs

I started using jest and I now need to test callbacks.
To know when a callback was called, the done() is supposed to be used accourding to the documentation: https://jestjs.io/docs/en/asynchronous.html
However the done() is not recognized beeing undefined and is consequently throwing this Error:
Test suite failed to run
TypeScript diagnostics (customize using `[jest-config].globals.ts-jest.diagnostics` option):
pathToErrorFile:line - error TS2304: Cannot find name 'done'.
63 done();
~~~~
//code to reproduce:
test('test', ()=>{
fkt(param, ()=>{
done();
});
});
I have setup jest with node and angular and in both projects this function does not exist.
So what I want to know is, where this function is even coming from and how I can troubleshoot it.
Note that everything else (test, describe, etc. ) is working fine done() as its exception.

done is not defined as a global var. You get it passed to the test function.
test('test', done => {
fkt(param, () => {
done();
});
});
Note that if you specify done parameter, jest will detect it and will fail the test on timeout, if the done function is not called after the test has finished.
If done() is never called, the test will fail (with timeout error), which is what you want to happen.
Then, you have to call done even if the test fails - otherwise you won't see the error.
If we want to see in the test log why it failed, we have to wrap expect in a try block and pass the error in the catch block to done. Otherwise, we end up with an opaque timeout error that doesn't show what value was received by expect(data).
See Jest - Testing Asynchronous Code

Related

Testing for an error not being thrown by an async function

I'm trying to test for an error not being thrown, and I've done the following in my test:
await expect(() => execute(1, 1)).rejects.not.toThrow()
The test fails when execute throws an error, as I want it to. However, when execute resolves successfully, I get the following test failure:
Received promise resolved instead of rejected
Resolved to value: undefined
I've previously used Jasmine for this sort of thing, and it happily does expect(() => codeThrowingError).not.toThrow(), but the syntax for Jest seems a bit more tortured and I'm not sure how to get this right.
Works great with https://stackoverflow.com/users/3001761/jonrsharpe response about doing await expect(execute(1, 1)).resolves.toEqual(expect.anything())

Can I make Chai's expect.to.not.throw synchronous?

I have a snippet of code that I'm testing in Chai and Pact. It looks something like this:
var myVerify = () => {
provider.verify().then(() => {
console.log('B verified')
done()
})
}
expect(myVerify).to.not.throw()
This works but it's a lot of extra work to go through to make a wrapper function to ensure that I wait on Pact's verify complete's before continuing on with the test. Pact has some internal state that will clear when it's done. If I just call this:
expect(provider.verify()).to.not.throw()
then it will conflict with other tests.
This code seems to work fine for me but it's very messy. Is there a simpler way to accomplish this?
I wouldn't recommend this method since if an error did in fact occur, it would never be caught anyways because promises don't "throw errors", they simply reject the promise, which you can catch using .catch or being the second parameter of the .then.
There are 2 ways of doing what you want:
Just with Mocha:
return provider.verify().then(() => {
console.log('B verified');
done();
}, () => throw new Error("B verification failed"));
In this simple example, we're not using chai to verify anything since you're not actually verifying data output of the verify, you're just checking to see if the promise was a success, if not, throw an error which will fail your tests. Mocha, by default, understands promises as long as they're returned as part of the test.
However, this method means that the wrapping it function needs to inject the done parameter, which I'm not a fan of. What I am a fan of is using:
Chai with Chai as Promised:
You need to set up Chai as Promised using
chai.use(require("chai-as-promised))
then in your tests, simply do:
return expect(provider.verify()).to.eventually.be.fulfilled;
This test will wait for the promise to return, and chai will validate that it is, in fact, fulfilled and not rejected. I find this syntax to be much simpler to use and makes writing tests simpler. You can also have multiple expects with the same promise, using Promises.all:
var verify = provider.verify();
return Promises.all(
expect(verify).to.eventually.be.fulfilled,
expect(verify).to.eventually.be.true,
);

Firebase Not Running Callbacks As Expected

I have a Firebase DB with a { hello: 'world'} at its root. Whenever I try to read hello's value in Node, the callback isn't executed unless I modify the value from within the Node process.
Here's the once call:
let callback = (snapshot) => {
console.log('The value is ', snapshot.val());
};
db.ref('hello').once('value', callback);
At this point I'd expect the callback to run and print "The value is world" printed... but nothing happens. Now say I use on instead of once. Even if I modify the value from the Firebase web console or another Node process, the callback still isn't called! The strange thing is all of this code works as expected in a browser with the same library version (v3.0.2).
The only way I've managed to execute the callback is by modifying the value directly from the same Node process.
db.ref('hello').once('value', callback);
db.ref('test').set('moon');
// => 'The value is moon.'
I've created a repository with test scripts to help replicate an debug the issue.
It turns out this is a known issue affecting certain accounts, and the Firebase team is working on it!

How to avoid timeouts in mocha testcases?

Here I am attaching my code, I am passing done callback and using supertest for request. Since I am using assert/expect in my testcase inside request.end block why I need to worry about timeout? What is mistake I am making here.
it('should get battle results ', function(done) {
request(url)
.post('/compare?vf_id='+vf_id)
.set('access_token',access_token)
.send(battleInstance)
.end(function(err, res){ // why need timeout
if (err) return done(err);
console.log(JSON.stringify(res.body));
expect(res.body.status).to.deep.equal('SUCCESS');
done();
});
});
Testcase results following response:
Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.
If I am running my testcases with mocha command then its show this error while If I am running test mocha --timeout 15000 then testcase is passing correctly. But I want to avoid timeout, How can I do that?
If I am running my testcases with mocha command then its show this error while If I am running test mocha --timeout 15000 then testcase is passing correctly. But I want to avoid timeout, How can I do that?
You can't avoid timeouts, since it looks like you're testing a remote service. If, for whatever reason, the request to that service takes a long time, you will run into timeouts.
You can tell Mocha to disable for timeout checking by setting the timeout to 0, but that's probably also not ideal because it may cause each test case to take an excessive amount of time.
As an alternative, you can mock request (which I assume is superagent) so you can control the entire HTTP request/response flow, but since it looks like you're testing a remote service (one which you have no control over) that would make this particular test case moot.
In mocha a default timeout of 2 seconds (2000ms) is set by default.
You can extend the default (global) timeout from the command line using the --timeout xxxx flag.
If you want instead to change the timeout for a specific test case you can use the this.timeout( xxxx ) function - note it does not work for arrow functions - (where xxxx is a number like 20000 representing milliseconds).
it('My test', function(){
this.timeout(5000);
//... rest of your code
});
You can also set a timeout of a set of test cases (wrapped by a describe):
describe("My suite", function(){
// this will apply for both "it" tests
this.timeout(5000);
it( "Test 1", function(){
...
});
it( "Test 2", function(){
...
});
});
It also works for before, beforeEach, after, afterEach blocks.
More documentation is available here: https://mochajs.org/#timeouts
Consider that 2 seconds is usually a good amount of time to run your tests so I would say that extend the default timeout should be an exception, not the common rule in your tests.
Also if your test is not async and you have to extend the timeout I would strongly suggest to review the function that is taking so long before extending the timeout.
Mocha : Timeouts
Test-specific timeouts may also be applied, or the use of this.timeout(0) to disable timeouts all together:
To disable the timeout from happening simply set it to 0. I use mocha <file> --timeout 0 when I'm debugging so the timeout error does not get thrown.
Here is what you need
mocha timeouts
describe('a suite of tests', function() {
this.timeout(500);
it('should take less than 500ms', function(done){
setTimeout(done, 300);
});
it('should take less than 500ms as well', function(done){
setTimeout(done, 250);
});
})

Mocha testing difference between done() and done as paramter to function

please explain difference between done() method and done keyword passed as a parameter to a function?
it("qwerty",function(done){
------
------
done();
});
it('qwerty', function(done){
----------
----------
.expect(404, done);
})
Please explain the differences and how many times i can call done() in loop
if i am calling like 15 times i am getting an error "multiple times done() called"
In the first example, you call it explicitly. In the second one, you pass done function as a callback to expect. It checks the response status (I assume you use supertest library) and if it equals to 404, calls done function without parameter (no error). Otherwise it calls done with something like an instance of assertation error, so mocha knows that this is a failed test.
As a regular callback, done is not supposed to be called multiple times. It should be called only once, denoting the end of some action, the test in your case. If you are looking for the ability to fail the test, just throw it.

Resources