Selenium / New Relic Synthetics login using Microsoft AD

We needed a synthetics script which can tell us when our site authentication is broken. The following is running in our New Relic monitoring, but can be ran in numerous other monitoring tools

The following can be adapted for anyone’s site, please note that your authentication process may not hit the following Microsoft screen in log step 4 so might need to be changed or removed completely, in my case it selects the ‘Work or school account’ using a xpath method.

** Additional, I swapped to using a test accounts which doesn’t go to the account selector page shown below, this seems to be working much better across all synthetics servers hosted in different countries – I noticed that French & Italian based ones occasionally threw issues. The account selector page only appears if you have two Microsoft accounts which are using the same email address :

If you received the "Which account do you want to use?" message when you sign in, it means you have two accounts with Microsoft that use the same email address
/**
 * Script Name: {Moodle Login}
 * 
 */

/** CONFIGURATIONS **/

// Theshold for duration of entire script - fails test if script lasts longer than X (in ms)
var ScriptTimeout = 180000;
// Script-wide timeout for all wait and waitAndFind functions (in ms)
var DefaultTimeout = 30000;
// Change to any User Agent you want to use.
// Leave as "default" or empty to use the Synthetics default.
var UserAgent = "default";

/** HELPER VARIABLES AND FUNCTIONS **/

const assert = require('assert'),
	By = $driver.By,
	browser = $browser.manage()
/** BEGINNING OF SCRIPT **/

console.log('Starting synthetics script: {Untitled Test Case}');
console.log('Default timeout is set to ' + (DefaultTimeout/1000) + ' seconds');

// Setting User Agent is not then-able, so we do this first (if defined and not default)
if (UserAgent && (0 !== UserAgent.trim().length) && (UserAgent != 'default')) {
  $browser.addHeader('User-Agent', UserAgent);
  console.log('Setting User-Agent to ' + UserAgent);
}

// Get browser capabilities and do nothing with it, so that we start with a then-able command
$browser.getCapabilities().then(function () { })
	.then(() => {
            logger.log(1, "https://your.site.ac.uk");
            return $browser.get("https://your.site/login/index.php"), DefaultTimeout;
        })
	.then(() => {
            logger.log(2, "click Sign in on Moodle page");
            return $browser.waitForAndFindElement(By.linkText("Sign in"), DefaultTimeout)
                .then(function (el) {
                    el.click();
                })
        })
	.then(() => {
            logger.log(3, "Pass Username");
            return $browser.waitForAndFindElement(By.name("loginfmt"), DefaultTimeout)
                .then(function (el) {
                    el.sendKeys($secure.USERNAME);
                })               
        }).then(function(el){
            //Find and click the login button.
            return $browser.waitForAndFindElement(By.xpath("//input[@value='Next']"), DefaultTimeout)
                .then(function (el) {
                    el.click();
                })
        })          
 	.then(() => {
            logger.log(4, "Select xpath Work or school account");
            return $browser.waitForAndFindElement(By.xpath("(.//*[normalize-space(text()) and normalize-space(.)='Work or school account'])[1]/following::small[1]"), DefaultTimeout) 
                .then(function (el) {
                    el.click();
                })
        })   
	.then(() => {
            logger.log(5, "Pass the password securely");
            return $browser.waitForAndFindElement(By.name("passwd"), DefaultTimeout)
                .then(function (el) {
                    el.sendKeys($secure.PASSWORD);
                })               
        }).then(function(el){
            //Find and click the login button.
            return $browser.waitForAndFindElement(By.xpath("//input[@value='Sign in']"), DefaultTimeout)
                .then(function (el) {
                    el.click();
                })
        })               
	.then(function() {
		logger.end();
		console.log('Browser script execution SUCCEEDED.');
	}, function(err) {
		logger.end();
		console.log ('Browser script execution FAILED.');
		throw(err);
	});


//** Export Functions
const logger=(function (timeout=3000, mode='production') {

    var startTime = Date.now(),
        stepStartTime = Date.now(),
        prevMsg = '',
        prevStep = 0;


    if (typeof $util == 'undefined'  ){
        $util = {
            insights: {
                set: (msg) => {
                    console.log(`dryRun: sending to Insights using ${msg}`)
                }
            }
        }

    }

    function log(thisStep, thisMsg) {

        if (thisStep > prevStep && prevStep != 0) {
            end()
        }

        stepStartTime = Date.now() - startTime;

        if (mode != "production") {
            stepStartTime = 0

        }

        console.log(`Step ${thisStep}: ${thisMsg} STARTED at ${stepStartTime}ms.`);

        prevMsg = thisMsg;
        prevStep = thisStep;

    }

    function end() {
        var totalTimeElapsed = Date.now() - startTime;
        var prevStepTimeElapsed = totalTimeElapsed - stepStartTime;

        if (mode != 'production') {
            prevStepTimeElapsed = 0
            totalTimeElapsed = 0
        }

        console.log(`Step ${prevStep}: ${prevMsg} FINISHED. It took ${prevStepTimeElapsed}ms to complete.`);

        $util.insights.set(`Step ${prevStep}: ${prevMsg}`, prevStepTimeElapsed);
        if (timeout > 0 && totalTimeElapsed > timeout) {
            throw new Error('Script timed out. ' + totalTimeElapsed + 'ms is longer than script timeout threshold of ' + timeout + 'ms.');
        }
    }

    return {
        log,
        end
    }
})(ScriptTimeout)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s