Testing with Mocha and Chai consuming values from previous tests


Testing with Mocha and Chai consuming values from previous tests



I have some tests created with mocha and chai using TypeScript, they actually work as expected. Each function returns a Promise which runs a test.


mocha


chai


TypeScript


Promise


test



My question is if is there anyway to consume on each test the value returned by a previous test without using the nesting you see below.


test


test



My concern is that if I have more test the nesting code could be very annoying going to the right


test


import * as request from 'supertest';
import app from '../src/app';
import { Promise } from 'bluebird';
import * as dateformat from 'dateformat';
import Commons from '../../utils/commons';
import { expect } from 'chai';

...
// all the functions used below are defined over here
...

registerNonExistingUser(email, pass, role).then(
(jwtToken: string) => {
authenticateUserCorrectJwt(jwtToken).then(
(user) => {
authenticateUserWrongJwt().then(
() => {
loginUserWrongCredentials().then(
() => {
loginUserCorrectCredentials(email, pass).then(
(jwtToken: string) => {
getLocalUserInfoCorrectJwt(jwtToken, email).then(
(user) => {
createTodoAsEditor(jwtToken, todoTitle).then(
(todos) => {
checkTodoExistsWithCorrectTitle(jwtToken, todoTitle).then(
(todo: any) => {
deleteTodoWithCorrectIdAsEditor(jwtToken, todo._id).then(
(todo) => {
unregisterExistingUser({
'local.email': email,
}).then(
(user) => {
// console.log(Commons.stringify(user));
}
);
}
);
}
);
}
);
}
);
}
);
}
);
}
);
}
);
}
);



Any idea on how to beautify this?



[EDIT 1]



@bhoo-day suggestion did the trick:


registerNonExistingUser(email, pass, role)
.then((_jwtToken: string) => {
return authenticateUserCorrectJwt(_jwtToken);
})
.then((user) => {
return authenticateUserWrongJwt();
})
...



Now I'm wondering if I could transform the beginning of the chain, in order to be something like the following (which I tried but doesn't work). My goal is to put every function at the same level, including the very first function:


Promise.resolve()
.then(() => {
return registerNonExistingUser(email, pass, role);
})
.then((jwtToken: string) => {
return authenticateUserCorrectJwt(jwtToken);
})
.then((user) => {
return authenticateUserWrongJwt();
})
...



[EDIT 2]



I tried the following and it works. Do you have any idea on how to simplify it?, maybe using: Promise.resolve()...?


Promise.resolve()...


new Promise((resolve) => {
it('dummy', (done) => { resolve(); return done(); });
})
.then(() => {
return registerNonExistingUser(email, pass, role);
})
.then((_jwtToken: string) => {
return authenticateUserCorrectJwt(_jwtToken);
})



Thanks!




1 Answer
1



If you use promise, you could avoid this callback hell because that is the main purpose of promise.



Some ideas to solve the issue.


// temp variable to store jwt token
let token;

registerNonExistingUser(email, pass, role)
.then((jwtToken: string) => {
token = jwtToken; // assign it so other functions can use it
return authenticateUserCorrectJwt(jwtToken)
})
.then((user) => authenticateUserWrongJwt())
.then(() => loginUserWrongCredentials())
.then(() => loginUserCorrectCredentials(email, pass))
.then((jwtToken: string) => getLocalUserInfoCorrectJwt(jwtToken, email))
.then((user) => createTodoAsEditor(token, todoTitle))
.then((todos) => checkTodoExistsWithCorrectTitle(token, todoTitle))
.then((todo: any) => deleteTodoWithCorrectIdAsEditor(token, todo._id))
.then((todo) => unregisterExistingUser({ 'local.email': email }))
.then((user) => {
// console.log(Commons.stringify(user));
});



or if you use node 7.6.0 or higher, you can use async/await. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await


async function printUser() {
try {
let jwtToken = await registerNonExistingUser(email, pass, role);
const user = await authenticateUserCorrectJwt(jwtToken);

await loginUserWrongCredentials();
jwtToken = await loginUserCorrectCredentials(email, pass);
const user = await getLocalUserInfoCorrectJwt(jwtToken, email);
const todos = await createTodoAsEditor(token, todoTitle);
const todo = await checkTodoExistsWithCorrectTitle(token, todoTitle)

const todo = await deleteTodoWithCorrectIdAsEditor(token, todo._id);
const user = await unregisterExistingUser({ 'local.email': email });

console.log(Commons.stringify(user));
} catch (error) {
// catch error here
}
}





thanks @bhoo-day, your suggestion did the trick. Do you have maybe one suggestion for the question I just added on my edition above?
– davidesp
Jul 2 at 5:19





@davidesp that is supposed to work with your Promise.resolve().then solution. Can you do breakpoint using debugger or add console.log there?
– bhoo-day
Jul 2 at 5:34


Promise.resolve().then


console.log





when using: Promise.resolve() I added a breakpoint on the first return and the debugger stops there, but at the same time the testing finalizes right away. Then when I continue the debugging, it doesn't stop on the second return (I think the execution finalized or jumps to the end). In the other, if I use your version, when it stops on the first return the testing doesn't finalize yet, the I can continue pressing F5 to jump from return to return as expected.
– davidesp
Jul 2 at 5:53



Promise.resolve()


return


return


return


F5


return


return





Perhaps we can try with return Promise.resolve().then or use done() at the last function from mocha mochajs.org/#asynchronous-code
– bhoo-day
Jul 2 at 6:04


return Promise.resolve().then


done()





I just added [EDIT 2] with one working example. Do you think we could simplify it?, please, check above. Thanks!
– davidesp
Jul 2 at 9:10






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Rothschild family

Cinema of Italy