/// <summary> /// Function that retrieves the Automation element in which we want to act. /// </summary> /// <param name="curNode">The current node of the tree in which we start.</param> /// <param name="relPath">The relative path at the starting point.</param> /// <param name="dstPath">The destination path we want to reach.</param> /// <returns>Either and error or the Node that was being looking for.</returns> public static Either <WalkerError, AutomationElement> walkTree(AutomationElement curNode , List <VTreeNode> relPath , List <Either <STreeNode, CTreeNode> > dstPath) { var iniState = new WState { relPath = new List <VTreeNode>(relPath) , destPath = new List <Either <STreeNode, CTreeNode> >(dstPath) , curAutNode = curNode }; var fState = whileS(walkNode, checkState, iniState); var res = fState.Match <Either <WalkerError, AutomationElement> >( Left: (wstate) => { return(wstate.curAutNode); }, Right: (werror) => { return(werror); } ); return(res); }
/// <summary> /// Make a step throught the UI Automation Tree /// </summary> /// <param name="curState"> /// State to be computed and actualized. /// </param> /// <returns> /// Either a new state or a error. /// </returns> public static Either <WState, WalkerError> walkNode(WState curState) { if (!curState.destPath.Any()) { var error = new WalkerError { nodeError = new NodeError { errCode = NodeErrCode.WrongMove , descr = "No destination path." } , errorPath = curState.relPath }; } var curAutNode = curState.curAutNode; var curDestPath = curState.destPath; var curRelPath = curState.relPath; // Update variables for current iteration. var nextNode = curDestPath.First(); curRelPath.Add(new VTreeNode { name = curAutNode.Current.Name }); Either <NodeError, AutomationElement> procNodeRes = nextNode.Match <Either <NodeError, AutomationElement> >( Left: (sNode) => { var nNode = makeMove(sNode, curAutNode); var nextMoveRes = nNode.Match <Either <NodeError, AutomationElement> >( Left: (nodeError) => { return(nodeError); }, Right: (nxtNode) => { return(nxtNode); } ); return(nextMoveRes); }, Right: (cNode) => { var t = new TaskCompletionSource <Option <WalkerError> >(); var lScope = cNode.postActionEvents.Item2.scope; var eventType = cNode.postActionEvents.Item2.changeType; var property = cNode.postActionEvents.Item1; var tP = addSyncPropertyEventWatcher(curAutNode, TreeScope.Children, property); var tS = addSyncStructureEventWatcher(curAutNode, lScope, eventType); // Return not used, need to refactor this var inkRes = invkNodeAction(cNode, curAutNode); var cRes = inkRes.Match <Either <NodeError, AutomationElement> >( Some: (nodeError) => { return(nodeError); }, None: () => { var pChangeRes = tP.Result; if (pChangeRes == None) { var sChangeRes = tS.Result; if (sChangeRes == None) { var nNode = makeMove(cNode.sNode, curAutNode); var nextMoveRes = nNode.Match <Either <NodeError, AutomationElement> >( Left: (_nodeError) => { return(_nodeError); }, Right: (_nxtNode) => { return(_nxtNode); } ); return(nextMoveRes); } else { return(new NodeError { errCode = NodeErrCode.InvalidOp , descr = "Structure Change Error" }); } } else { return(new NodeError { errCode = NodeErrCode.InvalidOp , descr = "Property Change Error" }); } } ); var resVal = cRes.Match <Either <NodeError, AutomationElement> >( Left: (nError) => { return(nError); }, Right: (autElem) => { return(autElem); } ); return(resVal); } ); var itRes = procNodeRes.Match <Either <WalkerError, AutomationElement> >( Left: (nodeError) => { return(new WalkerError { nodeError = nodeError, errorPath = curRelPath }); }, Right: (autNode) => { return(autNode); } ); var fRes = itRes.Match <Either <WState, WalkerError> >( Left: (walkerError) => { return(walkerError); }, Right: (autElem) => { curDestPath = updatePath(curDestPath); return(new WState { relPath = curRelPath , destPath = curDestPath , curAutNode = curAutNode }); } ); return(fRes); }