A personal repository of random information in compensation for a fatigued biological computer
20131120 Lets capture these now
First is utilities and second is locators & UIMaps
diaExtensions.js
/*************************************************************************************/
/*************************************************************************************/
// Selenium extensions for GDAP project
// Version: 20121217-19:00
/*************************************************************************************/
// xPathCount functions don't work with UI-Elements so we will make our own here..
// Selenium.prototype.getCountNodes = function(locator, target) {
// var container = this.page().findElement(locator);
// /*
// var count = 0;
// for(var prop in element) {
// alert(element.prop);
// if(element.hasOwnProperty(prop))
// ++count;
// }
// storedVars[target] = count;
// */
// // from http://help.dottoro.com/ljsfamht.php per childElementCount
// // and http://blog.tegneblokken.net/2009/08/counting-childnodes-with-javascript-the-whitespace-incident/
// //var container = document.getElementById ("container");
// var childCount = 0;
// /*
// if ('childElementCount' in container) {
// alert("1");
// childCount = container.childElementCount;
// }
// else {
// if (container.children) {
// alert("2");
// childCount = container.children.length;
// }
// else
// { // Firefox before version 3.5
// alert("3");
// */
// var childNodes = container.childNodes
// for(var i=0; i<childNodes.length; i++) {
// alert(childNodes[i])
// }
// alert("Part1 done");
// var p2count = 0;
// var childNodes = container.childNodes
// for(var i=0; i<childNodes.length; i++) {
// if (childNodes[i].nodeType == 1) {
// alert(childNodes[i])
// p2count++;
// }
// }
// alert("Part2 count" + p2count);
// var p3count = 0;
// for(var i=0; i<container.length; i++) {
// //if (container[i].nodeType == 1) {
// alert(container[i])
// p3count++;
// // }
// }
// alert("Part3 count" + p3count);
// var child = container.firstChild;
// while (child) {
// if (child.nodeType == 1) {
// alert (child.nodeName + ", " + child.innerHTML + ", " + child.nodeType);
// childCount++;
// }
// child = child.nextSibling;
// }
// /*
// }
// }
// */
// alert ("The number of child elements is " + childCount);
// return childCount;
// }
// Selenium.prototype.getCountObjects = function(locator) {
// var container = this.page().findElement(locator);
// var childCount = 0;
// var log = 0;
// for (var i in container) {
// var obj = container[i];
// log += "here it is: " + obj.nodeType + ", " + i + "\r\n";
// childCount++;
// }
// alert (log);
// return childCount;
// }
// Selenium.prototype.getCountObjects = function(locator) {
// var container = this.page().findElement(locator);
// var childCount = 0;
// var log = 0;
// for (var i in container) {
// var obj = container[i];
// log += "here it is: " + obj.nodeType + ", " + i + "\r\n";
// childCount++;
// }
// alert (log);
// return childCount;
// }
// Selenium.prototype.getLocator = function(locator, target) {
// storedVars[target] = map.getLocator(locator);
// }
/*************************************************************************************/
/* Random values generator */
/*************************************************************************************/
Selenium.prototype.doStoreRandomValue = function(options, varName ) {
/* Options: type-length */
var length = 8;
var type = 'alphanumeric';
var o = options.split( '|' );
for ( var i = 0 ; i < 2 ; i ++ ) {
if ( o[i] && o[i].match( /^\d+$/ ) )
length = o[i];
if ( o[i] && o[i].match( /^(?:alpha)?(?:numeric)?$/ ) )
type = o[i];
}
switch( type ) {
case 'alpha' : storedVars[ varName ] = randomAlpha( length ); break;
case 'numeric' : storedVars[ varName ] = randomNumeric( length ); break;
case 'alphanumeric' : storedVars[ varName ] = randomAlphaNumeric( length ); break;
default : storedVars[ varName ] = randomAlphaNumeric( length );
};
};
function randomNumeric (length) {
return generateRandomString( length, '0123456789'.split( '' ) );
}
function randomAlpha (length) {
var alpha = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split( '' );
return generateRandomString( length, alpha );
}
function randomAlphaNumeric (length) {
var alphanumeric = '01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split( '' );
return generateRandomString( length, alphanumeric );
}
function generateRandomString(length, chars) {
var string = '';
for ( var i = 0 ; i < length ; i++ )
string += chars[ Math.floor( Math.random() * chars.length ) ];
return string;
}
/*************************************************************************************/
/* Date functions */
/*************************************************************************************/
// Date helpers (could be merged but no time..)
diaGetCurrentTimeHHcolonMMcolonSS = function(seconds) {
// param: seconds = if true output seconds
var d = new Date();
var curr_hour = d.getHours();
var curr_min = d.getMinutes();
var curr_sec = d.getSeconds();
var result = String("0" + curr_hour).slice(-2)+':' + String("0" + curr_min).slice(-2);
if (seconds) result += ':'+ String("0" + curr_sec).slice(-2);
return result
};
diaGetCurrentDateDDslashMMslashYY = function(date) {
//var date=new Date();
var year=date.getFullYear();
var day=date.getDay();
var month=date.getMonth()+1;
if (month<10)
month='0'+month;
var monthDate=date.getDate();
if (monthDate<10)
monthDate='0'+monthDate;
//this will contain the final date
return monthDate+'/'+month+'/'+String(year).slice(-2);
}
diaGetCurrentDateDDslashMMslashYYYY = function(date) {
//var date=new Date();
var year=date.getFullYear();
var day=date.getDay();
var month=date.getMonth()+1;
if (month<10)
month='0'+month;
var monthDate=date.getDate();
if (monthDate<10)
monthDate='0'+monthDate;
//this will contain the final date
return monthDate+'/'+month+'/'+year.slice;
}
diaGetCurrentDateDDslashMMslashYYYY = function(date) {
//var date=new Date();
var year=date.getFullYear();
var day=date.getDay();
var month=date.getMonth()+1;
if (month<10)
month='0'+month;
var monthDate=date.getDate();
if (monthDate<10)
monthDate='0'+monthDate;
//this will contain the final date
return monthDate+'/'+month+'/'+year;
}
diaGetCurrentDateDD_MMM_YYYY = function(date) {
var fullYear=date.getFullYear();
var month=date.getMonth();
var monthDate=date.getDate();
if (monthDate<10)
monthDate='0'+monthDate;
var monthArr=new Array('Jan','Feb','Mar','April','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
return monthDate+' '+monthArr[month]+' '+fullYear;
};
diaGetCurrentDateFull = function(date) {
/**
* This function return system full date like "Saturday, September 12, 2009" format
**/
// var fifteenth=new Date();
var fifteenth=date;
var fullYear=fifteenth.getFullYear();
var seventeenth=fifteenth.getDay();
var month=fifteenth.getMonth();
var monthDate=fifteenth.getDate();
if (monthDate<10)
monthDate='0'+monthDate;
var dayArr=new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
var monthArr=new Array('January','February','March','April','May','June','July','August','September','October','November','December');
return dayArr[seventeenth]+', '+monthArr[month]+' '+monthDate+', '+fullYear;
};
// date/time assemblers
diaGetDateFormatted = function(options) {
// Options: format|dayDifference = days to add/subtract from today
var dayDifference = 0;
var type = "";
var o = options.toUpperCase().split( '|' );
// Lindsay: this probably isn't necessary but it does allow optional params options
// in either order so is an interesting example of param parsing
for ( var i = 0 ; i < 2 ; i ++ ) {
// if ( o[i] && o[i].match( /^\d+$/ ) )
if ( o[i] && o[i].match( /^[-+]?[0-9]*\.?[0-9]+$/ ) ) // positive & negative
dayDifference = o[i];
if ( o[i] && o[i].match( /\b(DDMMYY|DDMMYYYY|DDMMMYYYY|FULL)\b/ ) )
type = o[i];
}
var today = new Date();
var requiredDate = new Date();
requiredDate.setDate(today.getDate()+ parseInt(dayDifference));
switch( type) {
case 'DDMMYY' : return diaGetCurrentDateDDslashMMslashYY(requiredDate); break;
case 'DDMMYYYY' : return diaGetCurrentDateDDslashMMslashYYYY(requiredDate); break;
case 'DDMMMYYYY' : return diaGetCurrentDateDD_MMM_YYYY(requiredDate); break
case 'FULL' : return diaGetCurrentDateFull(requiredDate); break
default : return "Invalid date format: " + options;
};
}
diaGetTimeCurrentFormatted = function(options){
// Options: format
var type = "";
var o = options.toUpperCase().split( '|' );
// Lindsay: this probably isn't necessary but it does allow optional params options
// in either order so is an interesting example of param parsing
for ( var i = 0 ; i < 2 ; i ++ ) {
if ( o[i] && o[i].match( /\b(HHMM|HHMMSS)\b/ ) )
type = o[i];
}
switch( type) {
case 'HHMM' : return diaGetCurrentTimeHHcolonMMcolonSS(false); break;
case 'HHMMSS' : return diaGetCurrentTimeHHcolonMMcolonSS(true); break;
default : return "Invalid time format: " + options;
};
};
// date/time extensions
// Use match function for directly comparing against locators..
// i.e. don't use
Selenium.prototype.doStoreTime = function(options, varName){
// Options: format
storedVars[ varName ] = diaGetTimeCurrentFormatted(options);
};
Selenium.prototype.isTimeMatch = function(locator, options) {
var element = this.browserbot.findElement(locator);
return element.innerHTML == diaGetTimeCurrentFormatted(options);
};
Selenium.prototype.doStoreDate = function(options, varName){
// Options: format|dayDifference
storedVars[ varName ] = diaGetDateFormatted(options);
};
Selenium.prototype.isDateMatch = function(locator, options){
var element = this.browserbot.findElement(locator);
return element.innerHTML == diaGetDateFormatted(options);
};
Selenium.prototype.doAppendDateTime = function(strval, varName ) {
// Options: strval = prefix for appending date time to
storedVars[varName] = strval + ' ' + diaGetDateFormatted('ddmmyyyy|0') + '-' + diaGetTimeCurrentFormatted('hhmmss');
}
user-extensions.js
/*************************************************************************************/
// GDAP Selenium testing user extensions
/*************************************************************************************/
// XPath mapping
// Note that grid item columns are assumed to be in fixed columns at this time, however Matt/Andrew
// have agreed in principle to add identifiers to each cell most likely as classes
var testData = {
"url":"http://test.xxxxxxx",
"users":{
"editor1": {
"username":"Tester1 - xxxx",
"password":"xxxx",
"logoutExisting":true,
"office":"xxxxxxxxx",
"failIfLoginInUse": false
}
}
};
var testSharedOptions = {
"jobStates":"['In Draft', 'For Review', 'Reviewed' , 'To Finish']",
"jobListJobElements":"['row', 'title', 'created', 'arrived', 'entitycount', 'itemcount', 'flag', 'flagonlyifset']",
"jobListDetailDisplayFields":"['Number', 'Owner', 'Office', 'State', 'Arrived', 'Created']",
"jobListDetailCreateEntityOptions":"[\
'Access Authority'\
,'Accession'\
,'Agency'\
,'Disposal Authority'\
,'Function'\
,'Item group'\
,'Jurisdiction'\
,'Organisation'\
,'Series']"
};
var testGDAPLocators = {
"login": {
"username":"//input[@id='username']",
"password":"//input[@id='password']",
"logoutExisting":"//input[@id='exceptionIfMaximumSessionsExceeded']",
"btnLogin":"//button[@id='login']"
},
"common": {
"headerLinks": {
"root": "//div[@id='primary-links']",
"selected": function(){return this.root + "//li[contains(@class,'selected')]/child::";},
"lJobs": function(){return this.root + "//a[span[.='Jobs']]";},
"lSearch": function(){return this.root + "//a[contains(.,'Search')]";},
"lThesaurus": function(){return this.root + "//a[span[.='Thesaurus']]";},
"lLegislation": function(){return this.root + "//a[span[.='Legislation']]";},
"lJobsSelected": function(){return this.selected() + "a[span[.='Jobs']]";},
"lSearchSelected": function(){return this.selected() + "a[contains(.,'Search')]";},
"lThesaurusSelected": function(){return this.selected() + "a[span[.='Thesaurus']]";},
"lLegislationSelected": function(){return this.selected() + "a[span[.='Legislation']]";},
"lLogout": function(){return "//a[.='Logout']";}
}
},
"jobs": {
"root": "//div[@class='jobs']",
"headerLinks": {
"root": "//div[@class='jobs']//div[@class='subnav']",
"selected": function(){return this.root + "//li[contains(@class,'selected')]/child::";},
"lMyJobs": function(){return this.root + "//a[span[.='My jobs']]";},
"lForReview": function(){return this.root + "//a[span[.='For review']]";},
"lJobSearch": function(){return this.root + "//a[span[.='Job search']]";},
"lMyJobsSelected": function(){return this.selected() + "a[span[.='My jobs']]";},
"lForReviewSelected": function(){return this.selected() + "a[span[.='For review']]";},
"lJobSearchSelected": function(){return this.selected() + "a[span[.='Job search']]";}
},
"actions": {
"root": "//div[@class='jobs']//div[@class='actions']",
"btnCreateJob": function(){return this.root + "//a[span[.=' Create job']";}
},
"jobList": {
"root": "//div[contains(@class,'jobListHead')]",
"headerByState": function(){return "//div[contains(@class,'jobListHead') and descendant::span[.='STATE']]/h4";},
"jobListByState": function(){return "//div[contains(@class,'jobListHead') and descendant::span[.='STATE']]/following-sibling::*";},
"jobListJobRows": function(){return this.jobListByState() + "//tbody/tr";},
"jobSelected": function(){return "contains(@class,'selected') and ";},
"jobByTitle": function(){return this.jobListJobRows() + "[SELECTED td[@class='title' and descendant::span[text()='TITLE']]]";},
"jobByRow": function(){return this.jobListJobRows() + "[ROW]";},
"jobAttribute":{
"title": "//td[@class='title']/span",
"created": "//td[@class='created']/span",
"arrived": "//td[@class='arrived']/span",
"entitycount": "//td[@class='entities']/span/span[1]",
"itemcount": "//td[@class='entities']/span/span[2]",
"flag": "//td[@class='flag']/a",
"flagonlyifset": "//td[@class='flag']/a/img[not(contains(@src,'unset'))]",
"suffix": function(column) {
switch (column.toUpperCase())
{
case "ROW":
return "";
break;
case 'TITLE':
return this.title;
break;
case 'CREATED':
return this.created;
break;
case 'ARRIVED':
return this.arrived;
break;
case 'ENTITYCOUNT':
return this.entitycount;
break;
case 'ITEMCOUNT':
return this.itemcount;
break;
case 'FLAG':
return this.flag;
break;
case 'FLAGONLYIFSET':
return this.flagonlyifset;
break;
}
}
},
},
"jobDetail": {
"root": "//div[contains(@class,'selectedJob')]",
"titleRead": function(){return this.root + "//div[@class='job-title']//span";},
"titleEdit": function(){return this.root + "//div[@class='job-title']//input";},
"titleEditIcon": function(){return this.root + "//div[@class='job-title']/descendant::a";},
"toolbar": {
"root": "//div[contains(@class,'selectedJob')]//div[contains(@class,'btn-toolbar')]",
"btnCreateEntityPartText": function(){return this.root + "//*[@id='create-entity']";},
"btnCreateEntityPartDownArrow": function(){return this.btnCreateEntityPartText() + "/following-sibling::*";},
"btnCreateEntityOptionByLabel": function(){return this.root + "//ul[preceding-sibling::a[@id='create-entity']]//a[span[text()='ENTITY']]";},
"btnSendForReview": function(){return this.root + "//*[contains(text(),'Send for review')]";},
"btnDelete": function(){return this.root + "//*[contains(text(),'Delete')]";},
"btnUnassign": function(){return this.root + "//*[contains(text(),'Unassign')]";},
},
"displayField": function(){return this.root + "//dd[preceding-sibling::dt[text()='FIELD']][1]/span";},
"chkPriority": function(){return this.root + "//dt/input[@id='priority']";},
"selJobType": function(){return this.root + "//dd[preceding-sibling::dt[text()='Type']][1]/select";},
"txtNote": function() { return this.root + "//dd[preceding-sibling::dt[text()='Notes']][1]//div";},
"entities": {
},
"itemgroup": {
"root" : "//*[@class='sectionHead' and text()='Item Groups']",
"list" : function() {return this.root + "/following::*[1][contains(@class,'entities')]";},
"byTitle": function(){return this.list + "//tbody/tr[td[@class='title' and descendant::span[text()='TITLE']]]";},
"byRow": function(){return this.root + "//tbody//tr[ROW]";},
}
}
},
"itemGroup": {
"titleRead": "//div[contains(@class,'item-group-title')]/descendant::span",
"titleEdit": "//div[contains(@class,'item-group-title')]/descendant::input",
"titleEditIcon": "//div[contains(@class,'item-group-title')]/descendant::a",
"toolbar": {
"root": "//div[contains(@class,'toolbar-buttons')]",
"btnInfo": function(){return this.root + "//a[.=' Info']";},
"btnColumns": function(){return this.root + "//a[.=' Columns']";},
"btnSort": function(){return this.root + "//a[.=' Sort']";},
"btnCreate": function(){return this.root + "//a[.=' Create']";},
"btnImport": function(){return this.root + "//a[.=' Import']";},
"btnExport": function(){return this.root + "//a[.=' Export']";},
"btnFill": function(){return this.root + "//a[.=' Fill']";},
"btnMove": function(){return this.root + "//a[.=' Move']";},
"btnReady": function(){return this.root + "//a[.=' Ready']";},
"btnSelectAll": function(){return this.root + "//a[.=' Select all']";},
"btnSelectBy": function(){return this.root + "//a[.=' Select by...']";},
"btnClearSelection": function(){return this.root + "//a[.=' Clear selection']";},
"btnFilter": function(){return this.root + "//a[.=' Filter']";},
"btnFilterBy": function(){return this.root + "//a[.=' Filter by...']";},
"btnClearFilter": function(){return this.root + "//a[.=' Clear filter']";},
"btnComments": function(){return this.root + "//a[.=' Comments']";}
},
"count": {
"root": "//div[@class='item-summary-info']",
"total": function(){return this.root + "//span[1]";},
"filtered": function(){return this.root + "//span[2]";},
"selected": function(){return this.root + "//span[3]";}
},
"pagination": {
"root": "//div[@class='navigator']",
"lFirst": function(){return this.root + "//a[@class='first']";},
"lPrev": function(){return this.root + "//a[@class='prev']";},
"lNext": function(){return this.root + "//a[@class='next']";},
"lLast": function(){return this.root + "//a[@class='last']";},
"lPage": function(){return this.root + "//a[contains(@href,'navigator-PAGE']";}
},
"grid": {
"root": "//div[@class='results']",
"header": function(){return this.root + "//tr[contains(@class,'headers')]";},
"item": {
"summary": {
"root": "//div[@class='results']//tr[contains(@class,'summary')][INDEX]",
"lChevron": function(){return this.root + "//span[contains(@class,'chevron')]";},
"lChevronUp": function(){return this.root + "//span[contains(@class,'chevron-right')]";},
"lChevronDown": function(){return this.root + "//span[contains(@class,'chevron-down')]";},
"chkSelect": function(){return this.root + "//input[@class='selectionCheckBox')]";},
"agencyRecID": function(){return this.root + "/td[3]";},
"code": function(){return this.root + "/td[4]";},
"type": function(){return this.root + "/td[5]/span";},
"title": function(){return this.root + "/td[6]";},
"years": function(){return this.root + "/td[7]";},
"series": function(){return this.root + "/td[8]";},
"restriction": function(){return this.root + "/td[9]";},
"description": function(){return this.root + "/td[10]";},
"accession": function(){return this.root + "/td[11]";},
"state": function(){return this.root + "/td[12]";}
},
"detail": {
"root": "//tr[contains(@class,'detail')][INDEX]",
"tab": {
"root": "//tr[contains(@class,'detail')][INDEX]",
"General": function(){return this.root + "//span[.='General']";},
"Relationships": function(){return this.root + "//span[.='Relationships']";},
"Repository": function(){return this.root + "//span[.='Repository']";},
"restrictions": function(){return this.root + "//span[.='Restrictions']";},
"documentation": function(){return this.root + "//span[.='Documentation']";}
},
"content": {
"root": "//tr[contains(@class,'detail')][INDEX]//div[contains(@class,'tab-content')",
"code": function(){return this.root + "//li[label[.='Code']]/span";},
"type": function(){return this.root + "//li[label[.='Type']]/span";},
"years": function(){return this.root + "//li[label[.='Years']]/span";}
}
}
}
}
}
};
/*************************************************************************************/
/*************************************************************************************/
// UI-Elements Maps
/*************************************************************************************/
// Q. Why use UI-elements and not just a JS object?
// A. Because maps integrate into the IDE and can also be used in Web driver..
var map = new UIMap();
map.addPageset({name: 'login_page', description: 'login page elements', pathRegexp: '.*' });
map.addPageset({name: 'common_page', description: 'common page elements', pathRegexp: '.*' });
map.addPageset({name: 'jobs_page', description: 'jobs page elements', pathRegexp: '.*'});
map.addPageset({name: 'itemGroup_page', description: 'itemGroup', pathRegexp: '.*'});
/***************************************************/
// Login page
map.addElement('login_page', {name: 'username', description: 'userid input', locator: testGDAPLocators.login.username});
map.addElement('login_page', {name: 'password', description: 'password input', locator: testGDAPLocators.login.password});
map.addElement('login_page', {name: 'logoutExisting', description: 'Logout existing sessions', locator: testGDAPLocators.login.logoutExisting});
map.addElement('login_page', {name: 'btnLogin', description: 'Login button', locator: testGDAPLocators.login.btnLogin});
/***************************************************/
// Common to every page except login
// This one just to give something harmless to click off edits where there is no 'done' type button, ie job title..
map.addElement('common_page', {name: 'banner', description: 'common bannr for harmless click to finish edits', locator: testGDAPLocators.common.headerLinks.root});
map.addElement('common_page', {name: 'lJobs', description: 'jobs link', locator: testGDAPLocators.common.headerLinks.lJobs()});
map.addElement('common_page', {name: 'lSearch', description: 'seach link', locator: testGDAPLocators.common.headerLinks.lSearch()});
map.addElement('common_page', {name: 'lThesaurus', description: 'thesaurus link', locator: testGDAPLocators.common.headerLinks.lThesaurus()});
map.addElement('common_page', {name: 'lLegisation', description: 'legisation link', locator: testGDAPLocators.common.headerLinks.lLegislation()});
map.addElement('common_page', {name: 'lJobsSelected', description: 'jobs link', locator: testGDAPLocators.common.headerLinks.lJobsSelected()});
map.addElement('common_page', {name: 'lSearchSelected', description: 'seach link', locator: testGDAPLocators.common.headerLinks.lSearchSelected()});
map.addElement('common_page', {name: 'lThesaurusSelected', description: 'thesaurus link', locator: testGDAPLocators.common.headerLinks.lThesaurusSelected()});
map.addElement('common_page', {name: 'lLegisationSelected', description: 'legisation link', locator: testGDAPLocators.common.headerLinks.lLegislationSelected()});
map.addElement('common_page', {name: 'lLogout', description: 'legisation link', locator: testGDAPLocators.common.headerLinks.lLogout()});
/***************************************************/
// Jobs page
// Header toolbar
map.addElement('jobs_page', {name: 'lMyJobs', description: 'My Jobs link', locator: testGDAPLocators.jobs.headerLinks.lMyJobs()});
map.addElement('jobs_page', {name: 'lMyJobsSelected', description: 'My Jobs link selected', locator: testGDAPLocators.jobs.headerLinks.lMyJobsSelected()});
map.addElement('jobs_page', {name: 'lForReview', description: 'For review link', locator: testGDAPLocators.jobs.headerLinks.lForReview()});
map.addElement('jobs_page', {name: 'lForReviewSelected', description: 'For review link selected', locator: testGDAPLocators.jobs.headerLinks.lForReviewSelected()});
map.addElement('jobs_page', {name: 'lJobSearch', description: 'Job search link', locator: testGDAPLocators.jobs.headerLinks.lJobSearch()});
map.addElement('jobs_page', {name: 'lJobSearchSelected', description: 'Job search link selected', locator: testGDAPLocators.jobs.headerLinks.lJobSearchSelected()});
// Job list by state
map.addElement('jobs_page', {name: 'btnCreateJob', description: 'Create job button', locator: testGDAPLocators.jobs.actions.btnCreateJob()});
map.addElement('jobs_page', {
name: 'jobListHeaderByState'
, description: 'Job list header by state'
, args: [
{
name: 'state',
description: 'Target job states',
defaultValues: eval(testSharedOptions.jobStates)
}
]
, getLocator: function(args) {
return testGDAPLocators.jobs.jobList.headerByState().replace(/STATE/g, args.state);
}
});
map.addElement('jobs_page', {
name: 'jobListByState'
, description: 'Job list by state'
, args: [
{
name: 'state',
description: 'Target job states',
defaultValues: eval(testSharedOptions.jobStates)
}
]
, getLocator: function(args) {
return testGDAPLocators.jobs.jobList.jobListByState().replace(/STATE/g, args.state);
}
});
map.addElement('jobs_page', {
name: 'jobListJobRows'
, description: 'Job list rows, use with Selenese storeXpathCount statement'
, args: [
{
name: 'state',
description: 'Target job states',
defaultValues: eval(testSharedOptions.jobStates)
}
]
, getLocator: function(args) {
return testGDAPLocators.jobs.jobList.jobListJobRows().replace(/STATE/g, args.state);
}
});
map.addElement('jobs_page', {name: 'test', description: 'TEST FOR HARDCODED JOB ROWS', locator: "//div[contains(@class,'jobListHead') and descendant::span[.='In Draft']]/following-sibling::*//tbody/tr"});
map.addElement('jobs_page', {
name: 'jobListJobByTitle'
, description: 'Job in job list by state/title'
, args: [
{
name: 'state',
description: 'Target job state',
defaultValues: eval(testSharedOptions.jobStates)
},
{
name: 'title',
description: 'Target job title',
defaultValues: []
/*
getDefaultValues: function(inDocument) {
var defaultValues = [];
var elements = this.browserbot.findElement(testGDAPLocators.jobs.jobList.jobListJobRows.jobAttribute.title);
for (var i = 0; i < titles.length; i++)
{
var element = elements[i];
defaultvalues.push(element.innerHTML);
}
return defaultValues;
}
*/
},
{
name: 'selected',
description: 'true if job must be currently selected, defaults to false',
defaultValues: [true, false]
},
{
name: 'column',
description: 'Target job list column, defaults to entire (clickable) row',
defaultValues: eval(testSharedOptions.jobListJobElements)
}
]
, getLocator: function(args) {
if (!args.column) args.column = 'row';
if (!args.selected) args.selected = 'false';
var locator = testGDAPLocators.jobs.jobList.jobByTitle().replace(/STATE/g, args.state).replace(/TITLE/g, args.title);
locator = locator.replace(/SELECTED/g, (args.selected.toUpperCase()=='TRUE') ? testGDAPLocators.jobs.jobList.jobSelected(): '');
return locator += testGDAPLocators.jobs.jobList.jobAttribute.suffix(args.column);
}
});
map.addElement('jobs_page', {
name: 'jobListJobByRow'
, description: 'Job row in job list vertically (starting at 1)'
, args: [ {
name: 'state',
description: 'Target job state',
defaultValues: eval(testSharedOptions.jobStates)
},
{
name: 'row',
description: 'Target job row no',
defaultValues: range(1, 100)
},
{
name: 'selected',
description: 'true if job must be currently selected, defaults to false',
defaultValues: [true, false]
},
{
name: 'column',
description: 'Target job list column, defaults to entire (clickable) row',
defaultValues: eval(testSharedOptions.jobListJobElements)
}
]
, getLocator: function(args) {
if (!args.column) args.column = 'row';
if (!args.selected) args.selected = 'false';
var locator = testGDAPLocators.jobs.jobList.jobByRow().replace(/STATE/g, args.state).replace(/ROW/g, args.row);
locator = locator.replace(/SELECTED/g, (args.selected.toUpperCase()=='TRUE') ? testGDAPLocators.jobs.jobList.jobSelected(): '');
return locator += testGDAPLocators.jobs.jobList.jobAttribute.suffix(args.column);
}
});
// Job detail title
map.addElement('jobs_page', {name: 'jobTitleDisplay', description: 'Job title not editable', locator: testGDAPLocators.jobs.jobDetail.titleRead()});
map.addElement('jobs_page', {name: 'jobTitleEdit', description: 'Job title editable', locator: testGDAPLocators.jobs.jobDetail.titleEdit()});
map.addElement('jobs_page', {name: 'jobTitleEditIcon', description: 'Job title edit icon', locator: testGDAPLocators.jobs.jobDetail.titleEditIcon()});
// Job detail toolbar
map.addElement('jobs_page', {name: 'btnCreateEntityPartText', description: 'Create entity button text part', locator: testGDAPLocators.jobs.jobDetail.toolbar.btnCreateEntityPartText()});
map.addElement('jobs_page', {name: 'btnCreateEntityPartDownArrow', description: 'Create entity button down arrow part', locator: testGDAPLocators.jobs.jobDetail.toolbar.btnCreateEntityPartDownArrow()});
map.addElement('jobs_page', {name: 'btnCreateEntityOptionByLabel'
, description: 'Create entity selection'
, args: [
{
name: 'label',
description: 'target entity label (case sensitive as it appears on the page)',
defaultValues: eval(testSharedOptions.jobListDetailCreateEntityOptions)
}
]
, getLocator: function(args) {
return testGDAPLocators.jobs.jobDetail.toolbar.btnCreateEntityOptionByLabel().replace(/ENTITY/g, args.label);
}
});
map.addElement('jobs_page', {name: 'btnSendForReview', description: 'Send for review button', locator: testGDAPLocators.jobs.jobDetail.toolbar.btnSendForReview()});
map.addElement('jobs_page', {name: 'btnDelete', description: 'Send for review button', locator: testGDAPLocators.jobs.jobDetail.toolbar.btnDelete()});
map.addElement('jobs_page', {name: 'btnUnassign', description: 'Send for review button', locator: testGDAPLocators.jobs.jobDetail.toolbar.btnUnassign()});
// Job detail fields
map.addElement('jobs_page', {name: 'detailFieldBylabel'
, description: 'Job detail, fields by label'
, args: [
{
name: 'label',
description: 'target field label (case sensitive as it appears on the page)',
defaultValues: eval(testSharedOptions.jobListDetailDisplayFields)
}
]
, getLocator: function(args) {
return testGDAPLocators.jobs.jobDetail.displayField().replace(/FIELD/g, args.label);
}
});
map.addElement('jobs_page', {name: 'detailChkPriority', description: 'Job detail, priority checkbox', locator: testGDAPLocators.jobs.jobDetail.chkPriority()});
map.addElement('jobs_page', {name: 'detailJobTypeSelector', description: 'Job detail, job type selector', locator: testGDAPLocators.jobs.jobDetail.selJobType()});
map.addElement('jobs_page', {name: 'detailNoteClickable', description: 'Job detail, note', locator: testGDAPLocators.jobs.jobDetail.txtNote()});
// Job detail item group list
map.addElement('jobs_page', {
name: 'jobItemGroupByTitle'
, description: 'Item group in job by item group title'
, args: [
{
name: 'title',
description: 'Target item group title',
defaultValues: ['']
},
{
name: 'column',
description: 'Target job list column (use row for clickable element)',
defaultValues: eval(testSharedOptions.jobListJobElements)
}
]
, getLocator: function(args) {
var locator = testGDAPLocators.jobs.jobList.jobByTitle().replace(/STATE/g, args.state).replace(/TITLE/g, args.title);
return locator += testGDAPLocators.jobs.jobList.jobAttribute.suffix(args.column);
}
});
/***************************************************/
// Item group page
// Item title
map.addElement('itemGroup_page', {name: 'titleDisplay', description: 'Item group title', locator: testGDAPLocators.itemGroup.titleRead});
map.addElement('itemGroup_page', {name: 'titleEdit', description: 'Item group title', locator: testGDAPLocators.itemGroup.titleEdit});
map.addElement('itemGroup_page', {name: 'titleEditIcon', description: 'Item group title edit link', locator: testGDAPLocators.itemGroup.titleEditIcon});
// Tool bar
map.addElement('itemGroup_page', {name: 'btnInfo', description: 'Item group info button', locator: testGDAPLocators.itemGroup.toolbar.btnInfo()});
map.addElement('itemGroup_page', {name: 'btnColumns', description: 'Item group Columns button', locator: testGDAPLocators.itemGroup.toolbar.btnColumns()});
map.addElement('itemGroup_page', {name: 'btnSort', description: 'Item group Sort button', locator: testGDAPLocators.itemGroup.toolbar.btnSort()});
map.addElement('itemGroup_page', {name: 'btnCreate', description: 'Item group Create button', locator: testGDAPLocators.itemGroup.toolbar.btnCreate()});
map.addElement('itemGroup_page', {name: 'btnImport', description: 'Item group Import button', locator: testGDAPLocators.itemGroup.toolbar.btnImport()});
map.addElement('itemGroup_page', {name: 'btnExport', description: 'Item group Export button', locator: testGDAPLocators.itemGroup.toolbar.btnExport()});
map.addElement('itemGroup_page', {name: 'btnFill', description: 'Item group Fill button', locator: testGDAPLocators.itemGroup.toolbar.btnFill()});
map.addElement('itemGroup_page', {name: 'btnMove', description: 'Item group Move button', locator: testGDAPLocators.itemGroup.toolbar.btnMove()});
map.addElement('itemGroup_page', {name: 'btnReady', description: 'Item group Ready button', locator: testGDAPLocators.itemGroup.toolbar.btnReady()});
map.addElement('itemGroup_page', {name: 'btnSelectAll', description: 'Item group Select all button', locator: testGDAPLocators.itemGroup.toolbar.btnSelectAll()});
map.addElement('itemGroup_page', {name: 'btnSelectBy', description: 'Item group Select by button', locator: testGDAPLocators.itemGroup.toolbar.btnSelectBy()});
map.addElement('itemGroup_page', {name: 'btnClearSelection', description: 'Item group Clear selection button', locator: testGDAPLocators.itemGroup.toolbar.btnClearSelection()});
map.addElement('itemGroup_page', {name: 'btnFilter', description: 'Item group Filter button', locator: testGDAPLocators.itemGroup.toolbar.btnFilter()});
map.addElement('itemGroup_page', {name: 'btnFilterBy', description: 'Item group Filter by button', locator: testGDAPLocators.itemGroup.toolbar.btnFilterBy()});
map.addElement('itemGroup_page', {name: 'btnClearFilter', description: 'Item group Clear filter button', locator: testGDAPLocators.itemGroup.toolbar.btnClearFilter()});
map.addElement('itemGroup_page', {name: 'btnComments', description: 'Item group Comments button', locator: testGDAPLocators.itemGroup.toolbar.btnComments()});
// Item counters (at least 1 item in itemGroup)
map.addElement('itemGroup_page', {name: 'count', description: 'items count', locator: testGDAPLocators.itemGroup.count.total()});
map.addElement('itemGroup_page', {name: 'itemsFiltered', description: 'items filter count', locator: testGDAPLocators.itemGroup.count.filtered()});
map.addElement('itemGroup_page', {name: 'itemsSelected', description: 'items selected count', locator: testGDAPLocators.itemGroup.count.selected()});
// Pagination controls (> 50 items in itemGroup)
map.addElement('itemGroup_page', {name: 'pagination', description: 'container for item pagination', locator: testGDAPLocators.itemGroup.pagination.root});
map.addElement('itemGroup_page', {name: 'lFirst', description: 'First page navigator', locator: testGDAPLocators.itemGroup.pagination.lFirst});
map.addElement('itemGroup_page', {name: 'lPrev', description: 'Prev page navigator', locator: testGDAPLocators.itemGroup.pagination.lPrev});
map.addElement('itemGroup_page', {name: 'lNext', description: 'Next page navigator', locator: testGDAPLocators.itemGroup.pagination.lNext});
map.addElement('itemGroup_page', {name: 'lLast', description: 'Last page navigator', locator: testGDAPLocators.itemGroup.pagination.lLast});
map.addElement('itemGroup_page', {
name: 'lPage'
, description: 'Specific page navigator'
, args: [
{
name: 'page',
description: 'the page no',
defaultValues: range(1, 50)
}
]
, getLocator: function(args) {
var page = args.page - 1;
return testGDAPLocators.itemGroup.pagination.lPage().replace(/PAGE/g, page);
}
});
// Item grid (at least 1 item in itemGroup)
map.addElement('itemGroup_page', {name: 'gridHeader', description: 'Item grid header', locator: testGDAPLocators.itemGroup.grid.header()});
map.addElement('itemGroup_page', {name: 'grid', description: 'container for items', locator: "//div[@class='results']"});
map.addElement('itemGroup_page', {name: 'gridheader', description: 'grid header', locator: "//div[@class='results']//tr[contains(@class,'headers')]"});
map.addElement('itemGroup_page', {
name: 'gridItemSummary'
, description: 'item summary relative entry'
, args: [{
name: 'index',
description: 'the relative item index',
defaultValues: range(1, 50)
}]
, getLocator: function(args) {
var index = args.index;
return "//div[@class='results']//tr[contains(@class,'summary')][" + index + "]";
}
});
map.addElement('itemGroup_page', {
name: 'gridItemDetail'
, description: 'item detail relative entry'
, args: [{
name: 'index',
description: 'item summary element',
defaultValues: range(1, 50)
}]
, getLocator: function(args) {
var index = args.index;
return "//div[@class='results']//tr[contains(@class,'detail')][" + index + "]";
}
});
var rollups = new RollupManager();
rollups.addRollupRule({
name: 'jobsPageCountJobs'
, description: 'Count how many jobs in the list for the target status, param status=In Draft'
, pre: 'Jobs page is displayed'
, post: 'variable jobsPageCountJobs is populated'
, args: [
{
name: 'status'
, description: "the job state ie 'In Draft'"
, exampleValues: eval(testSharedOptions.jobStates)
}
]
, commandMatchers: []
, getExpandedCommands: function(args) {
var commands = [
{ command:'store', target: '0', value: 'jobsPageCountJobs'},
// In Draft header?
{ command: 'storeElementPresent',
target: 'ui=jobs_page::jobListHeaderByState(state=' + args.status + ')',
value: 'jobsPageCountJobs_present'},
{ command:'gotoIf', target: '!${jobsPageCountJobs_present}', value: 'DONECOUNTING'},
// In Draft header so we have jobs, are they displayed? look for row 1
{ command:'storeVisible',
target: 'ui=jobs_page::jobListJobByRow(state=' + args.status + ', row=1, column=row)',
value: 'jobsPageCountJobs_present'},
{ command:'gotoIf', target: '${jobsPageCountJobs_present}', value: 'PRIMECOUNT'},
// Jobs not visible so click to expand header
{ command:'click',
target: 'ui=jobs_page::jobListHeaderByState(state=In Draft)',
value: 'jobsPageCountJobs'},
{ command:'label', target: 'PRIMECOUNT'},
{ command:'store', target: '1', value: 'jobsPageCountJobs'},
{ command:'label', target: 'DOCOUNT'},
{ command:'storeElementPresent',
target: 'ui=jobs_page::jobListJobByRow(state=In Draft, row=${jobsPageCountJobs} ,column=row)',
value: 'jobsPageCountJobs_present'},
{ command:'gotoIf', target: '!${jobsPageCountJobs_present}', value: 'DONECOUNTING'},
{ command:'storeEval', target: '${jobsPageCountJobs} + 1', value: 'jobsPageCountJobs'},
{ command:'goto', target: 'DOCOUNT'},
{ command:'label', target: 'DONECOUNTING'},
{ command:'storeEval', target: '${jobsPageCountJobs} - 1', value: 'jobsPageCountJobs'},
]
return commands;
}
});
xxx