/// <summary> /// Will wait for the element to have one of the specified names. /// </summary> /// <remarks> /// Will TestServices.Assert on timeout. /// </remarks> /// <param name="element">The AutomationElement to watch.</param> /// <param name="strings">The text to wait for.</param> public static void WaitForText(AutomationElement element, string[] strings) { DateTime end = DateTime.Now.AddMilliseconds(Timeout); bool foundText = false; while ((!foundText) && (DateTime.Now < end)) { foreach (string text in strings) { if (element.Current.Name.Equals(text, StringComparison.CurrentCultureIgnoreCase)) { foundText = true; break; } else { System.Threading.Thread.Sleep(Interval); } } } TestServices.Assert( foundText, "None of the desired strings were found: {0}", strings); }
/// <summary> /// Walks the Automation Tree from the specified root, searching for the element with the given property. /// (Stolen from HostingHelper used by DrtLaunchContainer) /// </summary> /// <param name="root">The root to start searching from</param> /// <param name="property">The property to search for</param> /// <param name="value">The possible values of above property</param> /// <param name="maxDepth">The maximum depth to search</param> /// <param name="allowPartialMatch">Allow partial matches (i.e. for window titles)</param> /// <returns></returns> public static AutomationElement FindElementWithPropertyValue(AutomationElement root, AutomationProperty property, object[] values, int maxDepth, bool allowPartialMatch) { AutomationElement outElement = null; DateTime end = DateTime.Now.AddMilliseconds(Timeout); while ((outElement == null) && (DateTime.Now < end)) { foreach (object value in values) { if (FindElementWithPropertyValueImpl(root, property, value, maxDepth, allowPartialMatch, 0 /* currentDepth */, ref outElement)) { break; } System.Threading.Thread.Sleep(Interval); } } TestServices.Assert( outElement != null, "The specified element was not found. Looking for values:", values); return(outElement); }
/// <summary> /// Will wait for a window with that name to exist and return it. /// </summary> /// <remarks> /// Will TestServices.Assert on timeout if assertOnFailure is set. /// </remarks> /// <param name="windowName">Exact name of window.</param> /// <param name="assertOnFailure">Whether to assert if the window is not found.</param> /// <param name="timeout">Maximum time to wait, in milliseconds.</param> /// <returns>The AutomationElement for the window or null if it times out and /// assertOnFailure is set.</returns> public static AutomationElement FindWindow(string windowName, bool assertOnFailure, int timeout) { AutomationElement result = null; DateTime end = DateTime.Now.AddMilliseconds(timeout); while ((result == null) && (DateTime.Now < end)) { IntPtr hWnd = UnsafeNativeMethods.FindWindow(null, windowName); if (hWnd != IntPtr.Zero) { result = AutomationElement.FromHandle(hWnd); } System.Threading.Thread.Sleep(Interval); } if (assertOnFailure) { TestServices.Assert( result != null, "Window {0} was not found.", windowName); } return(result); }
/// <summary> /// Will wait for the first descendant with that name to exist. /// </summary> /// <remarks> /// Will TestServices.Assert on timeout if assertOnFailure is set. /// /// UISpy is immensely valuable for discovering property names and ids. /// Locaiton: ($SDXROOT)windows\accessibletech\wap\tools\uispy /// </remarks> /// <param name="container">The AutomationElement to search within. /// </param> /// <param name="name">Exact name of the AutomationElement to look for. /// </param> /// <param name="assertOnFailure">Whether to TestServices.Assert if the element is not found. /// </param> /// <returns>The AutomationElement for the descendant or null if it /// times out and assertOnFailure is unset</returns> public static AutomationElement FindDescendantByName( AutomationElement container, string name, bool assertOnFailure) { AutomationElement result = null; DateTime end = DateTime.Now.AddMilliseconds(Timeout); while ((result == null) && (DateTime.Now < end)) { Condition cond = new PropertyCondition( AutomationElement.NameProperty, name); result = container.FindFirst(TreeScope.Descendants, cond); System.Threading.Thread.Sleep(Interval); } TestServices.Assert(!assertOnFailure || (result != null), "Descendant {0} was not found.", name); if (result != null) { TraceAutomationElement("FoundByName", result); } return(result); }
/// <summary> /// See if this element has a specified property with specified value. /// </summary> /// <param name="root">The root of this element</param> /// <param name="property">The property to check</param> /// <param name="value">The value to check for</param> /// <param name="allowPartialMatch">Whether to allow partial matches</param> /// <returns></returns> private static bool IsElementWithPropertyValue(AutomationElement root, AutomationProperty property, object value, bool allowPartialMatch) { // Get the value and see if you found it. object actualValue = root.GetCurrentPropertyValue(property); if (value.Equals(actualValue)) { return(true); } // Assume that the value is a string if allowPartialMatch is true. if (allowPartialMatch) { string expectedString = value as string; string actualString = actualValue as string; if (actualString == null) { return(false); } TestServices.Assert(expectedString != null, "value must be string when allowPartialMatch is true."); if (actualString.ToLower().IndexOf(expectedString.ToLower()) != -1) { return(true); } } return(false); }
/// <summary> /// Attaches PackageProperties to an XpsDocument. /// </summary> /// <param name="coreProperties">The PackageProperties to attach.</param> /// <param name="rp">The Xps package that will contain the properties.</param> private static void AttachCorePropertiesToPackage(PackageProperties coreProperties, XpsDocument rp) { TestServices.Assert(rp.CoreDocumentProperties != null, "XpsDocument.CoreDocumentProperties is null, cannot set new property values."); rp.CoreDocumentProperties.Category = coreProperties.Category; rp.CoreDocumentProperties.ContentStatus = coreProperties.ContentStatus; rp.CoreDocumentProperties.ContentType = coreProperties.ContentType; rp.CoreDocumentProperties.Creator = coreProperties.Creator; if (coreProperties.Created.HasValue) { rp.CoreDocumentProperties.Created = coreProperties.Created.Value; } if (coreProperties.Modified.HasValue) { rp.CoreDocumentProperties.Modified = coreProperties.Modified.Value; } rp.CoreDocumentProperties.Description = coreProperties.Description; rp.CoreDocumentProperties.Identifier = coreProperties.Identifier; rp.CoreDocumentProperties.Keywords = coreProperties.Keywords; rp.CoreDocumentProperties.Language = coreProperties.Language; rp.CoreDocumentProperties.LastModifiedBy = coreProperties.LastModifiedBy; if (coreProperties.LastPrinted.HasValue) { rp.CoreDocumentProperties.LastPrinted = coreProperties.LastPrinted.Value; } rp.CoreDocumentProperties.Revision = coreProperties.Revision; rp.CoreDocumentProperties.Subject = coreProperties.Subject; rp.CoreDocumentProperties.Title = coreProperties.Title; rp.CoreDocumentProperties.Version = coreProperties.Version; }
/// <summary> /// Finds the requested element from its Automation ID and sets text in it, /// throwing an assert if the element returned is null. /// </summary> /// <param name="parent">The parent under which the element we're searching for lives.</param> /// <param name="automationID">The automation ID to search for under the parent</param> public static void FindAndSetText(AutomationElement parent, string automationID, string text) { AutomationElement element = AutomationHelper.FindDescendantById(parent, automationID); TestServices.Assert(element != null, "Could not find the element with Automation ID '" + automationID + "'"); AutomationHelper.SetText(element, text); }
/// <summary> /// Will wait for the call to complete. /// </summary> /// <remarks> /// Will TestServices.Assert on timeout. /// </remarks> public void WaitForCall() { if (!_callComplete.WaitOne(_timeout, false)) { TestServices.Assert( false, "Timeout after waiting {0}ms for step.", _timeout); CancelCall(); } }
/// <summary> /// Finds the requested element from its Automation ID and invokes it, /// throwing an assert if the element returned is null. /// </summary> /// <param name="parent">The parent under which the element we're searching for lives.</param> /// <param name="automationID">The automation ID to search for under the parent</param> public static void FindAndInvoke(AutomationElement parent, string automationID) { //Find the element AutomationElement element = AutomationHelper.FindDescendantById(parent, automationID); TestServices.Assert(element != null, "Could not find the element with Automation ID '" + automationID + "'"); //Invoke the element AutomationHelper.Invoke(element); }
public void ValidatePortInUse() { using (WebServer ws = new WebServer(new Uri[0], 135)) { ws.Start(); ws.Stop(); TestServices.Assert( ws.BaseUri.Port != 135, "A random port number was not assigned."); } }
/// <summary> /// Watches a Process for failure; a non-zero exit code. /// /// Will TestServices.Assert on failure. /// /// ThreadSafe /// </summary> /// <param name="info">Process information.</param> private void WatchForFailure(ProcessInfo info) { lock (info) // Lock: Scope=Class Order=1 { // validate it is supposed to be watched if (!info.AssertOnFailure) { return; } // validate that it has exited if (!info.Process.HasExited) { return; } // we don't want to handle this process agian info.AssertOnFailure = false; } Process process = info.Process; // assert on failure codes for exited processes try { if (process.ExitCode != 0) { TestServices.Assert( true, "Process: {0}[{1}] exited with failure code: {2}.", info.Name, process.Id, process.ExitCode); } else { TestServices.Log( "Process: {0}[{1}] exited with code: {2}.", info.Name, process.Id, process.ExitCode); } } catch (InvalidOperationException) { TestServices.Log( "Process: {0}[{1}] exited, but the exit code could not be determined, possibly because we didn't start it.", info.Name, process.Id); } }
/// <summary> /// Ended the call immediately; before execution is complete. /// </summary> private void EndCall() { _thread.Interrupt(); if (_callComplete != null) { _callComplete.Set(); } else { TestServices.Assert( false, "We are ending a call that was never started."); } _ended = DateTime.Now; }
/// <summary> /// Will press the key, and verify that the requested element is focused. /// </summary> /// <param name="key"></param> /// <param name="element"></param> public static void PressKeyCheckFocus( Key key, AutomationElement newElement) { AutomationHelper.InputKey(key); // Wait for new element to take focus. WaitForFocus(newElement); // Check if the new element was correctly assigned focus. TestServices.Assert(newElement.Current.HasKeyboardFocus, "Key {0} failed; {1} should have focus, but {2} does.", key.ToString(), newElement.Current.AutomationId, AutomationElement.FocusedElement.Current.AutomationId); }
/// <summary> /// Waits until the given element has received focus. /// </summary> /// <param name="element"></param> public static void WaitForFocus(AutomationElement element) { DateTime end = DateTime.Now.AddMilliseconds(Timeout); while (DateTime.Now < end) { //Does the element have focus? Then we're done. if (element.Current.HasKeyboardFocus) { return; } System.Threading.Thread.Sleep(Interval); } TestServices.Assert(false, "The requested element did not receive focus."); }
/// <summary> /// Similar to FindAndInvoke, with the difference that this method /// performs a "manual" (non-input pattern) invocation of the element to work around /// automation issues with modal dialogs. /// </summary> /// <param name="parent">The parent under which the element we're searching for lives.</param> /// <param name="automationID">The automation ID to search for under the parent</param> /// <param name="failSilently">If true, we will simply return if the element can't be /// found or can't be focused. If false, we throw an exception.</param> public static void FindAndManualInvoke( AutomationElement parent, string automationID, bool failSilently) { //We do the invoke differently here due to an unfortunate issue where //Invoke()ing a Winforms Button that brings up a Modal Dialog //will not return until the Modal Dialog is closed. //This obviously would prevent this test from continuing on past that point. //What we're doing to work around the issue is to put focus on the button and invoke //an Enter keypress to bring up the dialog. AutomationElement element = AutomationHelper.FindDescendantById( parent, automationID, !failSilently); if (failSilently && (element == null)) { TestServices.Log("warning - FindAndManualInvoke could not locate " + automationID); return; } TestServices.Assert(element != null, "Could not find the element with Automation ID '" + automationID + "'"); //Focus the element try { element.SetFocus(); } catch (InvalidOperationException) { if (failSilently) { TestServices.Log("warning - FindAndManualInvoke could not focus " + automationID); return; } else { throw; } } //Ensure the element has focus before continuing. WaitForFocus(element); //Invoke the "Enter" key to raise the dialog Input.SendKeyboardInput(Key.Enter, true); WaitForUIRefresh(); Input.SendKeyboardInput(Key.Enter, false); }
/// <summary> /// Will press the given key gesture, and verify that the requested element is focused. /// </summary> /// <param name="gesture"></param> /// <param name="element"></param> public static void PressKeyCheckFocus( KeyGesture gesture, AutomationElement newElement) { AutomationHelper.InputKeyGesture(gesture); // Wait for new element to take focus. WaitForFocus(newElement); // Check if the new element was correctly assigned focus. TestServices.Assert(newElement.Current.HasKeyboardFocus, "Gesture [{0}+{1}] failed; {2} should have focus, but {3} does.", gesture.Modifiers.ToString(), gesture.Key.ToString(), newElement.Current.AutomationId, AutomationElement.FocusedElement.Current.AutomationId); }
/// <summary> /// Waits until the given element has the IsEnabled state set to the same state is the /// IsEnabled param. /// </summary> /// <param name="element"></param> /// <param name="element"></param> public static void WaitForIsEnableChange(AutomationElement element, bool targetEnabledState) { DateTime end = DateTime.Now.AddMilliseconds(Timeout); while (DateTime.Now < end) { //Is the element enabled to match the target state? Then we're done. if (element.Current.IsEnabled == targetEnabledState) { return; } System.Threading.Thread.Sleep(Interval); } TestServices.Assert(false, "The requested element IsEnabled state was never marked: " + targetEnabledState.ToString()); }
/// <summary> /// Waits for the window with the given name to close. /// </summary> /// <remarks> /// Asserts if the window does not close within the given timeout. /// </remarks> /// <param name="windowName">Exact name of window.</param> public static void WaitForWindowClose(string windowName) { DateTime end = DateTime.Now.AddMilliseconds(Timeout); while (DateTime.Now < end) { IntPtr hWnd = UnsafeNativeMethods.FindWindow(null, windowName); //The window no longer exists. if (hWnd == IntPtr.Zero) { return; } System.Threading.Thread.Sleep(Interval); } TestServices.Assert(false, "Window {0} did not close.", windowName); }
/// <summary> /// Will return all the dependencies (as defined by WaitFor) on a call. /// </summary> /// <remarks> /// Current implementation assumes a default plan where calls map 1:1 to /// methods marked as test steps. This will need to change for XML /// plans. /// </remarks> /// <param name="attribute">The attribute for which we would like the /// dependent calls.</param> /// <param name="knownCalls">A dictionary of known calls with the name /// of the test step as the key.</param> /// <returns>A list of the dependent calls from the knownCalls /// parameter.</returns> private static Call[] GetDependencies( TestStepAttribute attribute, Dictionary<string, Call> knownCalls) { string waitForList = attribute.WaitFor; // PreCondition: if there is no list, return an empty array if (string.IsNullOrEmpty(waitForList)) { return new Call[0]; } // turn the comman seperated list into an array string[] callNames = waitForList.Split( CultureInfo.InvariantCulture .TextInfo.ListSeparator.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); // return array size matches the list Call[] dependencies = new Call[callNames.Length]; // look up the dependent call and store it in the array for (int i = 0; i < callNames.Length; i++) { string callName = callNames[i].Trim(); if (knownCalls.ContainsKey(callName)) { dependencies[i] = knownCalls[callName]; } else { // fail if there is an unknown dependency TestServices.Assert( false, "WaitFor call named {0} not found.", callName); } } return dependencies; }
/// <summary> /// Create a process and manage its' lifetime. /// </summary> /// <param name="startInfo">Start-up information for the process.</param> /// <param name="assertOnFailure">If true ProcessManager will /// TestServices.Assert on a non-zero exit code.</param> /// <returns>A new Process</returns> public Process Create(ProcessStartInfo startInfo, bool assertOnFailure) { Process p = Process.Start(startInfo); ProcessInfo info = new ProcessInfo( p, Path.GetFileName(startInfo.FileName), assertOnFailure); if (p != null) { AddToJob(info); SafeAdd(info); TestServices.Trace( "Process: {0}[{1}] {2} created.", info.Name, info.Process.Id, startInfo.Arguments); } else { if (assertOnFailure) { TestServices.Assert( true, "Process: {0}[n/a] {1} could not be created.", info.Name, startInfo.Arguments); } else { TestServices.Warning( "Process: {0}[n/a] {1} could not be created.", info.Name, startInfo.Arguments); } } return(p); }
//---------------------------------------------------------------------- // Constructors //---------------------------------------------------------------------- /// <summary> /// Creates a Call that will use the MethodInvoker to invoke the Method /// with the specified arguments on the object. /// </summary> /// <param name="invoker">The MethodInvoker to use for the call.</param> /// <param name="method">The Method to call.</param> /// <param name="target">The Target of the call.</param> /// <param name="args">The Parameters use for the call.</param> /// <param name="dependencies">The calls this call will wait on prior to /// invoking.</param> public Call( MethodInvoker invoker, MethodInfo method, object target, object[] args, Call[] dependencies) { _invoker = invoker; Method = method; Target = target; Parameters = args; _dependencies.AddRange(dependencies); TestStepAttribute attrib = TestServices.GetFirstAttribute( typeof(TestStepAttribute), Method) as TestStepAttribute; if (attrib != null) { _timeout = attrib.Timeout; _delay = attrib.Delay; _async = attrib.Async; _order = attrib.Order; } else { TestServices.Assert( false, "Method does not have the TestStep attribute."); } if (_forceNoTimeout & (_timeout != Timeout.Infinite)) { TestServices.Trace( "Forcing Timeout.Infinite on {0} was {1}.", method.Name, _timeout); _timeout = Timeout.Infinite; } }
/// <summary> /// Waits for the address bar in a given IE window to display the /// specified address. /// </summary> /// <remarks> /// Will TestServices.Assert on timeout. /// </remarks> /// <param name="ieWindow">The IE window</param> /// <param name="address">The address to wait for</param> public static void WaitForAddressBarText(AutomationElement ieWindow, string address) { // wait for the address bar to show the new document AutomationElement addressBar = AutomationHelper.FindDescendantById(ieWindow, "41477"); Condition editClassCondition = new PropertyCondition(AutomationElement.ClassNameProperty, "Edit"); addressBar = addressBar.FindFirst(TreeScope.Descendants, editClassCondition); TestServices.Assert( addressBar != null, "Address bar edit control was not found."); TraceAutomationElement("AddressBar", addressBar); DateTime end = DateTime.Now.AddMilliseconds(Timeout); bool foundAddress = false; while ((!foundAddress) && (DateTime.Now < end)) { TextPattern textPattern = (TextPattern)(addressBar.GetCurrentPattern(TextPattern.Pattern)); string currentAddress = textPattern.DocumentRange.GetText(-1); if (currentAddress.Equals(address, StringComparison.CurrentCultureIgnoreCase)) { foundAddress = true; break; } else { System.Threading.Thread.Sleep(Interval); } } TestServices.Assert( foundAddress, "The address was not found: {0}", address); }
public void ValidateGetContentTypes() { Type registryHelpers = ReflectionHelper.GetType( "DRT.WebServer+RegistryHelpers", this.GetType().Assembly); string contentType = (string)ReflectionHelper.InvokeMethod( registryHelpers, "GetContentType", new object[] { "something.txt" }); TestServices.Assert( string.Equals("text/plain", contentType, StringComparison.OrdinalIgnoreCase), "Well known content type did not match."); contentType = (string)ReflectionHelper.InvokeMethod( registryHelpers, "GetContentType", new object[] { "something.unknown" }); TestServices.Assert( string.Equals("application/octet-stream", contentType, StringComparison.OrdinalIgnoreCase), "Well unknown content type was not default."); }
/// <summary> /// Focus a control, send it a keygesture, and check the proper result via GetText. /// </summary> /// <param name="target">The AutomationElement to focus on, or null to keep current focus.</param> /// <param name="keyGesture">The key gesture to send the target.</param> /// <param name="textElement">The AutomationElement to check the text of (via TextPattern).</param> /// <param name="desiredValue">The expected string.</param> public static void CheckKeyResult( AutomationElement target, KeyGesture keyGesture, AutomationElement textElement, string desiredValue ) { if (target != null) { target.SetFocus(); AutomationHelper.WaitForFocus(target); } InputKeyGesture(keyGesture); string actualValue = AutomationHelper.GetText(textElement); TestServices.Assert(actualValue.Equals(desiredValue), "Key gesture ({0}) failed. DesiredResult: {1} ActualResult: {2}", keyGesture.DisplayString, desiredValue, actualValue); }
public void ValidateSecurityZoneMethods() { SecurityZone orginal = WebServer.SecurityZone; foreach (string current in Enum.GetNames(typeof(SecurityZone))) { SecurityZone zone = (SecurityZone)Enum.Parse( typeof(SecurityZone), current); WebServer.SecurityZone = zone; TestServices.Assert( WebServer.SecurityZone == zone, "Get after set for SecurityZone does not match: was {0}, expected {1}.", WebServer.SecurityZone, zone); } WebServer.RestoreSecurityZone(); TestServices.Assert( WebServer.SecurityZone == orginal, "Restored zone {0} does not match orginal {1}.", WebServer.SecurityZone, orginal); SecurityZone forcedRestore = SecurityZone.MyComputer; WebServer.RestoreSecurityZone(forcedRestore); TestServices.Assert( WebServer.SecurityZone == forcedRestore, "Restore value {0} was not set.", forcedRestore); WebServer.RestoreSecurityZone(orginal); }
//---------------------------------------------------------------------- // Constructors //---------------------------------------------------------------------- /// <summary> /// Will connect TestServices to DrtBase set Drt properties by /// inspect the derived classes TestGroupAttribute. /// </summary> protected DrtBaseAdapter() { Type subclass = this.GetType(); base.DrtName = subclass.Name; base.WindowTitle = subclass.Name; TestServices.Current.MessageSent += this.MessageSentHandler; TestGroupAttribute testGroup = TestServices.GetFirstAttribute( typeof(TestGroupAttribute), subclass) as TestGroupAttribute; if (testGroup != null) { base.Contact = testGroup.Contact; base.TeamContact = testGroup.Team; } else { TestServices.Assert( true, "TestGroup attribute missing from derived class."); } }