Selenium : Hiding Login Credentials In An Automated Test
With most web automation and testing tasks you are going to want to login to a secure system. You are also going to want to keep your login credentials out of the testing code repository. For my test suite that is being rewritten with Selenium for the MySLP service I am employing a basic JavaScript module methodology along with some git ignore rules to keep my credentials private.
In this example I have also added the ability to switch between production and staging environments and load the proper credentials for each. This can be done by setting an environment variable on my operating system before running the test. In my case I can do this in my phpStorm execution instructions or from the MacOS command line if I choose to run my JavaScript app from there.
The Premise
In my setup I have a config subdirectory which is in the public repository that configures the variables I need that are specific to my environment. This holds things like my URLS to get to the apps , a list of test users, and even the admin login credentials sourced from another place.
The other place for admin credentials is the env subdirectory. The public repo has a *-example.js. The mirror of these are the *-real.js set of files which are kept out of the repo. It is these -real.js files that are read during the program execution.
Any of the devs on the team can copy production-example.js to production-real.js and replace the username and password with their own. They can do the same for staging.
By default the testing is run against staging. The QA team can switch environments to test the production servers by setting the environment variable NODE_ENV before executing the tests. Setting it to production or staging accordingly.
The Code
The test script.
var myslp_config = require( '../config/myslp_config' ); /** * @type {WebDriver} driver */ var driver; /** * MySLP Dashboard Login */ var myslp_dash_login = function() { driver.get( myslp_config.url_for.dashboard ) .then( _ => driver.findElement( { 'id' : 'email' } ).sendKeys( myslp_config.admin.user ) ) .then( _ => driver.findElement( { 'id' : 'login-password' } ).sendKeys( myslp_config.admin.pwd ) ) .then( _ => driver.findElement( { 'css' : '[type=submit]' } ).click() ) ; } /** * Selenium setup. */ var webDriver = require('selenium-webdriver'); var seleniumDrivers = require('selenium-drivers'); /** * Initialize the driver. * This is much like the jQuery document.ready() methodology. */ seleniumDrivers.init({ browserName: 'safari', download: true }).then(function () { driver = new webDriver.Builder() .forBrowser('safari') .build(); myslp_dash_login(); driver.sleep( 10000 ) .then( _ => driver.quit() ); });
The configuration lib.
/** * Set the environment to staging or production. * * The admin property will be set to the values configured in ./env/staging-real.js or ../env/production-real.js * * Default environment is staging. Rather than edit this code you can set the environment variable NODE_ENV: * * $ NODE_ENV=production node login.js * $ NODE_ENV=staging node login.js */ var environment = process.env.NODE_ENV|| 'staging'; // Admin Login - configure in the env/<environment>-real.js file var admin = require( '../env/' + environment + '-real' ); // URLs var url_for = {}; if ( environment == 'production' ) { url_for = { 'my': 'https://my.storelocatorplus.com', 'dashboard': 'https://dashboard.storelocatorplus.com', }; } else { url_for = { 'my': 'https://mybeta.storelocatorplus.com', 'dashboard': 'https://dashbeta.storelocatorplus.com', }; } // test User var test_user = [ { 'email' : 'test1@slp.guru', 'first' : 'TestOne'} ]; // What to export module.exports = { admin: admin, url_for: url_for, test_user: test_user, };
The example environment lib.
var user = 'admin@slp.guru'; var pwd = 'myeasyadminpassword'; module.exports = { user: user, pwd: pwd };
The ignore file
# WebDriver Env /webdriver_tests/env/*-real.js # Selenium Webdriver Listeners /browser_listeners/*river* /browser_listeners/*js*
How It Works
Loading The Environment
Assigning the require of the myslp_config lib to a local myslp_config variable makes it globally accessible within the running test. All of the exported properties from the module become properties of the myslp_config variable so things like myslp_config.url_for points to the URLs in the myslp_config file. We can then reference myslp_config.url_for.dashboard to get to the dashboard interface or myslp_config.url_for.my to get to the main marketing interface (short for the MySLP site or to be more specific the MySLP marketing site).
var myslp_config = require( '../config/myslp_config' );
The myslp_config file itself will look at the NODE_ENV environment variable if set and internally set the environment property to ‘staging’ or ‘production’. The default, if the NODE_ENV variable is not set is ‘staging’. We then use this to further refine our url_for variable to set the proper server paths.
/** * Set the environment to staging or production. * * The admin property will be set to the values configured in ./env/staging-real.js or ../env/production-real.js * * Default environment is staging. Rather than edit this code you can set the environment variable NODE_ENV: * * $ NODE_ENV=production node login.js * $ NODE_ENV=staging node login.js */ var environment = process.env.NODE_ENV|| 'staging';
Define The Test Actions
The myslp_dash_login function runs through the automated web driver, in my case for Safari, and runs the steps to type in the admin username and password and then click submit. Using the string of .then() methods from the Promise JavaScript construct we can ensure the username and password are typed before clicking submit.
/** * MySLP Dashboard Login */ var myslp_dash_login = function() { driver.get( myslp_config.url_for.dashboard ) .then( _ => driver.findElement( { 'id' : 'email' } ).sendKeys( myslp_config.admin.user ) ) .then( _ => driver.findElement( { 'id' : 'login-password' } ).sendKeys( myslp_config.admin.pwd ) ) .then( _ => driver.findElement( { 'css' : '[type=submit]' } ).click() ) ; }
Execute The Test
Using the standard Selenium driver init and webDriver commands we launch the test and when done hold the window open for 10 seconds before closing it.
Details about setting up Selenium with NodeJS and automating Safari are in my other articles.