Have you ever faced the issue where finding an UI element using TestStack White SearchCriteria API returns null? If yes, here are few alternatives that utilises the AutomationElement.
1 2 3 4 5 |
var tabGroup = window.Get<Tab>(SearchCriteria.ByControlType(ControlType.Tab));//return null //OR var tabUi = window.Get<UIItem>(SearchCriteria.ByAutomationId("ToolWindowTabGroupId"));//return null //OR var tabGroup = window.Get<Tab>(SearchCriteria.ByClassName("ToolWindowTabGroup"));//return null |
The alternative approach uses AutomationElement which is part of the Microsoft UI Automation API. Simply, it iterates through the children elements of AutomationElement of the White UI elmement.
Extension Methods
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
public static class AutomationExtensions { #region Find Methods public static AutomationElement FindByHelpText(this AutomationElement automationElement, string helpText) { var children = automationElement.Children().ToList(); return children.FirstOrDefault(a => a.Current.HelpText == helpText); } public static AutomationElement FindByAutomationId(this AutomationElement automationElement, string id) { var children = automationElement.Children().OfType<AutomationElement>(); return children.FirstOrDefault(a => Equals(a.Current.AutomationId, id)); } public static IEnumerable<AutomationElement> FindAll(this AutomationElement automationElement, ControlType controlType) { var children = automationElement.Children().ToList(); return children.Where(a => Equals(a.Current.ControlType, controlType)); } public static IEnumerable<AutomationElement> FindAllByClassName(this AutomationElement automationElement, string className) { var children = automationElement.Children().OfType<AutomationElement>(); return children.Where(a => Equals(a.Current.ClassName, className)); } public static AutomationElement FindByName(this AutomationElement automationElement, string name) { var children = automationElement.Children().ToList(); return children.FirstOrDefault(a => a.Current.Name == name); } #endregion #region Conversions public static AutomationElementCollection Children(this AutomationElement rootElement) { return rootElement.FindAll(TreeScope.Children | TreeScope.Element | TreeScope.Descendants, Condition.TrueCondition); } public static AutomationElementCollection Children(this IUIItemContainer container) { return container.AutomationElement.Children(); } public static IList<AutomationElement> ToList(this AutomationElementCollection collection) { var list = new List<AutomationElement>(); foreach (AutomationElement automationElement in collection) { list.Add(automationElement); } return list; } public static void Invoke(this AutomationElement automationElement) { object patternObject; automationElement.TryGetCurrentPattern(InvokePattern.Pattern, out patternObject); var invokePattern = patternObject as InvokePattern; invokePattern?.Invoke(); } public static IList<AutomationElement.AutomationElementInformation> AutomationElementInformations(this AutomationElementCollection collection) { var list = new List<AutomationElement.AutomationElementInformation>(); foreach (AutomationElement automationElement in collection) { list.Add(automationElement.Current); } return list; } #endregion } |
Example
Use VisualUIAVerifyNative.exe to read identification properties of the desired control.
1 2 3 4 5 6 7 |
//window is TestStack.White.UIItems.WindowItems.Window object. var tabGroupElement = window.AutomationElement.FindAllByClassName("ToolWindowTabGroup"); //OR var tabGroupElement = window.AutomationElement.FindByAutomationId("TAB_ST:0:0:{131369f2-062d-44a2-8671-91ff31efb4f4}"); //OR var buttonElement = window.AutomationElement.FindByHelpText("sensibleHelpText"); buttonElement?.Invoke();//clicks the button |