How we do Exception handling in protractor-cucumber and do a email notification - protractor

I am using Protractor-Cucumber framework with protractor 5.2.2 and cucumber 3.2. I have a requirement of posting in no.of locations. So I have written a script in a loop for it. But it randomly fails before completing the loop. So when the script ends abnormally, is there like an exception handling section that gets control before exiting.The script can be fail due to any of the reasons like web driver issue,NoSuchElementError,ElementIsNotIntractable,ElementIsNotVisible etc.So whatever be the issue I have to handle that, and if it fails, I have to do an email notification. I have tried try catch, as given below, but it does not work for me.
When(/^I login$/, function () {
try{
element(by.css(".signin")).click();
var count=post_details.length ;
for (var i=0; i<count; i++){
post();
}
}
catch(e){
console.log("failed");
}
});
How we can do this in protractor-cucumber.Thanks in advance

For the exception problem you can try this. ignoreUncaughtException
For the email part create a hooks.js file. Here you can setup the After() function, to check your scenario fails or not. Cucumber Docs.
Example:
After(function (scenario) {
if (scenario.result.status === Status.FAILED)
{
failed = true;
const attach = this.attach;
//creates a screenshot for the report
return browser.takeScreenshot().then(function(png) {
return attach(new Buffer(png, "base64"), "image/png");
});
}
});
Then you can use nodemailer to send messages. Nodemailer
In your AfterAll() function you can handle the send part.
Example:
AfterAll(function(callback){
console.log("AfterAll");
if (failed)
{
var transporter = nodemailer.createTransport(
{
host: 'host.com',
port: xx,
secure: false,
//proxy: 'http://10.10.10.6:1098',
auth: {
user: userMail,
pass: pw
}
});
var mailOptions = {
from: 'xx', // sender address (who sends)
to: xxxxxx#mail.com',
subject: 'your subject', // Subject line
text: 'Your test failed....', // plaintext body
/*attachments: [
{
filename: 'report.html',
path: htmlReport,
}]*/
};
transporter.sendMail(mailOptions, function(error, info)
{
if(error)
{
return console.log(error);
}
console.log('Email sent: ' + info.response);
console.log(info);
});
} else {
//do your stuff
}
setTimeout(callback, 2000);
});

Related

protractor promises - querying an API using "request"

I am trying to use protractor to call an api - it will return some JSON to me and I want to assert against it. I thought I had this working, until I tried to take it further and realised I hadn't got it right, but having a bit of a time trying to work out why.
I have placed some console.logs in and expected the sequence to be 1,2,3 however it appears to be 3 (test finished) then 2 and 1. So I suspect a promise issue.
code below:
'use strict';
var request = require('request');
var path = require('path');
var info;
//var fname = null;
var fname = 'joe';
describe("Sample test", function() {
var request = require('request');
var options = {
method: 'GET',
url: 'URL here',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: '{ "pay_load": [] }'
};
function callback(error, response, body) {
if (!error && response.statusCode == 200) {
info = JSON.parse(body);
console.log('in the callback now');
//console.log('body :' + body);
//var count = Object.keys(info).length;
//console.log('body len:' + count);
//console.log('info :' + info);
fname = info.firstname;
console.log('firstname1 : ' + info.firstname);
console.log('firstname2 : ' + fname);
} else {
console.log('there was some error');
}
}
it("proves the API is alive - firstname is null", function() {
request(options, callback);
//expect(fname).toBe(null);
console.log('firstname3 : ' + fname);
//expect(fname).toBe(null);
//var common = new Common();
//common.checkForAPI();
});
So in my head I thought I would see "in the callback", then "firstname1", "firstname2" and finally "firstname3"
No, firstname3 will always get printed first, the way you have it. The reason for it as that all http requests in nodejs are async, so while your request is processing (or in flight), firstname3 will be printed. Then console.logs in your request callback.
Edit1 - Addressing the comment
Simple example which would print firstname1,2,3 in sequence (tested)
var request = function(cb) {
//basically call your request stuff and then when you are done call cb
console.log('firstname 1');
console.log('firstname 2');
cb();
};
request(function() {
console.log('firstname 3');
});
This prints
firstname 1
firstname 2
firstname 3
Or you can use a third party library called async and use async.tryEach to run tasks in series.
async.tryEach([
function getDataFromFirstWebsite(callback) {
// Try getting the data from the first website
callback(err, data);
},
function getDataFromSecondWebsite(callback) {
// First website failed,
// Try getting the data from the backup website
callback(err, data);
}
],
// optional callback
function(err, results) {
Now do something with the data.
});

How to read mail text in mail listener 2?

conf.js
var MailListener = require("mail-listener2");
var mailListener = new MailListener({
username: "*****#office365.com",
password: "******",
host: "outlook.office365.com",
port: 993, // imap port
tls: true,
fetchUnreadOnStart: true,
tlsOptions: {rejectUnauthorized: false},
mailbox: "INBOX",
searchFilter: "UNSEEN",
markSeen: true
});
mailListener.on("server:connected", function () {
console.log("imapConnected");
});
mailListener.on("server:disconnected", function () {
console.log("imapDisconnected");
});
(function () {
var count = 0;
mailListener.on("mail", function (mail, seqno, attributes) {
var mailuid = attributes.uid,
toMailbox = 'Inbox',
i = ++count;
if (i > 1) {
mailListener.stop(); // start listening
return;
}
console.log('email parsed', {
i: i,
subject: mail.subject,
from: mail.from,
text:mail.text,
seqno: seqno,
uid: attributes.uid,
attributes: attributes
});
expect(mail.subject).toEqual("FW: Secure One-Time-Password for Account Login");
var pattern = new RegExp(/Please use (\w+)/g);
var regCode = pattern.exec(mail.text)[1];
console.log(regCode);
console.log('attempting to mark msg read/seen');
mailListener.imap.addFlags(mailuid, '\\Seen', function (err) {
if (err) {
console.log('error marking message read/SEEN');
return;
}
//console.log('moving ' + (seqno || '?') + ' to ' + toMailbox);
//mailListener.imap.move(mailuid, toMailbox, function (err) {
if (err) {
console.log('error moving message');
return;
}
console.log('moved ' + (seqno || '?'), mail.subject);
});
});
});
})
();
mailListener.start(); // start listening
setTimeout(function () {
mailListener.stop(); // start listening
}, 60 * 1000);
I am reading all the details except text and the text is in html table format.
Instead of text i am getting undefined message.If needed i will add html code also.
If i am forwarding the same mail to gmail from office 365 and reading the mail from gmail i am able to get text.
Error:
subject: 'test mail',
from: [ { address: 'otp#gmail.com', name: 'gmail.com' } ],
body: undefined,
seqno: 2,
uid: 18,
attributes:
{ date: 2017-06-14T16:22:06.000Z,
flags: [ '\\Seen' ],
uid: 18,
modseq: '3914',
'x-gm-labels': [],
'x-gm-msgid': '1570197813730673685',
'x-gm-thrid': '1570197813730673685' } }
[21:56:13] E/launcher - Cannot read property '1' of null
[21:56:13] E/launcher - TypeError: Cannot read property '1' of null
I see that this is an old issue, but I am facing the same problem and using the nearly the same function.
I want to get the content of the e-mail with a link and the email is in HTML. So: mail.text doesn't and won't work in this case.
Solution is really simple and it works for me straight forward: mail.html

How to use botkit with facebook and wit.ai

I am a novice in chatbot development and I would like some help.
While it seems quite simple to connect botkit with facebook messenger and wit.ai in orger to use NLP. I haven't managed to do so. My initial goal is to have a simple conversation like hello-hello but using wit.ai as middleware.
Below I attach the code. What it should do is receive a "hello" message, pass it to wit.ai and then respond "I heard hello!" as a reply (without using wit at this stage). Instead I just receive
debug: RECEIVED MESSAGE
debug: CUSTOM FIND CONVO XXXXXXXXXXXXXX XXXXXXXXXXXXXX
debug: No handler for message_received
after every message I send to facebook messenger bot. In wit it seems like I am getting the messages since I receive messages in my inbox to update the intents.
If there is any code much simpler than the one below I would be very happy to have it so that I can start with something much simpler :).
Thanks
<pre><code>
if (!process.env.page_token) {
console.log('Error: Specify page_token in environment');
process.exit(1);
}
if (!process.env.page_token) {
console.log('Error: Specify page_token in environment');
process.exit(1);
}
if (!process.env.verify_token) {
console.log('Error: Specify verify_token in environment');
process.exit(1);
}
if (!process.env.app_secret) {
console.log('Error: Specify app_secret in environment');
process.exit(1);
}
var Botkit = require('./lib/Botkit.js');
var wit = require('./node_modules/botkit-middleware-witai')({
token: process.env.wit,
minConfidence: 0.6,
logLevel: 'debug'
});
var os = require('os');
var commandLineArgs = require('command-line-args');
var localtunnel = require('localtunnel');
const ops = commandLineArgs([
{name: 'lt', alias: 'l', args: 1, description: 'Use localtunnel.me to make your bot available on the web.',
type: Boolean, defaultValue: false},
{name: 'ltsubdomain', alias: 's', args: 1,
description: 'Custom subdomain for the localtunnel.me URL. This option can only be used together with --lt.',
type: String, defaultValue: null},
]);
if(ops.lt === false && ops.ltsubdomain !== null) {
console.log("error: --ltsubdomain can only be used together with --lt.");
process.exit();
}
var controller = Botkit.facebookbot({
debug: true,
log: true,
access_token: process.env.page_token,
verify_token: process.env.verify_token,
app_secret: process.env.app_secret,
validate_requests: true, // Refuse any requests that don't come from FB on your receive webhook, must provide FB_APP_SECRET in environment variables
});
var bot = controller.spawn({
});
controller.setupWebserver(process.env.port || 3000, function(err, webserver) {
controller.createWebhookEndpoints(webserver, bot, function() {
console.log('ONLINE!');
if(ops.lt) {
var tunnel = localtunnel(process.env.port || 3000, {subdomain: ops.ltsubdomain}, function(err, tunnel) {
if (err) {
console.log(err);
process.exit();
}
console.log("Your bot is available on the web at the following URL: " + tunnel.url + '/facebook/receive');
});
tunnel.on('close', function() {
console.log("Your bot is no longer available on the web at the localtunnnel.me URL.");
process.exit();
});
}
});
});
controller.middleware.receive.use(wit.receive);
controller.hears(['hello'], 'direct_message', wit.hears, function(bot, message) {
bot.reply(message, 'I heard hello!');
});
function formatUptime(uptime) {
var unit = 'second';
if (uptime > 60) {
uptime = uptime / 60;
unit = 'minute';
}
if (uptime > 60) {
uptime = uptime / 60;
unit = 'hour';
}
if (uptime != 1) {
unit = unit + 's';
}
uptime = uptime + ' ' + unit;
return uptime;
}
Make sure you have a few conversations in Wit.ai beforehand so for example hello there and highlight the hello in that statement as something like, greetings.
Now i'm not sure what your intents are called in wit.ai but in your statement controller.hears(['hello'] you're actually listening to the wit.ai intents. So in the example i mentioned above, we'd be using hears(['greetings']) since that's the intent in wit.ai.
Also, instead of using direct_message use message_received this is what it should look like:
controller.hears(['hello'], 'message_received', wit.hears, function(bot, message) {
bot.reply(message, 'I heard hello!');
});
If you're struggling tracking down the problem you can stick a console statement in your controller so something like console.log("Wit.ai detected entities", message.entities); and see what you get back from that.
Let me know if you're still having any issues :)

Getting and "Error, wrong validation token" when trying to create a Facebook Chatbot

I'm trying to create a Facebook chatbot with NodeJS, Express, and a Heroku server.
I created my webhook on heroku and had it verified and saved by facebook. I then started adding code that would reply to the incoming messages and I can't seem to get it connected. It keeps saying "Error, wrong validation token" when I try to load my webhook in my browser. And when I try to send my bot a message I get no response. Even though I already had it verified and didn't change the code.
Here is my code:
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
var port = process.env.PORT || 3000;
// body parser middleware
app.use(bodyParser.urlencoded({ extended: true }));
// test route
//app.get('/', function (req, res) { res.status(200).send('Hello world!') });
app.get('/', function (req, res) {
if (req.query['hub.verify_token'] === '8FKU9XWeSjnZN4ae') {
res.send(req.query['hub.challenge']);
}
res.send('Error, wrong validation token');
})
app.post('/', function (req, res) {
messaging_events = req.body.entry[0].messaging;
for (i = 0; i < messaging_events.length; i++) {
event = req.body.entry[0].messaging[i];
sender = event.sender.id;
if (event.message && event.message.text) {
text = event.message.text;
sendTextMessage(sender, "Text received, echo: "+ text.substring(0, 200));
}
}
res.sendStatus(200);
});
// error handler
app.use(function (err, req, res, next) {
console.error(err.stack);
res.status(400).send(err.message);
});
app.listen(port, function () {
console.log('Listening on port ' + port);
});
var token = <myToken>;
function sendTextMessage(sender, text) {
messageData = {
text:text
}
request({
url: 'https://graph.facebook.com/v2.6/me/messages',
qs: {access_token:token},
method: 'POST',
json: {
recipient: {id:sender},
message: messageData,
}
}, function(error, response, body) {
if (error) {
console.log('Error sending message: ', error);
} else if (response.body.error) {
console.log('Error: ', response.body.error);
}
});
}
So I'm confused as to why nothing is happening and why I'm getting that error. I feel like I'm missing a whole step. I am following this tutorial by the way: https://developers.facebook.com/docs/messenger-platform/quickstart
Any help is appreciated. Thanks!
Edit: Here are my heroku logs
Do not post your full access tokens here!
Have you tested the output of the challenge? Since it's just a GET and you know all values you can try it yourself: your-app-domain.com/your-callback-url?hub_mode=subscribe&hub_verify_token=the_token_you_set_in_your_app_config&hub_challenge=ping which sould print 'ping' if everything work fine.
Make sure you add sendStatus(200) to the hub challenge response, too.
You need to subscribe your page to the app first. To do so make a POST request to /your-page-id/subscribed_apps which should return "success". You can make a GET request to the same endpoint afterwards to double check your app is subscribed to your page
You did not mention which events you subscribed to (needs to be message_deliveries, messages, messaging_optins, messaging_postbacks)
Make sure the webhooks tab in your app dashboard now says "complete"
Test again
You are actually using "request" but you are never importing it anywhere. Here's how to fix it:
var request = require("request")
Once you have added that to your index.js or app.js file (basically whatever this file is), make sure you do:
npm install request --save
This should fix it. Unfortunately, Heroku doesn't error out and say that it does not know what "request" is and that's why it was so hard to figure this out in the first place!

How send string/image base64 to Sailsjs - Skipper with ajax

Currently I am capturing the image of the camera, this Base64 format,and I'm sending through ajax.
xhr({
uri: 'http://localhost:1337/file/upload',
method: 'post',
body:'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAA...'
}
0 file(s) uploaded successfully!
Here is a nice link that will guide you to do send an image from an Ajax Client to an ajax server.
http://www.nickdesteffen.com/blog/file-uploading-over-ajax-using-html5
You can read this sails documentation to receive files on a sails server :
http://sailsjs.org/documentation/reference/request-req/req-file
You can do as the following example :
Client side ( ajax ):
var files = [];
$("input[type=file]").change(function(event) {
$.each(event.target.files, function(index, file) {
var reader = new FileReader();
reader.onload = function(event) {
object = {};
object.filename = file.name;
object.data = event.target.result;
files.push(object);
};
reader.readAsDataURL(file);
});
});
$("form").submit(function(form) {
$.each(files, function(index, file) {
$.ajax({url: "/ajax-upload",
type: 'POST',
data: {filename: file.filename, data: file.data}, // file.data is your base 64
success: function(data, status, xhr) {}
});
});
files = [];
form.preventDefault();
});
Server side ( sails ) :
[let's say you have a model Picture that take an ID and a URL]
[here is a sample of Picture controller, just to give you an idea]
module.exports = {
uploadPicture: function(req, res) {
req.file('picture').upload({
// don't allow the total upload size to exceed ~10MB
maxBytes: 10000000
},
function onDone(err, uploadedFiles) {
if (err) {
return res.negotiate(err);
}
// If no files were uploaded, respond with an error.
if (uploadedFiles.length === 0){
return res.badRequest('No file was uploaded');
}
// Save the "fd" and the url where the avatar for a user can be accessed
Picture
.update(777, { // give real ID
// Generate a unique URL where the avatar can be downloaded.
pictureURL: require('util').format('%s/user/pictures/%s', sails.getBaseUrl(), 777), // GIVE REAL ID
// Grab the first file and use it's `fd` (file descriptor)
pictureFD: uploadedFiles[0].fd
})
.exec(function (err){
if (err) return res.negotiate(err);
return res.ok();
});
});
}
};
Hope this will help in your research.
I also recommand you to use Postman to test your API first, then code your client.