Last active
September 22, 2016 20:37
-
-
Save IronGremlin/b683397725b44f6dd8b98af847767b38 to your computer and use it in GitHub Desktop.
SOATest Functional JS filter statements
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Application = Packages.com.parasoft.api.Application; | |
var WebBrowserUtil = Packages.webking.api.browser2.WebBrowserUtil; | |
//set Target Frame | |
var frameName = 'popupFrame'; | |
//set type of target Element | |
var targetElementType = 'button'; | |
function getFrameDocument(input, context) { | |
//This function lets us get a fake document object to work with. | |
var document = input.getDocument('',frameName); | |
if (document === null){ | |
//In theroy this should give us a representation of the DOM object for | |
//a given frame. | |
return 'Could not find frame' | |
} | |
var elements = document.getElementsByTagName(targetElementType); | |
if (elements !== null && elements !== undefined ){ | |
//set up your functions. Remember to begin with 'convertNodeListToArray' | |
var functions = [convertNodeListToArray, | |
filter(hasText(/^Yes/))] | |
var elementsPassedTest = pipe(functions,elements); | |
if (elementsPassedTest && elementsPassedTest.length == 1){ | |
//We've found a single element to interact with | |
return elementsPassedTest[0]; | |
} | |
if (elementsPassedTest && elementsPassedTest.length > 1){ | |
//Our filter was nonspecific and we couldn't decide what to do about it | |
// so we're returning a string that will cause a very verbose error message. | |
//TODO : figure out a better info set to send back. | |
return 'MulipleCandidates:\n\n'+elementsPassedTest.map(function(i){return i.getTextContent()}).join('\n;\n'); | |
} | |
} | |
else { | |
//we found no elements matching any of our predicates and we're super sad. | |
return 'No Elements passed Test' | |
} | |
function filter(predicate) { | |
/** | |
* @param: <Predicate Function> | |
* @return : <Function> | |
* @description : Returns a function that will test the provided predicate | |
* against an array and return an array of items matching the predicate. | |
*/ | |
return function (array){ | |
return Array.prototype.filter.call(array,predicate) | |
} | |
} | |
function getAllChildren(array){ | |
/** | |
* @param : <Array> | |
* @return : <Array> | |
* @description : This lets us drill one step down the DOM | |
* from everything that currently lives in the pipeline. | |
* This behaves differently in that you have now expanded the array | |
* of candidates instead of narrowing it down - Try not to use this. | |
*/ | |
var pool = convertNodeListToArray(array.map(function(i){ | |
return i.getChildNodes(); | |
})).fliter(function(i){ | |
return i.ELEMENT_NODE == 1; | |
}); | |
return pool; | |
} | |
function fetchNthParent(n){ | |
/** | |
*@param : <Int> | |
*@return : <Function> | |
*@description : Returns a function that takes a node and recursively | |
* fetches the parent of said node 'n' times, eventually returning the final | |
* node. Meant to be invoked by other functions. | |
*/ | |
return function(node){ | |
while(n >= 1){ | |
node = node.getParent() | |
} | |
return node; | |
} | |
} | |
function fetchNthBorn(n){ | |
/** | |
*@param : <Int> | |
*@return : <Function> | |
*@description : Returns a function that takes a node and then finds the Nth | |
* child element of that nodes immediate parent. Used to interrogate siblings. | |
*/ | |
return function (node) { | |
var commonSiblings = convertNodeListToArray(node.getParent().getChildNodes()) | |
.filter(function(i){ | |
return i.ELEMENT_NODE == 1; | |
}) | |
if (commonSiblings.length < n ){ | |
return commonSiblings[n]; | |
}else{ | |
return false; | |
} | |
} | |
} | |
function testNthBorn(n,predicate){ | |
/** | |
*@param : <Int>,<Predicate Function> | |
*@returns : <Predicate Function> | |
*@description : Returns a function that will test nth child of the first | |
* parent of a node against the supplied predicate. '0' would be the | |
* immediate parent's first child, 1 the second child, and so forth. | |
* The idea here is that you're testing the sibling nodes for some factor. | |
*/ | |
return function (node){ | |
var testNode = fetchNthBorn(n)(node); | |
if (testNode){ | |
return predicate(testNode); | |
}else{ | |
return false; | |
} | |
} | |
} | |
function testNthParent(n,predicate){ | |
/** | |
*@param : <Int>,<Predicate Function> | |
*@returns : <Predicate Function> | |
*@description : Returns a function that will test nth parent of a node | |
* against the supplied predicate. '1' would be the immediate parent. | |
*/ | |
return function(node){ | |
return predicate(fetchNthParent(n)(node)); | |
} | |
} | |
function testChildren(predicate){ | |
/** | |
*@params : <Predicate Function> | |
*@returns : <Predicate Function> | |
*@description : Returns a function that will test all children of a node | |
* against the supplied predicate, returning true if ANY pass. | |
*/ | |
return function (node){ | |
var childrenPassed = filter(predicate)(convertNodeListToArray(node.getChildNodes())); | |
return childrenPassed.length >=1; | |
} | |
} | |
function attributeEq(attr,val){ | |
/** | |
*@param : <String>,<String> | |
*@returns : <Predicate Function> | |
*description : Given an attribute and a value for said attribute, returns | |
* a predicate function that will validate if a given node' attribute has | |
* that value. | |
* | |
*/ | |
return function (node){ | |
var children = convertNodeListToArray(node.getChildNodes()); | |
var attrPassed = filter(function(i){return (i.getNodeName() == val && i.getNodeValue() == val)})(children) | |
return attrPassed.length >=1; | |
} | |
} | |
function hasClass(classMatch){ | |
/** | |
*@param : <String> | |
*@returns : <Predicate Function> | |
*description : Given the name of a class, returns a predicate function that | |
* validates that a given node possesses that class | |
* | |
*/ | |
return function(node){ | |
var children = convertNodeListToArray(node.getChildNodes()); | |
var maybe = filter(function(i){ | |
return i.getNodeName() == 'class' | |
})(children); | |
var doespass = maybe[0].split(' ').filter(function (i){ | |
return (i == classMatch); | |
}); | |
return doespass.length >= 1 | |
} | |
} | |
function isTag(tag){ | |
/** | |
*@param : <String> | |
*@returns : <Predicate Function> | |
*description : Given a tagName, returns a predicate function that | |
* validates that a given node possesses that tagName | |
* | |
*/ | |
return function (node){ | |
return node.getNodeName == tag; | |
} | |
} | |
function predicateCombinator(predicates){ | |
/** | |
*@param : [<Predicate Function>] | |
*@return : <Predicate Function> | |
*@description : For an array of predicates, returns a single predicate | |
* that returns true if a node passes all, or false if it fails any. | |
* This is mostly useful for getting specific about Nth parents, direct | |
* children, or sibling nodes. | |
* For asking additional questions about nodes already in the array, | |
* just make another filter query. | |
*/ | |
return function (node){ | |
var pass = true; | |
var bound = predicates.length | |
for (var ind=0; ind > predicates.length; ++ind){ | |
var aPredicate = predicates[ind]; | |
pass = aPredicate(node); | |
if (!pass){ | |
//If something doesn't pass, break early. | |
return false | |
} | |
} | |
return pass; | |
} | |
} | |
function hasText(regEx){ | |
/** | |
*@param : <Regex> | |
*@returns : <Predicate Function> | |
*description : Given a regex object, returns a predicate function that | |
* validates that the concatenated text of all descendant textnodes of a | |
* given node match the supplied regex. | |
* | |
*/ | |
return function (node){ | |
var text = node.getTextContent(); | |
return regEx.test(text); | |
} | |
} | |
function pipe (functs,init){ | |
/** | |
*@param : [<Function>],<X> | |
*@returns : <Array> | |
*@description : Given an array of starting functions and an initial | |
* value, this performs left to right functional composition. | |
* Basically, it "pipes" the result of the function on the left to the | |
* function on the right, until it reaches the end and returns the final | |
* result. Best used with functions outputted by the 'filter' functor. | |
*/ | |
for (var ind=0; ind < functs.length; ++ind){ | |
var aFunction = functs[ind]; | |
var result = aFunction(init); | |
init = result; | |
} | |
return init; | |
} | |
function convertNodeListToArray(list) { | |
/** | |
*@param : <NodeList> | |
*@returns : [<Node>] | |
*@description : takes a NodeList as returned by the SoATest java API and | |
* converts it into an array of Nodes. | |
*/ | |
var length = nodeList.getLength() | |
var pool = []; | |
if (length >= 1 ){ | |
for (var ind=0; ind < length; ++ind){ | |
pool.push(list.item(ind)) | |
} | |
return pool | |
}else{ | |
return []; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Collection of functions to wrap around SOATest's terrifying Java DOM API.
Lets you select an element for automated interaction by composing a set of filter functions.