/// <summary> /// Interprets a model path (selection), selects the node and returns its path. /// </summary> /// <param name="con">Current context of the action instruction.</param> /// <returns>A "path" string</returns> protected string SelectToPath(Context con, string modelPath) { if (modelPath == null || modelPath == "") { return(null); } // only one node or attribute selected gets clicked m_log = Logger.getOnly(); m_log.paragraph(makeNameTag() + " creating one select-path target via " + modelPath); XmlNodeList pathNodes = XmlInstructionBuilder.selectNodes(con, modelPath, makeNameTag()); isNotNull(pathNodes, makeNameTag() + " select-path='" + modelPath + "' returned no model node"); // The modelPath text may have selected a string that is itself xPath! // If so, select on that xPath if (pathNodes.Count == 1 && pathNodes.Item(0).NodeType == XmlNodeType.Text) { // this text node should be an xpath statement string xPathImage = pathNodes.Item(0).Value; m_log.paragraph(makeNameTag() + " selected a text node with more XPATH: " + xPathImage); pathNodes = XmlInstructionBuilder.selectNodes(con, xPathImage, makeNameTag() + " selecting " + xPathImage); isNotNull(pathNodes, makeNameTag() + " selecting " + xPathImage + " from select='" + modelPath + "' returned no model node"); } // Click the first node returned XmlNode node = pathNodes[0]; XmlPath xPath = new XmlPath(node); if (!xPath.isValid()) { fail(makeNameTag() + " XmlPath not constructable from " + node.OuterXml); } return(xPath.Path); }
/// <summary> /// Execute this model node context, specified by @select and /// creating and executing child instructions. /// </summary> public override void Execute() { base.Execute(); if (m_created) { Finished = true; // tell do-once it's done return; // all has been done in the base Context.Execute(). } Context con = (Context)Ancestor(typeof(Context)); isNotNull(con, makeNameTag() + " must occur in some context"); AccessibilityHelper ah = con.Accessibility; isNotNull(ah, makeNameTag() + " context is not accessible"); // If there is a @select, select the nodes if (m_select != null && m_select != "") { // each node or attribute selected creates a context m_log.paragraph(makeNameTag() + " creating selection targets via " + m_select); XmlNodeList pathNodes = XmlInstructionBuilder.selectNodes(con, m_select, makeNameTag()); isNotNull(pathNodes, makeNameTag() + " select='" + m_select + "' returned no model nodes"); // The select text may have selected a string that is itself xPath! // If so, select on that xPath if (pathNodes.Count == 1 && pathNodes.Item(0).NodeType == XmlNodeType.Text) { // this text node should be an xpath statement string xPath = pathNodes.Item(0).Value; m_log.paragraph(makeNameTag() + " selected a text node with more XPATH: " + xPath); pathNodes = XmlInstructionBuilder.selectNodes(con, xPath, makeNameTag() + " selecting " + xPath); isNotNull(pathNodes, makeNameTag() + " selecting " + xPath + " from select='" + m_select + "' returned no model nodes"); } // Create a list of paths to loop over Model lastModel = this; // use as an insert reference node foreach (XmlNode node in pathNodes) { // build the path via each model node XmlPath xPath = new XmlPath(node); // xPath may be invalid - it means it has no guiPath //if (!xPath.isValid()) fail(makeNameTag() + " XmlPath not constructable from " + node.OuterXml); if (1 == m_logLevel) { m_log.paragraph(makeNameTag() + " appPath " + xPath.xPath()); m_log.paragraph(makeNameTag() + " guiPath " + xPath.Path); } Model model = new Model(); model.m_created = true; model.m_modelNode = xPath; model.m_path = xPath.Path; model.m_select = xPath.xPath(); model.m_when = m_when; model.m_name = XmlFiler.getAttribute(node, "name"); model.m_role = XmlFiler.getAttribute(node, "role"); model.m_nodeName = node.Name; model.Number = TestState.getOnly().IncInstructionCount; model.Id += (model.Number - Number).ToString(); model.Parent = con; con.Add(lastModel, model); lastModel = model; // insert the next one after this one. m_log.mark(model); // log the progress of interpretation // if there is content, add instructions to the new model context if (m_elt.HasChildNodes) { foreach (XmlNode xnChild in m_elt.ChildNodes) { // a side-effect of MakeShell is to add the instruction to the model XmlInstructionBuilder.MakeShell(xnChild, model); } } } } Finished = true; // tell do-once it's done }
// look for the expected dialog to appear. If it does, make an accessibilty // helper for it. public override void Execute() { // base.Execute(ts); // can't call this yet as it executes the children Wait(); // do call this but make sure Rest is reset to zero! Rest = 0; // reset to zero so there is no delay after the dialog is found. // number is needed in diagnostics for the log if (Number == -1) { Number = TestState.getOnly().IncInstructionCount; } Process proc = Application.Process; /// If present, use the selected dialog model title Context con = (Context)Ancestor(typeof(Context)); if (m_select != null && m_select != "") { // make a new model context node and move dialog's children to it XmlDocument doc = m_elt.OwnerDocument; XmlElement modElt = doc.CreateElement("model"); modElt.SetAttribute("select", m_select); XmlNodeList children = m_elt.ChildNodes; int count = children.Count; while (count > 0) { // move dialog children to model XmlNode child = children.Item(0); //get the first child modElt.AppendChild(child); // automatically removed from m_elt!! count = children.Count; } m_elt.AppendChild(modElt); // set the title to look for // can only have one text node XmlNodeList pathNodes = XmlInstructionBuilder.selectNodes(this, m_select, makeName()); m_log.isNotNull(pathNodes, "dialog " + this.Id + " select='" + m_select + "' returned no model"); m_log.isTrue(pathNodes.Count > 0, "dialog " + this.Id + " select='" + m_select + "' returned no model nodes"); // This is the model node XmlNode modNode = pathNodes.Item(0); m_title = XmlFiler.getAttribute(modNode, "title"); m_name = XmlFiler.getAttribute(modNode, "name"); m_select = null; // can only do this one time in do-once or model } if (m_title != null && m_title != "") { m_title = Utilities.evalExpr(m_title); } if (m_name != null && m_name != "") { m_name = Utilities.evalExpr(m_name); } m_log.paragraph(image()); // Give the window m_Rest seconds to show up int startTick = System.Environment.TickCount; IntPtr foundHwndPtr; string name = null; while (!m_found) { // If there is a regular expression, try it. if (m_title != null && m_title.StartsWith("rexp#")) { // match the window title via the regular expression Process[] allProcs = Process.GetProcesses(); Regex rx = null; try { rx = new Regex(m_title.Substring(5)); } catch (ArgumentException e) { m_log.paragraph("on-dialog title from rexp# " + m_title.Substring(5) + " error: " + e.Message); break; } for (int p = 0; p < allProcs.Length; p++) { Process pro = allProcs[p]; AccessibilityHelper ah = new AccessibilityHelper(pro.Handle); if (rx.IsMatch(ah.Name)) { m_ah = ah; m_found = true; break; } } } else { // get the window handle for windows with the right name // unfortuneately, other windows, or partially formed windows // seem to be obtained too. foundHwndPtr = FindWindow(null, m_title); if ((int)foundHwndPtr != 0) { // is this the window? Is it completely formed? m_ah = new AccessibilityHelper(foundHwndPtr); if (m_ah == null) { m_log.paragraph("Obtained window with no Accessibiilty!"); } else // this window has accessibility - hope it's fully built { // is this or one of its children the window? name = m_ah.Name; //when name1 = "", m_ah is probably bad - i.e. not an object if (name == "") { } // do nothing, keep looking else if (name.Equals(m_title) || name.Equals(this.m_name)) { // this is likely it m_found = true; } else // m_ah might be the ah for the main app or dialog window { // Maybe one of its children is the window we want m_ah = m_ah.FindChild(m_title, AccessibleRole.Dialog); if (m_ah != null) { // is this the window? name = m_ah.Name; // name1 can't be null if (name == "") { } // do nothing, keep looking else if (name.Equals(m_title) || name.Equals(this.m_name)) { // this might be it m_found = true; } } } } } } if (Utilities.NumTicks(startTick, System.Environment.TickCount) > m_until) { break; // time is up } System.Threading.Thread.Sleep(100); } m_Rest = 0; // don't wait later when base.Execute is invoked if (m_found) { m_DlgHwndStack.Push(m_ah.HWnd); } else { // Didn't find the window m_ah = null; } string contextPass, contextFail; PassFailInContext(OnPass, OnFail, out contextPass, out contextFail); // out m_onPass, out m_onFail); m_log.paragraph("on-dialog: passIn=" + OnPass + " failIn=" + OnFail + " pass="******" fail=" + contextFail); if (!m_found && contextFail == "skip") { return; // quietly exit } isTrue(m_found, "Dialog '" + m_title + @"' was not created or not accessible"); if (name == null) { m_log.paragraph("Wierd: ah exists but name was null - should NEVER happen!!"); name = ""; } if (contextPass == "assert") { fail("Dialog '" + m_title + "' was not supposed to display."); } base.Execute(); m_log.result(this); base.Finished = true; // finished processing this dialog context m_DlgHwndStack.Pop(); if (m_DlgHwndStack.Count > 0) { int hwnd = (int)m_DlgHwndStack.Peek(); SIL.FieldWorks.Common.Utils.Win32.SendMessage((IntPtr)hwnd, (int)SIL.FieldWorks.Common.Utils.Win32.WinMsgs.WM_SETFOCUS, 0, 0); m_log.paragraph("Sent Focus message to containing context object"); // m_ah.Parent.SendWindowMessage((int)SIL.FieldWorks.Common.Utils.Win32.WinMsgs.WM_SETFOCUS,0,0); } }
// When used in a do-once instruction, this call is repeated. // Note the code that keeps m_select from being prepended to m_path more than once. public override void Execute() { base.Execute(); if (m_path != null && m_path == "") { m_path = null; } if (m_select != null && m_select == "") { m_select = null; } if (m_selectPath != null && m_selectPath == "") { m_selectPath = null; } if (m_names != null && m_names == "") { m_names = null; } // must have: // one of select or names to provide a list to check against // with names, one of path or selectPath to get the place to check in the GUI isTrue(m_select != null || m_names != null, makeNameTag() + " must have a 'names' or 'select' attribute."); if (m_names != null) { isTrue(m_path != null || m_selectPath != null, makeNameTag() + " must have a 'path' or 'selectPath' attribute with 'names'."); } Context con = (Context)Ancestor(typeof(Context)); isNotNull(con, makeNameTag() + " must occur in some context"); m_path = Utilities.evalExpr(m_path); m_selectPath = Utilities.evalExpr(m_selectPath); m_select = Utilities.evalExpr(m_select); // set the gui path from path or select if (m_select != null && !m_doneOnce) { // set m_names and possibly m_path m_log.paragraph(makeNameTag() + " creating selection targets via " + m_select); XmlNodeList pathNodes = XmlInstructionBuilder.selectNodes(con, m_select, makeNameTag()); isNotNull(pathNodes, makeNameTag() + " select='" + m_select + "' returned no model node"); // The @select text may have selected a string that is itself xPath! // If so, select on that xPath if (pathNodes.Count == 1 && pathNodes.Item(0).NodeType == XmlNodeType.Text) { // this text node should be an xpath statement string xPathImage = pathNodes.Item(0).Value; m_log.paragraph(makeNameTag() + " selected a text node with more XPATH: " + xPathImage); pathNodes = XmlInstructionBuilder.selectNodes(con, xPathImage, makeNameTag() + " selecting " + xPathImage); isNotNull(pathNodes, makeNameTag() + " selecting " + xPathImage + " from select='" + m_select + "' returned no model node"); } if (pathNodes.Count >= 1) { // there are some nodes - make a list m_names = null; foreach (XmlNode xname in pathNodes) { if (m_names == null) { if (m_path == null) { XmlPath xPath = new XmlPath(xname.ParentNode); m_path = xPath.Path; } } else { m_names += "/"; } string name = XmlFiler.getAttribute(xname, "name"); if (name == null || name == "") { m_names += "#NONE"; } else { m_names += name; } } } m_doneOnce = true; } string sPath = ""; if (m_selectPath != null && m_selectPath != "") { sPath = SelectToPath(con, m_selectPath); } m_path = sPath + m_path; GuiPath gpath = new GuiPath(m_path); isNotNull(gpath, makeNameTag() + " attribute path='" + m_path + "' not parsed"); if (m_names != null) { m_list = Utilities.ParsePath(m_names); } PassFailInContext(m_onPass, m_onFail, out m_onPass, out m_onFail); AccessibilityHelper ah = con.Accessibility; isNotNull(ah, makeNameTag() + " context not accessible"); //check to see if it is visible m_Result = false; ah = gpath.FindInGui(ah, null); if (ah != null) { m_Result = GlimpseGUI(ah); } Finished = true; // tell do-once it's done if ((m_onPass == "assert" && m_Result == true) || (m_onFail == "assert" && m_Result == false)) { if (m_message != null) { fail(m_message.Read()); } else { fail(makeNameTag() + " Result = '" + m_Result + "', on-pass='******', on-fail='" + m_onFail + "'"); } } Logger.getOnly().result(this); }