xml2js is not throwing an error when I pass in an invalid xml to parse.parseString - nodejs-server

I am trying to write a jest test for the xml2js parse.parseString, but when I pass in an invalid xml it just bypasses the parse.parseString function rather than return the error in the callback function. I want to trigger the error in the callback function.
import xml2js from 'xml2js';
const parser = new xml2js.Parser({
async: false
});
parser.parseString(`<_>&%xstest</_>`, (err, result) => {
if (err) {
console.log('error',err)
throw new Error(`Parser error: ${err}`);
}
console.log('result', result)
});
any idea on why I can not trigger the err in the callback of parse.parseString to call? I am unable to get parse.parseString to throw an error.

Related

RxJs throwError does not trigger catch in Promise

I've got an Api call that is converted to a promise. My handleError function inside the observable re-throws via throwError. This re-thrown error does not trigger any catch in the outer Promise chain.
callApi() {
return this.http.get(`${this.baseUrl}/someapi`)
.pipe(
map((data: any) => this.extractData(data)),
catchError(error => this.handleError(error))
).toPromise();
handleError(error) {
console.error(error);
return throwError(error || 'Server error');
}
Calling code...
this.someService.callApi()
.then((response) => {
// THIS GETS CALLED AFTER throwError
// do something cool with response
this.someVar = response;
})
.catch((error) => {
// WE NEVER GET TO HERE, even when I force my api to throw an error
console.log(`Custom error message here. error = ${error.message}`);
this.displayErrorGettingToken();
});
Why doesn't the throwError trigger the Promise catch?
You should not use toPromise() when possible.
Use subscribe instead of then.
Also when you catch the error in a pipe it won't be thrown in then because you already caught it, also when you throw the error in a catch error, it won't be emitted into the regular pipe flow of your response.
callApi() {
return this.http.get(`${this.baseUrl}/someapi`);
}
This is totally ok. Http.get() returns a singleton observable stream, which emits only ONE value and then completes. Subscribe to the Observable.
this.someService.callApi()
.subscribe((response) => {
// THIS GETS CALLED always wenn everything is ok
this.someVar = response;
},
(error:HttpErrorResponse) =>{
console.log(`Custom error message here. error ${error.message}`);
this.displayErrorGettingToken();
});
Observable is like an extended version of promise. Use it.

How to expect toThrow on new ES6 Obj in Jasmine [duplicate]

I'm trying to write a test for the Jasmine Test Framework which expects an error. At the moment I'm using a Jasmine Node.js integration from GitHub.
In my Node.js module I have the following code:
throw new Error("Parsing is not possible");
Now I try to write a test which expects this error:
describe('my suite...', function() {
[..]
it('should not parse foo', function() {
[..]
expect(parser.parse(raw)).toThrow(new Error("Parsing is not possible"));
});
});
I tried also Error() and some other variants and just can't figure out how to make it work.
Try using an anonymous function instead:
expect( function(){ parser.parse(raw); } ).toThrow(new Error("Parsing is not possible"));
you should be passing a function into the expect(...) call. Your incorrect code:
// incorrect:
expect(parser.parse(raw)).toThrow(new Error("Parsing is not possible"));
is trying to actually call parser.parse(raw) in an attempt to pass the result into expect(...),
You are using:
expect(fn).toThrow(e)
But if you'll have a look on the function comment (expected is string):
294 /**
295 * Matcher that checks that the expected exception was thrown by the actual.
296 *
297 * #param {String} expected
298 */
299 jasmine.Matchers.prototype.toThrow = function(expected) {
I suppose you should probably write it like this (using lambda - anonymous function):
expect(function() { parser.parse(raw); } ).toThrow("Parsing is not possible");
This is confirmed in the following example:
expect(function () {throw new Error("Parsing is not possible")}).toThrow("Parsing is not possible");
Douglas Crockford strongly recommends this approach, instead of using "throw new Error()" (prototyping way):
throw {
name: "Error",
message: "Parsing is not possible"
}
As mentioned previously, a function needs to be passed to toThrow as it is the function you're describing in your test: "I expect this function to throw x"
expect(() => parser.parse(raw))
.toThrow(new Error('Parsing is not possible'));
If using Jasmine-Matchers you can also use one of the following when they suit the situation;
// I just want to know that an error was
// thrown and nothing more about it
expect(() => parser.parse(raw))
.toThrowAnyError();
or
// I just want to know that an error of
// a given type was thrown and nothing more
expect(() => parser.parse(raw))
.toThrowErrorOfType(TypeError);
A more elegant solution than creating an anonymous function whose sole purpose is to wrap another, is to use ES5's bind function. The bind function creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
Instead of:
expect(function () { parser.parse(raw, config); } ).toThrow("Parsing is not possible");
Consider:
expect(parser.parse.bind(parser, raw, config)).toThrow("Parsing is not possible");
The bind syntax allows you to test functions with different this values, and in my opinion makes the test more readable. See also:
Does Jasmine's toThrow matcher require the argument to be wrapped in an anonymous function?
I replace Jasmine's toThrow matcher with the following, which lets you match on the exception's name property or its message property. For me this makes tests easier to write and less brittle, as I can do the following:
throw {
name: "NoActionProvided",
message: "Please specify an 'action' property when configuring the action map."
}
and then test with the following:
expect (function () {
.. do something
}).toThrow ("NoActionProvided");
This lets me tweak the exception message later without breaking tests, when the important thing is that it threw the expected type of exception.
This is the replacement for toThrow that allows this:
jasmine.Matchers.prototype.toThrow = function(expected) {
var result = false;
var exception;
if (typeof this.actual != 'function') {
throw new Error('Actual is not a function');
}
try {
this.actual();
} catch (e) {
exception = e;
}
if (exception) {
result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected) || this.env.equals_(exception.name, expected));
}
var not = this.isNot ? "not " : "";
this.message = function() {
if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
return ["Expected function " + not + "to throw", expected ? expected.name || expected.message || expected : " an exception", ", but it threw", exception.name || exception.message || exception].join(' ');
} else {
return "Expected function to throw an exception.";
}
};
return result;
};
I know that is more code, but you can also do:
try
Do something
#fail Error("should send a Exception")
catch e
expect(e.name).toBe "BLA_ERROR"
expect(e.message).toBe 'Message'
In my case, the function throwing an error was async, so I followed this:
await expectAsync(asyncFunction()).toBeRejected();
await expectAsync(asyncFunction()).toBeRejectedWithError(...);
For CoffeeScript lovers:
expect( => someMethodCall(arg1, arg2)).toThrow()
For me, the posted solution didn't work and it kept on throwing this error:
Error: Expected function to throw an exception.
I later realised that the function which I was expecting to throw an error was an async function and was expecting the promise to be rejected and then throw an error and that's what I was doing in my code:
throw new Error('REQUEST ID NOT FOUND');
And that’s what I did in my test and it worked:
it('Test should throw error if request not found', willResolve(() => {
const promise = service.getRequestStatus('request-id');
return expectToReject(promise).then((err) => {
expect(err.message).toEqual('REQUEST NOT FOUND');
});
}));
it('it should fail', async () => {
expect.assertions(1);
try {
await testInstance.doSomething();
}
catch (ex) {
expect(ex).toBeInstanceOf(MyCustomError);
}
});

Mocha Chai HTTP post request not working

The following test is not working with mocha-chai, it is able to to get the input request but throws the error message.
it('/hb : ', function (done) {
return chai.request(app)
.post('/hb')
.send({"a":1 })
.then(function (res) {
expect(err).to.be.null;
expect(res).to.have.status(200);
// { ah: { rt: [Object] }, ad: { mojo: 1 } } }
//console.log("CAlling DOne ........... +");
done();
}, function (err) {
//console.log(err);
throw err;
});
});
Output:
Web Requests : /hb : :
Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.
The functions that chai-http adds to chai return promises. In your code you return the promise, which is good. However, you also declare your test to take the a parameter: function (done). This would be fine if you did not return the promise, but returning the promise is really the better mechanism here. When you declare your test to take a parameter, Mocha ignores the return value from the test, and so the promise is ignored. So just remove your use of done.
Here's an example that reproduces the error you had in your original code with err being undefined in the function you pass to then.
'use strict';
var app = require('./server');
var chai = require('chai');
chai.use(require('chai-http'));
var expect = chai.expect;
it('/hb', function () {
return chai.request(app)
.post('/hb')
.send({a: 1})
.then(function (res) {
expect(err).to.be.null;
expect(res).to.have.status(200);
});
});
If the server returns a 200 status, then you'll get this on the console:
1) /hb
0 passing (26ms)
1 failing
1) /hb:
ReferenceError: err is not defined
at test.js:13:20
If the server returns a 400 status, the output would be:
1) /hb
0 passing (24ms)
1 failing
1) /hb:
Error: Bad Request
at Test.Request.callback (node_modules/superagent/lib/node/index.js:792:17)
at IncomingMessage.<anonymous> (node_modules/superagent/lib/node/index.js:990:12)
at endReadableNT (_stream_readable.js:913:12)
you need to add following:
.set('content-type', 'application/x-www-form-urlencoded')
you can reference this question over Post request via Chai

How to properly throw and handle errors in promises in Sails.js?

I'm starting to convert my callback code to promises in Sails.js, but I don't understand how I can raise custom errors and handle them in the promise chain. Sails.js uses Q as its promise library.
User.findOne({email: req.param('professorEmail'), role: 'professor'})
.then(function (user) {
if (user) {
return Course.create({
user_id: user.id,
section: req.param('section'),
session: req.param('session'),
course_code: req.param('course_code')
});
} else {
// At this point `user` is undefined which means that no professor was found so I want to throw an error.
// Right now the following statement does throw the error, but it crashes the server.
throw new Error('That professor does not exist.');
// I want to be able to handle the error in the .fail() or something similar in the promise chain.
}
}).then(function (createSuccess) {
console.log(createSuccess);
}).fail(function (err) {
console.log(err);
});
Right now the .fail() is never called because the thrown error crashes the server.
Use .catch() instead of .fail().
Waterline's claim complete Q promise object after the first then seems untrue by your test. I've verified it myself as well and found a workaround.
You can do this :
var Q = require('q');
[...]
Q(User.findOne({email: req.param('professorEmail'), role: 'professor'}))
.then(function (user) {
if (user) {
return Course.create({
user_id: user.id,
section: req.param('section'),
session: req.param('session'),
course_code: req.param('course_code')
});
} else {
// At this point `user` is undefined which means that no professor was found so I want to throw an error.
// Right now the following statement does throw the error, but it crashes the server.
throw new Error('That professor does not exist.');
// I want to be able to handle the error in the .fail() or something similar in the promise chain.
}
}).then(function (createSuccess) {
console.log(createSuccess);
}).fail(function (err) {
console.log(err);
});
This will return a true Q promise.

Getting global handler to all AJAX calls in dojo

I need to invoke some common methods before an AJAX call is made and after the AJAX call (before the actual handler method is called) is success. I'm using dojo.aspect to achieve this.
This is my code sample
function makeAjaxCall(){
dojo.xhrGet({
url:"sample_url",
content:{
test:"value"
},
load:function(response){
//Do some logic here
},
error:function(response){
//handle error
}
});
}
Below is the dojo.aspect which I'm using to get a hook to the XHR calls.
define(["dojo/aspect"], function(aspect){
aspect.after(dojo, "xhr", function(deferred){
console.log("AJAX AFTER");
deferred.then(function(response){
//CALLED AFTER 'load' METHOD IS CALLED.
console.log("Testing");
});
});
aspect.before(dojo, "xhr", function(method, args){
console.log("AJAX BEFORE");
});
});
Now the problem is deferred.then inside aspect.after is called after the "load" function is called. Is it possible to have a method which is called before the actual load method is invoked?
The short answer is yes.
First, there are two ways to make ajax calls in Dojo.
dojo/xhr - this is what you have above and this is deprecated
in favor of
dojo/request/xhr
The first implementation will call into the second implementation. So I would recommend using aop on dojo/request/xhr.
aspect.around(require.modules['dojo/request/xhr'], 'result', function(originalXhr){
return function(url, options, returnDeferred){
var dfd = new Deferred();
// Logic before making the xhr call
originalXhr(url, options, returnDeferred)
.then(function(response) {
// Logic handling the response but before resolving the deferred.
dfd.resolve(vm);
// Logic after resolving the deferred.
}, function(err){
// error handling?
dfd.reject(msgs);
}, function(update) {
dfd.progress(update);
});
return dfd;
};
});
You can find the complete implementation at
https://github.com/cswing/evinceframework/blob/master/evf-web-js/src/dojo/evf/serviceRegistry.js (~ line 111)
USAGE:
require('dojo/xhr/request', function(xhr){
xhr({...}).then(
function(response) {
//handle response
},
function(error) {
//handle error
}
);
});
The dojo/xhr code will translate itself to the usage above, so the code you posted should work.
If you switch to the new API - dojo/request
Then you could use dojo/request/xhr and dojo/request/notify
In Dojo 1.10 there is new API to globally catch state of requests.
notify("error", function(error){
console.error(error);
//SyntaxError: Unexpected token < in JSON at position 0(…)
});
But in my case I get errors in html eg. so in error I get "error SyntaxError: Unexpected token < in JSON at position 0(…)"
In previous version there was an access to response object:
topic.subscribe("/dojo/io/error", function(/*dojo.Deferred*/ dfd, /*Object*/ response){
if (response.status === 401) {
window.location.reload();
}
});
So I figured out that json handler can be customized:
require(["dojo/request/handlers"], function(handlers){
handlers.register("json", function(response){
if (response.status === 401) {
window.location.reload();
return;
}
return JSON.parse(response.text || null);
});
});
This way you are able to detect response.errors before JSON.parse throws exception.

Resources