Protractor E2E testing; Verifying account activation email - javascript

I am trying to create a script for email verification. I mean when we create an account on the site, then a verification mail will come to the given mail address and then we have to go to that mail and verify it(clicking on the link/or fetching the code). I tried this solution. But I have got stuck on the specific error.
This is code which I am trying.
describe("Sample test case", function () {
function getLastEmail() {
let deferred = protractor.promise.defer();
console.log("Waiting for an email...");
mailListener.on("mail", function(mail){
deferred.fulfill(mail);
});
return deferred.promise;
}
beforeAll(function () {
browser.waitForAngularEnabled(false);
browser.get("https://mail.google.com/mail/");
isAngularSite(false);
browser.sleep(3000);
});
it("should login with a registration code sent to an email", function () {
element(by.id("username")).sendKeys("MyemailID");
element(by.id("password")).sendKeys("mypassword");
element(by.id("loginButton")).click();
browser.controlFlow().await(getLastEmail()).then(function (email) {
expect(email.subject).toEqual("BillPledge Email Verification");
expect(email.headers.to).toEqual("support#billpledge.com");
// extract registration code from the email message
let pattern = /Registration code is: (\w+)/g;
let regCode = pattern.exec(email.text)[1];
console.log(regCode);
});
});
});
and this is my conf file.
// An example configuration file.
exports.config = {
// The address of a running selenium server.
// seleniumAddress: 'http://localhost:4444/wd/hub',
// if we are using protractor's webdriver-manager locally, you cannot use selenium Address
// If the webdriver-manager needs to start a local server, you can use
selenium: 'http://localhost:4445/wd/hub',
seleniumPort: 4445, // Port matches the port above
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'chrome'
},
// Spec patterns are relative to the current working directly when
// protractor is called.
specs: ['./e2eTest/GmailTest.js'],
// Options to be passed to Jasmine-node.
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 300000
},
allScriptsTimeout: 200000,
onPrepare: function () {
global.isAngularSite = function (flag) {
browser.ignoreSynchronization = !flag;
};
browser.driver.manage().window().maximize();
//To generate the report.
let HtmlReporter = require('protractor-beautiful-reporter');
jasmine.getEnv().addReporter(new HtmlReporter({
baseDirectory: 'Results/Report'
}).getJasmine2Reporter());
let reporter = new HtmlReporter({
baseDirectory: 'Results/Report'
});
let path = require('path');
new HtmlReporter({
baseDirectory: 'Results/Report'
, preserveDirectory: false
, cssOverrideFile: 'css/style.css'
, takeScreenShotsForSkippedSpecs: true
, screenshotsSubfolder: 'images'
, jsonsSubfolder: 'jsons'
, takeScreenShotsOnlyForFailedSpecs: false
, gatherBrowserLogs: true
, pathBuilder: function pathBuilder(spec, descriptions, results, capabilities) {
// Return '<browser>/<specname>' as path for screenshots:
// Example: 'firefox/list-should work'.
return path.join(capabilities.caps_.browser, descriptions.join('-'));
}
, metaDataBuilder: function metaDataBuilder(spec, descriptions, results, capabilities) {
// Return the description of the spec and if it has passed or not:
return {
description: descriptions.join(' ')
, passed: results.passed()
};
}
});
let MailListener = require("mail-listener2");
// here goes your email connection configuration
let mailListener = new MailListener({
username: "myemailid",
password: "mypassword",
host: "imap.gmail.com",
port: 993, // imap port
tls: true,
tlsOptions: {rejectUnauthorized: false},
mailbox: "INBOX", // mailbox to monitor
searchFilter: ["UNSEEN", "FLAGGED"], // 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.
attachments: true, // download attachments as they are encountered to the project directory
attachmentOptions: {directory: "attachments/"} // specify a download directory for attachments
});
mailListener.start();
mailListener.on("server:connected", function () {
console.log("Mail listener initialized");
});
global.mailListener = mailListener;
},
onCleanUp: function () {
mailListener.stop();
},
};
But while executing the script I am getting following error. The error is:
Error: Please log in via your web browser:
https://support.google.com/mail/accounts/answer/78754 (Failure)
and
Failed: browser.controlFlow(...).await is not a function
I know I am doing some mistake but I am not able to figure out. So can anyone can help me in pointing out and solve it, not solve but at least some suggestion which can help in running this script perfectly.
Thanks

Try to use browser.wait(getLastEmail) instead of browser.controlFlow().await(getLastEmail()

Related

Keycloak Javascript failed to inicialize

I'm trying to use Keycloak with JavaScript and these are the steps that I followed.
I create a client inside KeyCloak admin panel.
Link to image
I copy the .json file to my apache folder.
{
"realm": "master",
"auth-server-url": "http://localhost:8080/auth",
"ssl-required": "external",
"resource": "test",
"public-client": true,
"confidential-port": 0
}
I go to my index.html and I add these two lines for calling the script.
<script src="keycloak.js"></script>
<script>
function initKeycloak() {
const keycloak = new Keycloak();
keycloak.init().then(function(authenticated) {
alert(authenticated ? 'authenticated' : 'not authenticated');
}).catch(function() {
alert('failed to initialize');
});
}
</script>
this is what i have in myLogical.js
var keycloak = new Keycloak();
function initKeycloak() {
keycloak.init({onLoad: 'login-required'}).then(function() {
constructTableRows(keycloak.idTokenParsed);
pasteToken(keycloak.token);
}).catch(function() {
alert('failed to initialize');
});
}
function constructTableRows(keycloakToken) {
document.getElementById('row-username').innerHTML = keycloakToken.preferred_username;
document.getElementById('row-firstName').innerHTML = keycloakToken.given_name;
document.getElementById('row-lastName').innerHTML = keycloakToken.family_name;
document.getElementById('row-name').innerHTML = keycloakToken.name;
document.getElementById('row-email').innerHTML = keycloakToken.email;
}
function pasteToken(token){
document.getElementById('ta-token').value = token;
document.getElementById('ta-refreshToken').value = keycloak.refreshToken;
}
var refreshToken = function() {
keycloak.updateToken(-1)
I tried to download the file keycloak.js and put it directly on my root folder but it happen the same problem.
These is the message I got when I try to open the page
I'm confused about point 1, does keycloak automatically load configuration from json file in Apache folder? Let's assume that no, and I think that where your problem lies, you're not passing config param to keycloak constructor.
How to initialize keycloak:
const initKeycloak = async () => {
//you can hardcode these values for now just to see if everything works
const config = { url: 'http://localhost:8080/auth', realm: 'master', clientId: 'test'};
const keycloak = new Keycloak(config);
await keycloak
.init({ onLoad: 'login-required' })
.then(isAuthenticated => {
//user is authenticated
})
.catch(error => { console.log('keycloak error', error); });
}
Another important thing is that keycloak-js library version (in package.json) must match keycloak server version. Sometimes different versions work with each other but it's always best practice that keycloak-js version matches keycloak server version.
You can also look here: https://github.com/m-s7/react-core/blob/devel/src/services/keycloak-service.ts this is my repo with working keycloak-js implementation.

Re-use a defined variable in multiple Nightwatchjs test steps

Ok, so I know this is probably going to be something obvious and straightforward, but I just can't seem to get it to work.
Using the Nigthwatchjs perform command, I'm trying to re-use a variable from a step into the next step.
Below is a snippet of my code from my test script;
'2) Breadcrumbs': function (browser) {
browser.perform(function() {
var testMake = browser.globals.specsTestMake;
var testModel = browser.globals.specsTestModel;
var testRange = browser.globals.specsTestRange;
var testYear = browser.globals.specsTestYear;
browser.assert.containsText('nav.site-breadcrumbs', 'Home', testMake, testModel, testRange, testYear, 'specs');
console.log('test make from step 2 = ', testMake);
});
},
'3) Heading': function (browser) {
browser.perform(function(testMake, done) {
console.log('test make from step 3 = ', testMake);
done();
});
},
The console.log from the first step, '2) Breadcrumbs' is correctly displayed (for this test example) as BMW, as defined in the globals file.
I therefore thought that the console.log for the second step, '3) Heading' would also be correctly displayed as BMW.
However, this is not the case.
The second console.log displays what appears to be the entire page, settings, etc.
A small snippet is below;
✔ 2) Breadcrumbs (26ms)
test make from step 3 = { capabilities:
{ acceptInsecureCerts: true,
acceptSslCerts: true,
applicationCacheEnabled: false,
browserConnectionEnabled: false,
browserName: 'chrome',
chrome:
{ chromedriverVersion: '2.44.609545 (c2f88692e98ce7233d2df7c724465ecacfe74df5)',
userDataDir:
'/var/folders/6x/3kzp0zhd6vv0q_mfstkxd73m0000gr/T/.org.chromium.Chromium.iDQCXI' },
cssSelectorsEnabled: true,
databaseEnabled: false,
'goog:chromeOptions': { debuggerAddress: 'localhost:52102' },
handlesAlerts: true,
Any idea on what I'm doing wrong with my perform command?
Thanks

A Jasmine spec timed out. Resetting the WebDriver Control Flow

I am getting
Jasmine spec timed out. Resetting the WebDriver Control Flow.
I have also used fakesyn before but getting same error message as above.
Please help me
This is my specs:
describe('CW Login Page', function() {
var username;
var password;
var login;
beforeEach(() => {
browser.waitForAngularEnabled(false);
browser.get('http://www.testing.com/');
console.log('after link await');
});
it('should find the element and send the parameters', fakeAsync(() => {
setTimeout(function() {
value=0;
console.log('Inside it function');
username = element(by.id('userIDInput'));
password= element(by.id('passwordInput'));
login= element(by.id('login'));
console.log('After await');
username.sendKeys('abc');
password.sendKeys('abc');
login.click();
console.log("After it function");
},5000);
tick(5000);
}));
`beforeEach`(() => {
console.log('\r\n ---=== TESTS FINISHED!!! ===--- \r\n');
});
});
This is my config:
exports.config = {
allScriptsTimeout: 50000,
getPageTimeout:40000,
framework:'jasmine2',
/*seleniumAddress: 'http://localhost:4723/wd/hub', // Ignored if directConnect is true
specs: ['loginpage.js'],*/
seleniumAddress: 'https://hub.testingbot.com/wd/hub',
specs: ['./src/loginpage_fakeasync.e2e-specs.js'],
seleniumArgs: ['--dev-server-target'], // '--dev-server-target' ],
directConnect: false, //Change this to true for your local testing
multiCapabilities: [{ // in 1 chrome run the 10 specs sequentially
browserName: 'chrome',
platform: 'Android',
version: '7.1',
platformName: 'Android',
deviceName: 'Pixel 2',
client_key: "abc",
client_secret: "xyz"
}],
jasmineNodeOpts: {
onComplete: null, //jasmine framework details
isVerbose: false,
showColors: true,
includeStackTrace: true,
defaultTimeoutInterval: 40000,
print: function() {}
I expect to open the webpage and login using the automation script. If someone can figure out the error it would be a great help
I am getting
Jasmine spec timed out. Resetting the WebDriver Control Flow.
I have also used fakesyn before but getting same error message as above.
Please help me
The control flow should keep everything running in sync so the fakeAsync & setTimeout should not be required. If your framework is not too large then you should consider disabling the control flow and using the async/await style of handling promises.
I doubt this will solve your issue but can you try the below code and post the results.
describe('CW Login Page', function () {
var username;
var password;
var login;
beforeEach(() => {
browser.waitForAngularEnabled(false);
browser.get('http://www.testing.com/');
console.log('after link await');
});
it('should find the element and send the parameters', () => {
value = 0;
console.log('Inside it function');
username = element(by.id('userIDInput'));
password = element(by.id('passwordInput'));
login = element(by.id('login'));
console.log('After await');
username.sendKeys('abc');
password.sendKeys('abc');
login.click();
console.log("After it function");
})
afterEach(() => {
console.log('\r\n ---=== TESTS FINISHED!!! ===--- \r\n');
}
});

#sentry/node integration to wrap bunyan log calls as breadcrumbs

Sentry by defaults has integration for console.log to make it part of breadcrumbs:
Link: Import name: Sentry.Integrations.Console
How can we make it to work for bunyan logger as well, like:
const koa = require('koa');
const app = new koa();
const bunyan = require('bunyan');
const log = bunyan.createLogger({
name: 'app',
..... other settings go here ....
});
const Sentry = require('#sentry/node');
Sentry.init({
dsn: MY_DSN_HERE,
integrations: integrations => {
// should anything be handled here & how?
return [...integrations];
},
release: 'xxxx-xx-xx'
});
app.on('error', (err) => {
Sentry.captureException(err);
});
// I am trying all to be part of sentry breadcrumbs
// but only console.log('foo'); is working
console.log('foo');
log.info('bar');
log.warn('baz');
log.debug('any');
log.error('many');
throw new Error('help!');
P.S. I have already tried bunyan-sentry-stream but no success with #sentry/node, it just pushes entries instead of treating them as breadcrumbs.
Bunyan supports custom streams, and those streams are just function calls. See https://github.com/trentm/node-bunyan#streams
Below is an example custom stream that simply writes to the console. It would be straight forward to use this example to instead write to the Sentry module, likely calling Sentry.addBreadcrumb({}) or similar function.
Please note though that the variable record in my example below is a JSON string, so you would likely want to parse it to get the log level, message, and other data out of it for submission to Sentry.
{
level: 'debug',
stream:
(function () {
return {
write: function(record) {
console.log('Hello: ' + record);
}
}
})()
}

ExtJs 5 - launch function not executed in Ext.application

I am new to extjs, and I try to integrate extjs 5 with django 1.7 on my localhost. I have set the backend and got the rest api work (at /api/), as at https://github.com/MaZderMind/django-vs-extjs , but when the index.html runs app.js, which displays the login page, it seems that:
The controller file (Login.js) isn't loaded,
the launch function is not executed.
In firebug I can see that it reads the function definition and then returns without executing it automatically (also, when defining controller it steps over like it is simple command, but on the require statement steps into the function that fetches them), hence the login page is not displayed. But the other js files (for authentication) are loaded, as I see in console. Do you have any ideas what is happening? The codes are:
app.js
Ext.Loader.setConfig({enabled:true});
Ext.application({
// base-package of all classes
name: 'MyApp',
// url to load js-files from - adapted to django project
appFolder : 'static/static',
// required controllers
controllers: ['Login'],
// other required components
requires: [
'MyApp.helper.CrsfTokenHelper',
'MyApp.helper.PhantomStoreInserter'
],
// application launch method
launch: function () {
// save the scope
var app = this;
console.log('launched');
// ensure the user is logged in before showing her the main navigation with all our application goodies
app.getController('Login').ensureLoggedIn(function(userinfo) {
console.log('Login-Controller ensured that user', userinfo.username, 'is is currently loggeg in. Proceeding to navigation.')
// upate display of the navigation conteoller and show it
//app.getController('Navigation')
//.updateUserinfo(userinfo)
//.view.show();
console.log('Here should be loaded the view after the login page');
});
}
});
Login.js (controller)
Ext.define('MyApp.controller.Login', {
extend: 'Ext.app.Controller',
mixins: ['Ext.mixin.Observable'],
views: ['Login'],
// pointers into the view
refs: [
{ 'ref': 'userField', selector: '#user' },
{ 'ref': 'passField', selector: '#pass' },
{ 'ref': 'submitButton', selector: '#submit' }
],
// stored user information as received from the server
userinfo: null,
// controller initialisation
init: function() {
// save the scope
var loginController = this;
// create an instance of the view
var win = loginController.loginWindow = loginController.getView('Login').create();
this.control({
// register for the login-click
'#submit': {
click: function() {
// retrieve username & password from view
var username = this.getUserField().getValue(), password = this.getPassField().getValue();
// mask the form out
win.mask('Verifying…');
// process the login with the backend
loginController.performLogin(username, password, function(success) {
// the user was successfully authorized
if(success) {
// now request additional information on the user (name and such)
loginController.fetchLoginStatus(function(userinfo) {
// test if the server responded with data as expected
if(userinfo) {
// hide the login-window
win.hide();
// store received information locally
loginController.userinfo = userinfo;
// raise a event on the controller when finished
loginController.fireEvent('login', userinfo);
loginController.fireEvent('ready', userinfo);
}
// we did not receive valid data from the server
// this sould not fail, but if it does, just handle it like a failed login
else {
// disable the login on the form
win.unmask();
// set error-message on password-field
loginController.clearPasswordAndFocus().setPasswordError('Invalid Username or Password!');
}
})
}
// authorization was not successful
// unmask the form, show an error message and restart login process
else {
win.unmask();
loginController.clearPasswordAndFocus().showError('Invalid Username or Password!');
}
})
}
}
});
// register keyboard handler
this.nav = new Ext.KeyNav(win.getEl(), {
// enter key -> login-button click
enter: function() {
loginController.getSubmitButton().fireEvent('click')
}
});
},
// test if the user is logged in.
// if she is, call back immediatly. if she is not, show a login form
// delay the callback until she logged in successfully
ensureLoggedIn: function(callback) {
// save the scope
var loginController = this;
// test if the backend knows us
loginController.fetchLoginStatus(function(userinfo) {
// analyze if a user is logged in
if(userinfo) {
// callback, if she is
loginController.userinfo = userinfo;
loginController.fireEvent('ready', userinfo);
return callback(userinfo);
}
// no, we're not. show the login-window
console.log('no user logged in, showing login-window');
// login-testing and re-trying is handled by the handler set in the init-method
// it raises an event on the controller once it is finished
// we listen on this event and relay it to our callback - but only once
// -> the callback shouldn't be called multiple times
loginController.on('login', callback, {single: true});
// initiate login procedure by showing the login window
loginController.loginWindow.show();
loginController.clearForm();
});
},
// ask the backend if and which user is currently logged in
fetchLoginStatus: function(callback) {
console.info('requesting current userinfo from backend');
Ext.Ajax.request({
url: '/api/auth/user/',
success: function(response) {
// decode json-response
var userinfo = Ext.util.JSON.decode(response.responseText);
// request user permission list
Ext.Ajax.request({
url: '/api/auth/permissions/',
success: function(response) {
// decode json-response
userinfo.permissions = Ext.util.JSON.decode(response.responseText);
// callback with the decoded response
console.log('received userinfo:', userinfo);
callback(userinfo);
},
failure: function(response) {
// callback without info
console.log('received no permission list - nobody logged in');
callback();
}
});
},
failure: function(response) {
// callback without info
console.log('received no userinfo - nobody logged in');
callback();
}
});
},
// submit username & password to the backend
performLogin: function(username, password, callback) {
console.info('trying to log into backend with username=', username, 'password=', password.length, 'Chars');
// send login data via ajax to the server and callback with result
Ext.Ajax.request({
url: '/api/auth/login/',
method: 'POST',
params: {
'username': username,
'password': password
},
success: function(){
callback(true);
},
failure: function() {
callback(false);
}
});
},
// ask the backend to throw away our session which makes us logged out
performLogout: function(callback) {
console.info('trying to log out from backend');
// ensure userinfo is unset
this.userinfo = null;
Ext.Ajax.request({
url: '/api/auth/logout/',
method: 'GET',
success: function(){
callback(true);
},
failure: function() {
callback(false);
}
});
},
// shorthand to test iff userinfo is available
isLoggedIn: function() {
// null -> false, string -> true
return !!this.userinfo;
},
// shorthand to get the current username
getUserinfo: function() {
return this.userinfo;
},
// shorthand to get the current username
getUsername: function() {
return this.isLoggedIn() ? this.getUserinfo().username : null;
},
// shorthand to get the current username
getPermissions: function() {
return this.isLoggedIn() ? this.userinfo.permissions.user_permissions : [];
},
// shorthand to get the current username
isSuperuser: function() {
return this.isLoggedIn() ? this.userinfo.permissions.is_superuser : [];
},
hasPermission: function(permission) {
return this.isLoggedIn() && (this.isSuperuser() || this.getPermissions().indexOf(permission) !== -1)
},
// clears all form elements in the view
clearForm: function() {
this.loginWindow.unmask();
this.getPassField().setValue('').unsetActiveError();
this.getUserField().setValue('').unsetActiveError();
this.getUserField().focus();
return this;
},
// clears the password-field in the view and sets the typing-focus to it
clearPasswordAndFocus: function() {
this.getPassField().setValue('').focus();
return this;
},
// set an error-message on the password-fieldy
setPasswordError: function(msg) {
this.getPassField().setActiveErrors([msg]);
return this;
}
});
Login.js (view)
Ext.define('MyApp.view.Login', {
extend: 'Ext.window.Window',
renderTo: Ext.getBody(),
id: "loginBox",
title: 'Login',
width: 400,
layout: 'form',
bodyPadding: 5,
closable: false,
resizable: false,
draggable: false,
defaultFocus: 'user',
defaultType: 'textfield',
items: [{
itemId: 'user',
fieldLabel: 'Username',
allowBlank: false
},{
inputType: 'password',
fieldLabel: 'Password',
itemId: 'pass',
allowBlank: false
}],
buttons: [{
text: 'Login',
itemId: 'submit'
}]
});
console output:
GET localhost /static/static/helper/CrsfTokenHelper.js?_dc=1414444486439 200 OK 3ms ext-all-debug.js (line 1010)
GET localhost /static/static/helper/PhantomStoreInserter.js?_dc=1414444486439 200 OK 2ms ext-all-debug.js (line 1010)
Thanks anyway!
Well, apparently you are getting errors with your required files. If you comment the requires line inside your Ext.application:
Ext.application({
// base-package of all classes
name: 'MyApp',
// url to load js-files from - adapted to django project
appFolder : 'static/static',
// required controllers
controllers: ['Login'],
// other required components
//requires: [
// 'MyApp.helper.CrsfTokenHelper',
// 'MyApp.helper.PhantomStoreInserter'
//],
...
});
You will see that your Login window will show up. Assuming of course that you have your folder structure setup correctly
index.html
app.js
static/
static/static/
static/static/controller/Login.js
static/static/view/Login.js

Categories