hello i have a question when i test my route the test don't execute the code present in the .then part I don't understand why i am testing with jest someone knows a solution ?
let mail = require('../models/M_Email')
mail.createGen(req.body.UserVerifMailGen, listUserstarget, listOptMailGen, listOpnMailGen)
.then(result => {
console.log("on est dans then")
//req.session.success = 'Ajout alerte réussie'
res.redirect('/genMail')
})
.catch(e => {
res.json('Erreur: ' + e)
})
someone knows something ?
Related
I started working with NodeJS a couple weeks ago. I am wondering what is the best way to handle errors in NodeJS?
Right now, I am doing it in all my controllers methods. For example:
exports.myMethod = async (req, res, next) => {
try {
// My method operations here
} catch(err) {
const email = new Email(); // This is a class that I create to notify me when an error happens. errorEmail(mailBody, mailSubject)
await email.errorEmail(err, "Email Subject - Error");
}
}
Is it a good way? I mean, is there a better/more efficient way to handle errors in NodeJS?
Thanks
Error handling when using Promises (or async/await) is pretty straight forward. You don't want to have lots of duplicates of error handling code and extra try/catch blocks all over the place.
The way I find best is to put the error handling at the highest possible level (not deep in the code). If an exception is thrown, or a Promise rejects, then the failure will percolate up to the point where you catch it and handle it. Everything in between doesn't have to do that if it's handled once at the appropriate place.
So your code can start looking cleaner like this:
// module #1
exports.myMethod = async () => {
// My method operations here
return result;
}
// module #2
exports.anotherMethod = async () => {
const result = await module1.myMethod();
// do more stuff
return anotherResult;
}
// module #3
exports.topMethod = () => {
module2.anotherMethod()
.then((res) => {
console.log("all done", res);
})
.catch((err) => {
const email = new Email(); // This is a class that I create to notify me when an error happens. errorEmail(mailBody, mailSubject)
email.errorEmail(err, "Email Subject - Error")
.then(() => console.log("done, but errors!", err);
});
}
The nice thing here is that the only place I have to add extra error handling is way at the top. If anything deep in the code fails (and it can get much more deep) then it will just return up the chain naturally.
You are free to put .catch statements anywhere in between for doing retries, or to handle expected errors quietly if you want, but I find using .catch is cleaner that wrapping sections of code with try/catch blocks.
I'm trying to build an automatic error reporting system for my meteor app but there is one little thing I'm not able to do right now. I would like to know if it is possible to create some sort of wrapper that would execute each time a helper or an event is called, for any template.
I've searched in blaze.js to see how they handle it and possibly edit it but I guess altering this file is not the way to go.
I found nothing about that, and at this point, I'm not sure it is even possible.
EDIT: I found some sort of a solution but it's far from perfect.
I've created a globalHelper :
Template.registerHelper('checkError', (tmplName, helperName, ...args) => {
try {
return Template[tmplName].__helpers.get(helperName).apply(this, args);
} catch(error) {
let trace = error.stack.split('\n').map(function (line) { return line.trim(); })
let obj = {
text: "" + error,
date: parseInt(Date.now() / 1000),
function: trace[0].split('#')[0],
template: tmpl,
trace: trace.slice(0, trace.length - 1)
}
Meteor.call("logNewCrash", obj, function(err, res) {
if (!err) {
Bert.alert("Une erreur est survenue et à été communiquée à un administrateur. Elle sera traitée dans les plus brefs délais.", "danger");
}
})
}
});
It works as expected but I need to call this helper instead of the original ones, for exemple :
<template name=templateName1>
{{#if checkError 'templateName1' 'helperName1' arg1 arg2}}
<!--do something-->
{{/if}}
</template>
with the following helper :
helperName1(arg1, arg2) {
if (arg1 == arg2)
return true;
return false;
}
EDIT 2 :
So I dropped my previous work to create a meteor package.
I successfully overrode Blaze._wrapCatchingExceptions like so :
Blaze._wrapCatchingExceptions = function (f, where) {
if (typeof f !== 'function')
return f;
return function () {
try {
return f.apply(this, arguments);
} catch (error) {
let trace = error.stack.split('\n').map(function (line) { return line.trim(); })
let obj = {
text: "" + error,
date: parseInt(Date.now() / 1000),
function: trace[0].split('#')[0],
template: Template.instance().view.name.split('.')[0],
trace: trace.slice(0, trace.length -1)
}
Meteor.call(configuration.method, obj, function(err, res) {
if (!err) {
Bert.alert(res.msg, "danger");
}
});
Blaze._reportException(error, 'Exception in ' + where + ':');
}
};
};
However, some errors aren't handled by Blaze but by Tracker. This is where it's getting frustrating, I can't get my Tracker override to work.
I tried to override Tracker._runFlush and _throwOrLogbut either I got a Maximum stack size exceeded or my function is just not called at all.
I probably was doing it wrong.
What am I missing ?
Thanks
I want to stop a whole describe of JEST without throwing an error or stoping the other describes.
Im writing e2e test for my app with JEST and PUPPETEER, I write the test in a way every DESCRIBE its a flow of the path and every IT its a step, inside a IT I want to stop the flow if the pages dont match some conditions.
describe('Book a Room', ()=> {
it ('enter on main page' async() => await mainPage.navigateToMainPage())
it('go to book room page', async() => await bookRoomPage.navigateToBookRoomPage())
// The function its inside the "bookRoomPage"
it('check if the user can book room', () => {
if (!page.userCanOpenARoom()) {
// DONT EXECUTE THE NEXT IT BUT CONTINUE WITH THE OTHER DESCRIBE
}
})
it('go to book preview...', async() => bookRoomPreviewPage.navigateToBookRoomPreviewPage());
// REMAINING FLOW
})
I already try with process.exit(0) but exit the whole process
You can try out what this blog says here its for sharing specs in your test suites which is pretty handy. But for your case specifically you could extract your page cases in separate suites and then dynamically include the test case on runtime if a condition is met.
Something like:
Include Spec function shared_specs/index.js
const includeSpec = (sharedExampleName, args) => {
require(`./${sharedExampleName}`)(args);
};
exports.includeSpec = includeSpec;
Test A shared_specs/test_a.js
describe('some_page', () => {
it...
})
Test B shared_specs/test_b.js
describe('some_other_page', () => {
it...
})
and then in your test case
// Something like this would be your path I guess
import {includeSpec} from '../shared_specs/includeSpec.js'
describe('Book a Room', async ()=> {
if (page.userCanOpenARoom()) {
includeSpec('test_a', page);
} else {
includeSpec('test_b', page); // Or dont do anything
}
});
Just make sure that you check the paths since
require(`./${sharedExampleName}`)(args);
will load it dynamically at runtime, and use includeSpec in your describe blocks not it blocks. You should be able to split up your test suites pretty nicely with this.
I am struggling to figure out whether google-translate-api stopped working in firebase functions. I have the following code which used to work but now all I get is locale Not Supported.
exports.translateNow = functions.database.ref('/Translate/lang'.onWrite(event => {
let loc='en';//event.data.val();
console.log("LOCA "+loc);
translateMessage('Ik spreek Engels',loc).then(function(result){
console.log("PYAM ",result);
}).catch(function(err){
console.log("ERR ",err);
});
return true;});
The locale is read from firebase database but I've hard coded en for English which is still not working.
Here is translateMessage
let translateMessage=function(text,loc){
let theLoc=loc;
if(theLoc=='ab'||theLoc=='aa'||theLoc=='ak'||theLoc=='an'||theLoc=='as'||theLoc=='av'||theLoc=='ae'||theLoc=='ay'||theLoc=='bm'||theLoc=='ba'||theLoc=='bh'||theLoc=='ce'||theLoc=='zh'||theLoc=='ki'){
theLoc='en'
}
return new Promise(function(resolve,reject){
translate(text, {from: 'en', to: theLoc}).then(res => {
resolve(res.text);
}).catch(function(result){
reject("Not Supported");
});
});};
Please someone help here's my include const translate = require('google-translate-api');
Followup from this question > Stopping response if document isn't found since it was recommended I use Promise.
So basic premise, I want node to return "Can't find ID" message if we can't find the id in our database.
v1.post("/", function(req, res) {
// If the project_id isn't provided, return with an error.
if ( !("project_id" in req.body) ) {
return res.send("You need to provide Project ID");
}
// Check if the Project ID is in the file.
helper.documentExists( ProjectsData, {project_id: req.body.project_id} )
.then(function(c) {
if ( c == 0 ) {
return res.send("The provided Project Id does not exist in our database.");
} else {
var gameDataObj = req.body;
GameData.addGameId(gameDataObj, function (err, doc) {
if (err) {
if (err.name == "ValidationError") {
return res.send("Please send all the required details.");
}
throw err;
};
res.json(doc);
})
};
});
});
And helper.documentExists
module.exports = {
documentExists: function(collection, query) {
return collection.count( query ).exec();
},
};
But the script continues to run after this and prints the "required data not found".
Output:
required data not found
1
I am using native ES6 Promises.
var mongoose = require("mongoose");
mongoose.Promise = global.Promise;
EDIT: Included the entire get route. (will fix those throw err later)
#######POINT 1#########
ProjectsData.count( {project_id: req.body.project_id} )
.then(function(c) {
#######POINT 3#########
if ( c == 0 ) {
console.log("1");
return res.send("The provided Project Id does not exist in our database.");
console.log("2");
}
});
#######POINT 2#########
//some other logic
console.log("required data not found");
Following async workflow: after POINT 1, the promise is created and your handler is attached. Now POINT 2 will continue, while (at some future clock the promise is resolved and you reach POINT 3.
With my limited understanding of your workflow/purpose I'd say simply put POINT 2 code in the else{} of the if at POINT 3 (as you rightly guessed in the comments).
EDIT: thanks to #jfriend00 for pointing out a serious mistake in the previous version of my answer.
Your code essentially results in this:
ProjectsData.count().then(...);
console.log("required data not found");
So, of course the second console.log() is going to run and print. Nothing that happens in the .then() handler runs until long after the console.log() has already run. And, even then, it can't stop other code from running. Promises don't make the interpreter "wait". They just provide structure for you to coordinate your asynchronous operations.
If you want to branch with promises, then you have to branch inside the .then() handler, not after it.
You don't show enough of the rest of what you're doing to know how to recommend a complete solution. We need to see the rest of your request in order to help you with the proper branching based on asynchronous results.
You probably need something like this:
ProjectsData.count( {project_id: req.body.project_id} ).then(function(c) {
if ( c == 0 ) {
return res.send("The provided Project Id does not exist in our database.");
} else {
// put other logic here
}
}).catch(function(err) {
// handle error here
});