vlucas / frisby

Frisby is a REST API testing framework built on Jest that makes testing API endpoints easy, fast, and fun.

Home Page:http://frisbyjs.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

can imap service integrated with jest and frisby

amrsa1 opened this issue · comments

Im trying to perform some API test using frisby and jest framework, what i want to do is it integrate mail-listener4 with jest so i can verify some mail contents as shown in the it block below.

fit('1- Verify by sending new user feedback, API will return status code 200', ()=> {
        flow.execute(getLastEmail);
        return frisby
            .post('https://sddctrl.com/api/users/userFeedback', {
                relatedTo: "endpoints",
                description: "test user feedback functionality ",
                userFeedbackFile: [218],
                userFeedbackContactInsertRequests: [{contactTypeId: 1}],
            })
            // .expect('status', 200)
            .then(function (email) {
                expect(email.subject)
                    .toEqual('dthsdeserds@thsdessdemso.com submitted feedback');
                expect(email.headers.to)
                    .toEqual('assddm@msddtions.com');
                expect(email.html.includes('User feedback details: accountId: 12345, related To: account-overview, description: ' + D.feedbackMsg + ''))
                    .toEqual(true);
                console.log(email.html);
                // console.log(email['text']);
            });
    })

its working fine when i integrate it with jasmine2 and protractor in config file since there are many reference here below is my working sample in jasmine2.

const Jasmine2HtmlReporter = require('protractor-jasmine2-html-reporter');
const HtmlReporter = require('protractor-beautiful-reporter');
const q = require('q');
const fs = require('fs');
const nodemailer = require('nodemailer');
const smtpTransport = require('nodemailer-smtp-transport');
const SpecReporter = require('jasmine-spec-reporter').SpecReporter;
const SendMail = function () {
	this.sendHTMLMail = function (htmlContent) {
		const transporter = nodemailer.createTransport(smtpTransport({
			service: 'Gmail',
			host: 'smtp.gmail.com',
			port: 465,
			auth: {
				user: '',
				pass: '',
			},
		}));
		const mailOptions = {
			from: 'Amr',
			to: [''],
			subject: '[no-reply] Automatic Generated Automation Test Report',
			text: 'Amr Kamel',
			html: htmlContent,
			mailParserOptions: { streamAttachments: true },
			attachments: [{
				// filename: '1234.jpg',
				// path: './autoReport/1234.jpg'
			}]
		};
		transporter.sendMail(mailOptions, function (error, info) {
			if (error) {
				return console.log(error);
			}
			console.log('Mail sent: ' + info.response);
		});
	};
};
exports.config = {
	framework: 'jasmine2',


	onPrepare() {

		jasmine.getEnv().addReporter(
			new Jasmine2HtmlReporter({
				savePath: './autoReport/reports/',
				screenshotsFolder: 'images',
				showPassed: false,
				takeScreenshotsOnlyOnFailures: true
			})
		);

		const t = new Date();
		t.setSeconds(t.getSeconds());

		const MailListener = require('mail-listener4');

		const mailListener = new MailListener({
			username: '',
			password: '0000',
			host: 'imap.gmail.com',
			port: 993, // imap port
			tls: true,
			  tlsOptions: { rejectUnauthorized: false },
			mailbox: 'INBOX', // mailbox to monitor
			searchFilter: ['UNSEEN', ['SINCE', t]], // the search filter being used after an IDLE notification has been retrieved
			markSeen: true, // all fetched email willbe marked as seen and not fetched next time
			fetchUnreadOnStart: true, // use it only if you want to get all unread email on lib start. Default is `false`,
			mailParserOptions: { streamAttachments: true }, // options to be passed to mailParser lib.
		});

		mailListener.on('server:connected', function () {
			console.log('imapConnected');
		});

		mailListener.on('server:disconnected', function () {
			console.log('imapDisconnected');
		});

// this is where it starts to differ from the first sample

// A more complex example.
// Get the first 20 (UNSEEN) emails, mark them read (\SEEN),
// and archive them.
		(function () {
			// make sure you include in options:
			//   fetchUnreadOnStart: true,
			let count = 0;
			mailListener.on('mail', function (mail, seqno, attributes) {
				const mailuid = attributes.uid;
					const toMailbox = 'All Mail';
					const i = ++count;

				if (i > 20) {
					mailListener.stop(); // start listening
					return;
				}

				console.log('email parsed', {
					i,
					subject: mail.subject,
					headers: mail.headers,
					body: mail.body,
					seqno,
					uid: attributes.uid,
					attributes
				});

				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

// Time out need to check the recieved email and mark it as unseen
		setTimeout(function () {
				mailListener.stop(); // start listening
			},
			60 * 60 * 1000);
		global.mailListener = mailListener;
	},

	params: {
		getLastEmail() {
			const deferred = protractor.promise.defer();
			console.log('Waiting for email...');

			let count = 0;
			mailListener.on('mail', function (mail, seqno, attributes) {
				const mailuid = attributes.uid;
				const toMailbox = 'All Mail';
				const i = ++count;
				if (i > 2) {
					mailListener.stop(); // start listening
					return;
				}
				testContent = {
					i,
					subject: mail.subject,
					seqno,
					uid: attributes.uid,
					attributes,
					text: mail.text
				};
				deferred.fulfill(mail);
			});
			return deferred.promise;
		}
	},

	onComplete() {
		mailListener.stop();
	},

	afterLaunch() {
		return q.fcall(function () {
			//  generate HTML report

			//  Send HTML Email
			const htmlFilePath = './autoReport/reports/htmlReport.html';
			const htmlFileContent = String(fs.readFileSync(htmlFilePath));
			(new SendMail()).sendHTMLMail(htmlFileContent);
		}).delay(4000);
		},


	// Options to be passed to Jasmine.
	jasmineNodeOpts: {
		defaultTimeoutInterval: 100000,

	},
};

The main difference between many Jasmine and Jest test runners is that Jest is much better at full test isolation and running the tests in parallel and random order. My gut feeling here is that if the code is the same on both tests, it is likely a timing/async issue. As in, perhaps the email was not sent yet before the Frisby test ran? What specific error are you getting back?

The main difference between many Jasmine and Jest test runners is that Jest is much better at full test isolation and running the tests in parallel and random order. My gut feeling here is that if the code is the same on both tests, it is likely a timing/async issue. As in, perhaps the email was not sent yet before the Frisby test ran? What specific error are you getting back?

yes i believe its something should be done on code level, here below is the method that is already working on other framwork that work with jasmine , the code snippet below didnt work with me with jest and i didnt get any output just test is executed normally and nothing is happening after, its SMTP service using nodmailer but if know how to get this one to work i think will be able to integrate imap service as well

U.Login_to_testing_env = async function (username,password) {
    await U.Post_request_advanced('https://test.ice.test.com/v1.0/endpoint/default/token','qs',
        {
            'client_id': '7a1e1dbf-caab-413',
            'grant_type': 'password',
            'username': username,
            'password': password,
            'client_secret': 'test',},
        {
            'Content-Type': 'application/x-www-form-urlencoded'
        },200)
        .then(res=>{
            let Body = JSON.parse(res.body);
            let access_token = Body.access_token;
            let authorization = 'Bearer ' + access_token;
            console.log('access_token', access_token);
            frisby
                .globalSetup({
                    request: {
                        baseUrl: baseUrl,
                        headers: {
                            'account-id': 'default',
                            authorization : authorization
                        }
                    }
                })
        })
}

const writeScreenShot =  function(data, filename) {
    const stream = fs.createWriteStream(filename);
    stream.write(new Buffer.from(data, 'base64'));
    stream.end();
}

const SendMail =  function () {

    const name = process.env.E2E_ENV;
    const envName = name.charAt(0).toUpperCase() + name.slice(1);

    this.sendHTMLMail =  function (htmlContent) {
        const transporter = nodemailer.createTransport(smtpTransport({
            service: 'Gmail',
            host: 'smtp.gmail.com',
            port: 465,
            auth: {
                user: process.env.SMTP_USER,
                pass: process.env.SMTP_PWD,
            },
        }));
        const mailOptions = {
            from: 'Amr kamel',
            to: ['amrka@test.com'],
            subject: envName + ' API Automation Test Report',
            text: 'Amr Kamel',
            html: htmlContent,
            mailParserOptions: {streamAttachments: true},
            attachments: [{
                filename: 'exception.png',
                path: './exception.png'
            }]
        };
        transporter.sendMail(mailOptions, function (error, info) {
            if (error) {
                return console.log(error);
            }
            console.log('Mail sent: ' + info.response);
        });
    };

    U.Send_Email_Notification = async function () {
        browser.takeScreenshot().then(function (png) {
            writeScreenShot(png, 'exception.png');
        }).then(function () {
            return q.fcall(function () {
                //  generate HTML report

                //  Send HTML Email
                const htmlFilePath = '__tests__\\suite\\testing\\test-report.html';
                const htmlFileContent = String(fs.readFileSync(htmlFilePath));
                (new SendMail()).sendHTMLMail(htmlFileContent);
            }).delay(4000);
        })
    }
};

module.exports = U;

this i call this method in afterAll

import {afterAll, beforeAll, describe} from "@jest/globals";

describe ('API Login Test',()=> {

    beforeAll( async ()=> {

      await U.Post_request_advanced('https://test.ice.test.com/v1.0/endpoint/default/token','qs',
          {
              'client_id': 'test',
              'grant_type': 'password',
              'username': D.email('amrka'),
              'password': D.password('amrka'),
              'client_secret': 'test',},
          {
              'Content-Type': 'application/x-www-form-urlencoded'
          },200)
            .then(res=>{
                let Body = JSON.parse(res.body);
                let access_token = Body.access_token;
                let authorization = 'Bearer ' + access_token;
                console.log('access_token', access_token);
                frisby
                    .globalSetup({
                        request: {
                            baseUrl: baseUrl,
                            headers: {
                                'account-id': 'default',
                                authorization : authorization
                            }
                        }
                    })
            })
    });

    afterAll(async ()=>{
       await U.Send_Email_Notification()
    })

it('',....etc)
}

what is happening that test is running normal and nothing is happening after all test being executed like the method doesn't exist