How to test a function in a catch block of try/catch? - vue.js

I have a custom package that is called if an error is thrown in the catch block of a try/catch. I want to test that the logFunction.error function is called. How do I test this function in the catch block? I'm passing in a mock jwt. I'm using jwtDcode (https://www.npmjs.com/package/jwt-decode) to decode my jwt. If it fails, an error is thrown the logFunction.error() returns a details object. Is this the correct way to set up this unit test?
file.js
jwtFunction ({commit}, idToken) {
try {
jwtDecode(idToken)
// do some logic
}catch (error) {
logFunction.error({
details: {
event: 'invalid jwt'
message: `${error.message} of ${idToken}`
timeStamp: Date.now()
}
})
commit(types.setApplicationError, error)
}
file.spec.js
it('[positive] should commit application error if jwt fails to decode', () => {
const mockIdToken = {}
const spy = jest.spyOn(logFunction, 'error')
actions.jwtFunction({ commit }, mockIdToken)
expect(spy).toHaveBeenCalled()
})

Related

Lambda doesn't reattempt processing the SQS message even after an error is returned from the handler

I am trying to invoke the lambda function using standard SQS. I have handled errors using a try-catch block and whenever an error is caught, it will be returned. Otherwise, a response message will be returned with 200 OK.
I want to reprocess the messages which returned errors. But lambda won't reprocess those messages.
Even the Retention time period(5 min) > Visibility time out(1 min)
Why does this happen?
const { spawnSync, execSync } = require('child_process');
const fs = require('fs');
const { S3Client, GetObjectCommand, PutObjectCommand } = require("#aws-sdk/client-s3");
const { DynamoDBClient, UpdateItemCommand } = require("#aws-sdk/client-dynamodb");
const { marshall } = require('#aws-sdk/util-dynamodb');
exports.lambdaHandler = async (event) => {
try {
const body = JSON.parse(event["Records"][0]['body']);
try {
// Code base 1
// All the above imported dependencies will be used here
const response = {
statusCode: 200,
body: JSON.stringify({ message: "Function Executed" })
};
console.log('Response: ',response);
return response;
}
catch (err) {
console.log("[ERROR]: ", err);
console.log('body is: ', body);
console.log("err returning");
return err;
}
}
catch (error) {
console.log("[ERROR]: ", error);
console.log("error returning");
return error;
}
};
// Below functions are used in code base 1
// No try catch block or error hadling in below code bases
async function downloadFile() {
//code base 2
};
async function uploadFile() {
// code base 3
};
async function updateUsdz() {
// code base 4
}
You are, as you say, literally returning the error. However, for lambda in this scenario, you're simply returning an object. It does not matter whether or not the object is an error object or any other object. According to the system, your lambda will have been successfully executed, the SQS service will receive a success response from AWS Lambda and the message will be dropped from the queue as it is handled.
If you want to use the retry functionality that SQS provides, you must ensure that you're lambda fails. In this case, this means actually throwing the error again after you've executed the code you want to execute on failure (e.g., logging the error). If you throw the error, the handler function will fail (instead of simply returning an error object) and the message will not be deleted from the SQS queue but will be retried.
For example:
exports.lambdaHandler = async (event) => {
try {
// Do something
} catch (error) {
console.log("[ERROR]: ", error);
throw error;
}
};
As a side note, if you're using a solution like this, ensure you are attaching a dead-letter queue to your SQS queue in order to catch messages that can never be handled by the lambda. If you do not have such a queue to catch those messages, these will keep being retried which effectively creates an infinite loop which could cost quite a lot of money.

Express Mongoose throw custom error on callbacks

I'm trying to throw some custom error classes from mongoose callbacks.
Here is a simple code
const Restaurant = require('../models/Restaurant')
const { InternalServerError, UnauthorizedError } = require('../errors/errors')
const checkRestaurantAuthorization = async (token) => {
const restaurant = Restaurant.findOne({ 'token': token }, function (error, result) {
if (error) throw new InternalServerError()
else if (!result) throw new UnauthorizedError()
else return token
})
}
In my code checkRestaurantAuthorization is called by a simple middleware like
const restaurantMidlleware = async (req, res, next) => {
console.log('Request Type:', req.method);
try {
token = await checkRestaurantAuthorization('invalid_token')
next()
} catch (error) {
next(error)
}
}
Now if a restaurant instance with the given token is not found, the app crashes with throw er; // Unhandled 'error' event. From my testing it seems that executions stops when throw new UnauthorizedError() is called and I'm unable to identify the issue.
Here is also an example of a custom defined error if it's useful
class UnauthorizedError extends Error {
constructor(message) {
super(message)
this.name = 'Unauthorized request'
this.code = 403
Error.captureStackTrace(this, UnauthorizedError)
}
}
What am I missing?
have you tried putting your first block in 'try-catch' block?
The throw statement throws a user-defined exception. Execution of the current function will stop (the statements after throw won't be executed), and control will be passed to the first catch block in the call stack. If no catch block exists among caller functions, the program will terminate.
you can change code to promise or async-await
another source of the problem could be the fact that your are using async and callback in one function try to omit async then use it again
And there is no point in writing 'const restaurant =' in
const restaurant = Restaurant.findOne
since every found restaurant will be saved in callback's result variable
try this
function checkRestaurantAuthorization(token){
return new Promise(async(resolve, reject)=>{
try {
const restaurant = await Restaurant.findOne({ 'token': token });
if (!restaurant)
return reject(new UnauthorizedError())
else
return resolve(token)
}catch(error){
return reject(new InternalServerError())
}
})}
Even better approach would be using only async function with try-catch instead of returning a promise or any callback

Vuex action "not a function" inside Nuxt fetch

I have just introduced error handling to one of my Nuxt pages and apparently the action mapped and called inside fetch raises a not a function error. If the try/catch block isn't there it works as expected and there's no error at all.
Here is my component stripped to the essential parts:
export default {
name: 'ViewArticle',
async fetch ({ error }) {
try {
await this.fetchArticle({ articleSlug: this.articleSlug })
} catch (err) {
error({ statusCode: 404, message: 'May the force be with you' })
}
},
computed: {
...mapGetters({
article: 'article/single'
}),
articleSlug () {
return this.$route.params.articleSlug
}
},
methods: {
...mapActions({
fetchArticle: 'article/fetchOne'
})
}
}
I am assuming that somehow mapActions only gets executed later in the spiel, but can't figure out how to prevent the error. This way, basically every time I load the page it gets immediately redirected to the error page.
The error message I'm getting is the following. Obviously fetchArticle is a function, and unless it's inside the try/catch block, it works as expected.
this.fetchArticle is not a function 03:30:51
at Object.fetch (52.js:32:18)
at server.js:2881:39
at Array.map (<anonymous>)
at module.exports../.nuxt/server.js.__webpack_exports__.default (server.js:2864:51)
Fetch provides the context as argument.
fetch(context)
Inside the context we can find our store. Here you can take a look what context contains: https://nuxtjs.org/api/context
fetch(context) {
let store = context.store;
}
People like to destructure it
fetch({ store }) {}
Your code should look like this:
async fetch ({ error, store }) {
try {
await store.dispatch('article/fetchOne', { articleSlug: this.articleSlug })
} catch (err) {
error({ statusCode: 404, message: 'May the force be with you' })
}
},
Fetch gets executed on the server side, thats why you get is not an function error. Its undefined
... fetch is called on server-side...
Use async fetch({store})
async fetch ({ error, store }) {
try {
await store.dispatch( 'article/fetchOne' , { articleSlug: this.articleSlug })
} catch (err) {
error({ statusCode: 404, message: 'May the force be with you' })
}

Angular GlobalErrorHandler and HttpErrorResponse - Resolver throwing badly formatted HttpErrorResponse

I've created global error handler in my Angular 6 application:
main error handler method:
handleError(error: Error | HttpErrorResponse) {
const router = this.injector.get(Router);
const notificationService = this.injector.get(NotificationsService);
this._logger(error);
if (!navigator.onLine) {
notificationService.displayNotification('error', 'timespan', {heading: 'Internet connection lost!', body: ''});
} else if (error instanceof HttpErrorResponse) {
notificationService.displayNotification('error', 'click', this._httpErrorMessage(error));
} else {
// CLIENT error
router.navigate(['/error-page']);
}
}
Problem:
Many of HTTP service calls are being performed in resolvers:
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<ClientDetailsModel> {
if (route.params.cif) {
const reqBody = new GetClientDetailsRequestModel({cif: route.params.cif, idWewPrac: this.userContext.getUserSKP()});
return this.clientsService.getClientDetails(reqBody)
.pipe(
map((clientDetails: { customerDetails: ClientDetailsModel }) => {
if (clientDetails.customerDetails) {
return clientDetails.customerDetails;
}
return null;
})
);
}
If Http error occurs in such a call, error received by my global error handler is formed as HttpErrorResponse wrapped inside Error (message of Error is HttpErrorResponse):
Uncaught (in promise): HttpErrorResponse: {"headers":{"normalizedNames":{},"lazyUpdate":null},"status":400,"statusText":"OK","url":"https://...
If Http errors occurs outside of resolvers global error handler works perfectly fine.
To reach my goal (throwing HttpErrorResponse from resolver) I need to specify the way to handle error in error callback inside subscription, but I cannot do it because resolver is the one who manages subscription.
Is there a way to specify how resolver should handle errors?
I would like to avoid manual parsing of these wrapped errors.
I was searching for a solution, but could only create a work-a-round.
This will check for the HttpErrorResponse text and tries to parse the JSON which results into the real error object.
Not great at all, but better then nothing.
handleError(error: any): void {
console.error('Errorhandler catched error: ' + error.message, error);
// We need to have this little hack in oder to access the real error object
// The Angular resolver / promise wraps the error into the message, serialized as json.
// So we extract this error again.
// But first lets check if we actually dealing with an HttpErrorResponse ...
if (error.message.search('HttpErrorResponse: ')) {
// The error includes an HTTPErrorResponse, so we try to parse it's values ...
const regex = new RegExp('^.*HttpErrorResponse:\\s(\\{.*\\})$');
const matches = regex.exec(error.message);
if (matches !== null) {
// matches the regex, convert...
const httpErrorResponse = JSON.parse(matches[1]); // This is now the real error object with all the fields
this.handleHttpErrorResponse(httpErrorResponse);
} else {
// It contains HttpErrorResponse, but no JSON part...
this.toastr.error('There was an unknown communication error',
'Communication error',
{timeOut: 10000});
}
} else {
this.toastr.error('Unknown error occured',
'Well that should not happen. Check the log for more information...',
{timeOut: 10000});
}
}

How to Catch Errors from Apollo/GraphQL

I use graphCool as a backend, but there is a bug which won't be fixed any time soon.
Making a delete mutation on File schema will always throw this error (not a big deal):
"GraphQL error: Whoops. Looks like an internal server error. Please contact us from the Console (https://console.graph.cool) or via email (support#graph.cool) and include your Request ID:"
The call works, but I need to access the update function after the call and I can't because of the error.
Two solutions:
1. Catch the graphql error so I can reach update: function, how can I do this?
2. Update the store without using the update: function, how can I do this?
Here is my code:
_deleteImageFile = async () => {
// THIS WORKS, BUT GET AN ERROR
const socialPostId = this.props.socialPost.id
// Tried to wrap the following in try catch without success
await this.props.deleteImageFileMutation({
variables: {
id: this.props.socialPost.image.id
}, //Error hits here "internal service error..."
update: (store) => { //This is never run because of error
console.log('this text will never log')
const userId = localStorage.getItem(GC_USER_ID)
const data = store.readQuery({query: ALL_SOCIAL_POSTS_QUERY,
variables: {
id: userId
}})
// Need to change the store here
store.writeQuery({query: ALL_SOCIAL_POSTS_QUERY, data,
variables: {
id: userId
}}).catch(res => { const errors = res.graphQLErrors; console.log(errors)})
//The catch was an attempt to fix it
}
})
}
Reference Bug: https://github.com/graphcool/framework/issues/434
You could try to pass down another dummy mutation and do that after the deleteImageFileMutation throws.
try {
await this.props.deleteImageFileMutation ...
} catch (e) {
// ...
} finally {
await this.props.dummyMutation ...
}