What is the correct way to test Webhooks? - node.js

I have a ReSTFul API in Meteor. I use hooks from Mandrill, Stripe, and other libraries to update a collection.
Router.route('/mandrill/message_rejected', { where: 'server' })
.post(function () {
var request = EJSON.parse(this.request.body.mandrill_events);
var rejects = _.map(_.where(request, {
event: 'reject'
}, {
return object.msg.email;
});
Meteor.users.update({
emails: {
$elemMatch: {
"address": {
$in: rejects
}
}
}
}, {
$set: { status: 'rejected' }
});
this.response.end();
});
My question is; how can I automate tests for this? The request is supposed to come from Mandrill. Is there some way to test webhook messages in a consistent way?

I use Mocha (although you can use other testing frameworks as Jasmine).
I combine the tests with the superagent library that allows you to perform HTTP requests.
The next part does the trick: set up a log and store the received JSON from Mandril or other hooks that you receive and build a library (or fixture) of incoming responses.
Then you can build up the different cases that you need, for example:
Removing an expected field
Sending duplicates
And so on
Making this method consistent requires that you spend time thinking about what hooks you expect to receive, reading the documentation to evaluate if a case you are thinking on is not possible and so on.
I'll recommend you to keep the log of received hooks to improve your tests over the time.

Related

I don't know why my http request doesn't work in my angular project?

I created a RESTful API with node.js and when I tested it with postman it worked properly and showed correct result.
But my problem is in request from my angular application. when I send a request, there is no reaction in API and it seems no request is sent to server at all!
My API url is:
http://localhost:3000/api/menus/menujsonexport
And when I send a request via postman it return a json correctly.
And here is my request script in angular:
private requestMenu(type: 'listsidemenu'): Observable<any> {
let base;
if (type === 'listsidemenu') {
base = this.http.get<any>('http://localhost:3000/api/menus/menujsonexport'
, { headers: { Authorization: `Bearer ${this.getToken()}` }});
}
const requestMenu = base.pipe(
map((data: any) => {
return data;
})
);
return requestMenu;
}
I called the request with this method :
public fetchjsonmenu() {
this.authserv.listSideMenu()
.pipe(
finalize(() => {console.log('finished'); }),
tap(x => {
console.log(x);
})
);
}
But there is no reaction in my nodejs API.
Do you have any idea?
Please tell me if there is lack of information to answer to this question.
An Observable instance begins publishing values only when someone subscribes to it. You subscribe by calling the subscribe() method of the instance, passing an observer object to receive the response.
.subscribe is not an Angular2 thing.
It's a method that comes from rxjs library which Angular is using internally.
If you can imagine yourself when subscribing to a newsletter and after subscribing, every time that there is a new newsletter, they will send it to your home (the method inside subscribe gets called).
That's what happens when you subscribing to a source of magazines ( which they call it Observable in rxjs library)
All the AJAX calls in Angular is using this library behind the scene and in order to use any of them, you've got to use the method name, e.g get, and then call subscribe on it, because get returns and Observable.
Also, when you're doing this <button (click)="doSomething()"> Angular is using Observables behind the scene and subscribes you to that source of thing, which in this case is a click event.
Back to our analogy of Observables and newsletter stores, after you've subscribed, as soon as and as long as there is a new magazine, they'll send it to you unless you go and unsubscribe from them which for that to happen you've got to remember the subscription number or id, which in rxjs it would be like :
let subscription = magazineStore.getMagazines().subscribe(
(newMagazine)=>{
console.log('newMagazine',newMagazine);
});
And when you don't want to get the magazines anymore:
subscription.unsubscribe();
Also, the same goes for
this.route.paramMap
which is returning an Observable and then you're subscribing to it.
My personal view is rxjs was one of the greatest things that were brought to JavaScript world and it's even better in Angular.
There are 150~ rxjs methods ( very similar to lodash methods) and the one that you're using is called switchMap
You need to add .subscribe() in your code after the get call.For more information check the link.
So, now your script should look something like this.
let base;
if (type === 'listsidemenu') {
base = this.http.get<any>('http://localhost:3000/api/menus/menujsonexport'
, { headers: { Authorization: `Bearer ${this.getToken()}` }}).subscribe();
}
const requestMenu = base.pipe(
map((data: any) => {
return data;
})
);
return requestMenu;
}```

Is there a better way with NodeJs to get updates from a Telegram bot?

I'm using simply like below:
class Bot {
constructor(token) {
let _baseApiURL = `https://api.telegram.org`;
//code here
}
getAPI(apiName) {
return axios.get(`${this.getApiURL()}/${apiName}`);
}
getApiURL() {
return `${this.getBaseApiUrl()}/bot${this.getToken()}`;
}
getUpdates(fn) {
this.getAPI('getUpdates')
.then(res => {
this.storeUpdates(res.data);
fn(res.data);
setTimeout(() => {
this.getUpdates(fn);
}, 1000);
})
.catch(err => {
console.log('::: ERROR :::', err);
});
}
}
const bot = new Bot('mytoken');
bot.start();
I'd like to know whether there is a better way to listen for Telegram's updates, instead of using a timeout and redo an Ajax call to 'getUpdates' API
Telegram supports polling or webhooks, so you can use the latter to avoid polling the getUpdates API
Getting updates
There are two mutually exclusive ways of receiving updates for your
bot — the getUpdates method on one hand and Webhooks on the other.
Incoming updates are stored on the server until the bot receives them
either way, but they will not be kept longer than 24 hours.
Regardless of which option you choose, you will receive JSON-serialized Update objects as a result.
More info on: https://core.telegram.org/bots/api#getting-updates
You can use telegraf to easily setup a webhook or to handle the polling for you with a great API

Why we need nock to do http request unit test?

Below is the sample code from redux document
describe('async actions', () => {
afterEach(() => {
nock.cleanAll()
})
it('creates FETCH_TODOS_SUCCESS when fetching todos has been done', () => {
nock('http://example.com/')
.get('/todos')
.reply(200, { body: { todos: ['do something'] }})
const expectedActions = [
{ type: types.FETCH_TODOS_REQUEST },
{ type: types.FETCH_TODOS_SUCCESS, body: { todos: ['do something'] } }
]
const store = mockStore({ todos: [] })
return store.dispatch(actions.fetchTodos())
.then(() => { // return of async actions
expect(store.getActions()).toEqual(expectedActions)
})
})
})
Why we nee to use nock for this unit test?
I did not see any where use the data from nock in this sample code.
Nock is used to mock http requests - if you mock http request it means that your code doesn't perform real http requests to the server.
Nock (and any other http mocking library) overrides native http requests methods so that real http requests will be never sent. It has many benefits - for example you don't have to wait for actual server response because mocked request returns response in no time and of course your test are independent of server. You can focus on testing application code and don't worry about server - even if server doesn't work you test can be run.
You don't have to explictly use data returned by mocked request if you don't need to test it - the main reason of using nock in your code sample is to prevent actual http request to the server that FETCH_TODOS_REQUEST action would normally sent. Besides, even if mocked response data is not explicily used in tests it's probably used in the application code (probably FETCH_TODOS_SUCCESS action expects todos array to be returend) so you have to mock response data so that your application gets data it expects.
If nock wasn't used the test would take much more time because real http request to the server would be sent.
Mainly because in this test we're interested in the actions that get produced by actions.fetchTodos(). This action will make a call to the /todos endpoint, thus returning actions with some data. Since we're just interested in the data contained in the actions, we just mock it.
Nock internally intercepts the real fetch call to /todos and returns a successful 200 code, making it possible for the redux store to continue.
The data you're looking for is
{ todos: ['do something'] }
This is mocked and also expected later on

loopback remote method return variable other than request data

I have a generic SendMail route which I want to create multiple remote methods to handle multiple request templates. Any ideas on how to return a Email_Type from the remote method back to the base route. I know I could add a default with a code in it, but would like a more elegant solution.
Mail.genericSendMail = function genericEmail(response, callback) {
console.log(response);
let templateId=0;
//PROBLEM: HOW TO KNOW WHICH REMOTE WAS USED
switch (response.emailType) {
case "Template-1":
templateId= 1234;
break;
case "Template-2":
tempalteId = 456;
break;
default:
templateId = 789l
} //switch
console.log(templateId);
};
//Want multiple routes like this to support various templates
Mail.remoteMethod("genericEmail", {
http: {
path: "/emailTemplate1",
verb: "POST"
},
accepts [
{arg: "request", type:"object",http: {source:"body"},
default: {firstName:"", lastName:"",emailAddress:""}
}],
returns: RESTResponseStatic.loopbackAdapterCommonRestResponseDefinition()
});
//Want multiple routes like this to support various templates
Mail.remoteMethod("genericEmail", {
http: {
path: "/emailTemplate2",
verb: "POST"
},
accepts [
{arg: "request", type:"object",http: {source:"body"},
default: {emailAddress:"", promoCode:""}
}],
returns: RESTResponseStatic.loopbackAdapterCommonRestResponseDefinition()
});
There are a couple of different ways to do this. Since it happens to be a POST request, I usually go with attaching data to the body using a before remote hook.
Let's say you have a model method for logging in users.
Say we have a multi realm platform, so we need to know what platform we are logging in. If you don't use realms or don't know what they are, don't worry. This just shows you how to populate the data to the model method.
User.login = function(data, cb) {
if (data.realm == 'platform1) {
return logUserIntoPlatform1(data, cb);
}
return logUserIntoDefaultPlatform(data, cb);
}
Now let's say you don't want the client/frontend to send the realm and you don't want to do the lookup for realm in the model. We can add a beforeRemote hook like so:
User.beforeRemote('login', function (context, user, next) {
context.args.data.realm = lookUpRealmSync(context); // 1
next();
});
This will be called before the login method. Note the next() call: this is how you could do error detection before actually hitting the model method. Something like next({ status: 422, message: 'Parameter missing: password }); would return an error and not execute the User.login method.
You may have to look carefully at your context object (i.e. the line marked with 1 may not work exactly as I've shown for you).
If you want to read more about this stuff, I LoopBack's docs are pretty good. It seems they've been updated since I've last used them so I can't link you to the more useful pages. I found the remote method documentation here though.
Edit: I took a closer look at your question. You should be able to retrieve the path from the context object and pass data accordingly. I'm not going to try to code that since I don't know where it would actually be within the object.

Reasonable design of using socket.io for RPC

I am building a web app that uses socket.io to trigger remote procedure calls that passes sessions specific data back go the client. As my app is getting bigger and getting more users, I wanted to check to see if my design is reasonable.
The server that receives websocket communications and triggers RPCs looks something like this:
s.on('run', function(input) {
client.invoke(input.method, input.params, s.id, function(error, res, more) {
s.emit('output', {
method: input.method,
error: error,
response: res,
more: more,
id: s.id
});
});
});
However, this means that the client has to first emit the method invocation, and then listen to all method returns and pluck out its correct return value:
socket.on('output', function(res) {
if (res.id === socket.sessionid) {
if (!res.error) {
if(res.method === 'myMethod') {
var myResponse = res.response;
// Do more stuff with my response
});
}
}
});
It is starting to seem like a messy design as I add more and more functions... is there a better way to do this?
The traditional AJAX way of attaching a callback to each function would be a lot nicer, but I want to take advantage of the benefits of websockets (e.g. less overhead for rapid communications).

Resources