Skip to content

Instantly share code, notes, and snippets.

@Xotabu4
Created August 8, 2017 09:08
Show Gist options
  • Save Xotabu4/011d728752507f6a2d4775fd8659cfc4 to your computer and use it in GitHub Desktop.
Save Xotabu4/011d728752507f6a2d4775fd8659cfc4 to your computer and use it in GitHub Desktop.
Little nodejs http server for serving users to protractor parallel runs, so each thread will get unique user.
/**
* Created by akhotemskyi on 8/18/16.
*/
const request = require('request');
let http = require('http');
let accounts;
let server;
/**
* Accepts array of object with users, that should be served thru HTTP server.
* This needs to provide reliable way to get user for parallel test run.
*
* Array example - [{username: name, password: passw}, {username:name, password: passwd} ... ]
*
* Think of this as external users provider.
*
* GET /get - replies with one of the available users, removes it from list of available users
* GET /return?account=accountName - puts back user to list of available users, replies with user that was returned
* GET /list - replies with JSON with list of available users
*
* Why do we need separate server, can we just use global object?
* Unfortunately no - global object is not shared between all browser instances, so each will get their own list.
* In order to have list of accounts as singleton, we are storing it in this server.
*
*/
exports.startAccountProviderService = function (providedAccounts) {
accounts = providedAccounts;
const PORT = 12000; //TODO: Hardcoded, find way to dynamically find free port
const ADDRESS = `http://localhost:${PORT}`
function accountProviderService(request, response) {
if (request.url.includes('/get')) {
let account = accounts.pop();
response.end(JSON.stringify(account));
console.log(`Account Provider Service: Providing User - ${JSON.stringify(account)}`);
} else if (request.url.includes('/return')) {
var url = require('url');
var query = url.parse(request.url, true).query;
let account = { username: query.username, password: query.password };
accounts.push(account);
response.end(JSON.stringify(account));
console.log(`Account Provider Service: User Returned - ${JSON.stringify(account)}`);
} else if (request.url.includes('/list')) {
response.end(JSON.stringify(JSON.stringify(account)));
}
}
server = http.createServer(accountProviderService);
server.listen(PORT, function () {
console.log("userProviderService server listening on: http://localhost:%s", PORT);
console.log('userProviderService has the following accounts to choose from:');
console.log(accounts);
});
server.unref(); // Making server die when node app (our tests) is dead or finished. So there won't be zombie process.
};
/**
* Receive user from running service, and put it to browser.params.
* Do not forget to call returnUser(user) when you no longer need it, or you will run out of accounts.
* @returns Promise, that will be resolved once user obtained and saved to params.
*/
exports.putUserToParams = function () {
var deferred = protractor.promise.defer();
request.get({ url: `${ADDRESS}/get` }, (error, response, body) => {
if (error || response.statusCode !== 200) {
console.error(`Account Provider Service: Error on attempt to GET http://localhost:12000/get : ${response.statusCode} : ${error}`);
}
let account = JSON.parse(body);
browser.params.user.name = account.username;
browser.params.user.password = account.password;
console.log('Account Provider Service: Pushing to params:');
console.log(' params.user.name = ' + browser.params.user.name);
console.log(' params.user.password = ' + browser.params.user.password);
deferred.fulfill(account)
});
return deferred.promise;
};
/**
* Returns user from browser.params by default, or your provided user back to server, so it could be used by other threads.
* @param userObject special formated object to return
*/
exports.returnUser = function (userObject = { username: browser.params.user.name, password: browser.params.user.password }) {
request.get({
url: `${ADDRESS}/return`,
qs: userObject
}, (error, response, body) => {
if (error || response.statusCode !== 200) {
console.error(`Account Provider Service: Error on attempt to GET ${ADDRESS}/return : ${response.statusCode} : ${error}`);
}
console.log('Account Provider Service: Returning:');
console.log(' params.user.name = ' + userObject.username);
console.log(' params.user.password = ' + userObject.password);
}
);
};
/**
* Get all free users from that are available to receive and use.
* Used for debug purposes.
* @returns Promise -> [userObject] array, special formatted
*/
exports.getUsersList = function () {
var deferred = protractor.promise.defer();
request.get({
url: `${ADDRESS}/list`,
}, (error, response, body) => {
let accounts = JSON.parse(body);
deferred.fulfill(accounts);
});
return deferred.promise;
};
const accountProviderService = require('./accountProviderService.js');
const accounts = [
{ username: 'test', password: '123456' },
{ username: 'test2', password: '123456' },
{ username: 'test3', password: '123456' }
]
exports.config = {
// Just example, this config should be updated with your settings.
beforeLaunch: function () {
accountProviderService.startAccountProviderService(accounts);
},
onPrepare: function () {
accountProviderService.putUserToParams();
},
onComplete: function () {
accountProviderService.returnUser();
}
}
function login(user) {
browser.get('/')
console.log('Using user: ${user} to login`)
$('input.username').sendKeys(user.username)
$('input.password').sendKeys(user.password)
$('button.login').click()
}
describe('Login test example', function () {
login(browser.params.user)
expect(new HomePage().isLoaded()).toBeTruthy('Home page should be loaded after login')
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment