Exemple #1
0
        public static void AreEqual(Bitmap expected, UiElement element)
        {
            WaitForStartAnimation(element);
            if (Equal(expected, element, RetryTime))
            {
                return;
            }

            using (var actualBmp = Capture.Rectangle(element.Bounds))
            {
                AreEqual(expected, actualBmp);
            }
        }
        private static void Details(StringBuilder stringBuilder, UiElement uiElement, string displayPadding)
        {
            const string indent = "    ";

            WriteDetail(uiElement, stringBuilder, displayPadding);
            WritePattern(uiElement, stringBuilder, displayPadding);
            var children = uiElement.CachedChildren;

            foreach (var child in children)
            {
                Details(stringBuilder, child, displayPadding + indent);
            }
        }
Exemple #3
0
        public static void RealizeItems(UiElement itemContainerElement)
        {
            if (itemContainerElement is null)
            {
                throw new System.ArgumentNullException(nameof(itemContainerElement));
            }

            // We save the scroll value to restore it afterwards
            if (itemContainerElement.AutomationElement.TryGetScrollPattern(out var scrollPattern))
            {
                var currHScroll = scrollPattern.Current.HorizontalScrollPercent;
                var currVScroll = scrollPattern.Current.VerticalScrollPercent;

                // First we try with the item container pattern and realize each item
                if (itemContainerElement.AutomationElement.TryGetItemContainerPattern(out var itemContainerPattern))
                {
                    // There's the item container pattern so we can go thru all elements and just realize them
                    AutomationElement?currElement = null;
                    while (true)
                    {
                        currElement = itemContainerPattern.FindItemByProperty(currElement, null, null);
                        if (currElement is null)
                        {
                            break;
                        }

                        if (currElement.TryGetVirtualizedItemPattern(out var virtualizedItemPattern))
                        {
                            virtualizedItemPattern.Realize();
                        }
                    }
                }
                else
                {
                    // Second we use the scroll pattern to scroll from top to bottom
                    scrollPattern.SetScrollPercent(0, 0);
                    do
                    {
                        scrollPattern.Scroll(ScrollAmount.NoAmount, ScrollAmount.SmallIncrement);
                    }while (scrollPattern.Current.VerticalScrollPercent < 100);
                }

                ResetScroll(scrollPattern, currHScroll, currVScroll);
                return;
            }

            // Third we try by using the scrollbar controls itself
            {
                // TODO
            }
        }
Exemple #4
0
        public static bool UntilResponsive(UiElement uiElement, TimeSpan timeout)
        {
            if (uiElement is null)
            {
                throw new ArgumentNullException(nameof(uiElement));
            }

            if (uiElement.TryGetWindow(out var window))
            {
                return(UntilResponsive(window.NativeWindowHandle, timeout));
            }

            return(false);
        }
        /// <summary>
        /// Compare Capture.Rectangle(element.Bounds) to the expected image.
        /// </summary>
        /// <param name="fileName">Can be a full file name relative filename or the name of a resource.</param>
        /// <param name="element">The automation element.</param>
        /// <param name="onFail">Useful for saving the actual image on error for example.</param>
        public static void AreEqual(string fileName, UiElement element, OnImageAssertFail onFail)
        {
            if (fileName is null)
            {
                throw new ArgumentNullException(nameof(fileName));
            }

            if (element is null)
            {
                throw new ArgumentNullException(nameof(element));
            }

            if (onFail is null)
            {
                throw new ArgumentNullException(nameof(onFail));
            }

            if (TryGetStream(fileName, Assembly.GetCallingAssembly(), out var stream))
            {
                using (stream)
                {
                    using var expected = (Bitmap)Image.FromStream(stream);
                    if (Equal(expected, element, RetryTime))
                    {
                        return;
                    }

                    using var actual = Capture.Rectangle(element.Bounds);
                    if (Debugger.IsAttached)
                    {
                        ImageDiffWindow.Show(expected, actual);
                    }

                    onFail(expected, actual, fileName);
                    throw ImageMatchException(expected, actual, fileName);
                }
            }
            else
            {
                using var actual = Capture.Rectangle(element.Bounds);
                if (Debugger.IsAttached)
                {
                    ImageDiffWindow.Show(null, actual);
                }

                onFail(null, actual, fileName);
                throw MissingResourceException(actual, fileName);
            }
        }
        /// <summary>
        /// Captures an element and saves it to a file.
        /// Note that a sleep may be required before if the control is newly loaded.
        /// </summary>
        public static void ElementToFile(UiElement element, string filePath)
        {
            if (element is null)
            {
                throw new ArgumentNullException(nameof(element));
            }

            if (filePath is null)
            {
                throw new ArgumentNullException(nameof(filePath));
            }

            using var bmp = Rectangle(element.Bounds);
            bmp.Save(filePath, ImageFormat.Png);
        }
Exemple #7
0
        public static bool Equal(Bitmap expected, UiElement element, TimeSpan retryTime)
        {
            var start = DateTime.Now;

            while (!Retry.IsTimeouted(start, retryTime))
            {
                using (var actual = Capture.Rectangle(element.Bounds))
                {
                    if (Equal(expected, actual))
                    {
                        return(true);
                    }
                }

                Wait.For(Retry.PollInterval);
            }

            return(false);
        }
        private static void WaitForStartAnimation(UiElement element)
        {
            if (StartAnimation <= TimeSpan.Zero)
            {
                return;
            }

            var window = element.Window;

            User32.GetWindowThreadProcessId(window.NativeWindowHandle, out var id);
            using (var process = Process.GetProcessById((int)id))
            {
                var upTime = DateTime.Now - process.StartTime;
                if (upTime < StartAnimation)
                {
                    Wait.For(StartAnimation - upTime);
                }
            }
        }
Exemple #9
0
        /// <summary>
        /// Compare Capture.Rectangle(element.Bounds) to the expected image.
        /// </summary>
        /// <param name="fileName">Can be a full file name relative filename or the name of a resource.</param>
        /// <param name="element">The automation element.</param>
        public static void AreEqual(string fileName, UiElement element)
        {
            WaitForStartAnimation(element);
            if (TryGetStream(fileName, Assembly.GetCallingAssembly(), out var stream))
            {
                using (stream)
                {
                    using (var expected = (Bitmap)Image.FromStream(stream))
                    {
                        if (Equal(expected, element, RetryTime))
                        {
                            return;
                        }

                        using (var actual = Capture.Rectangle(element.Bounds))
                        {
                            switch (OnFail)
                            {
                            case OnFail.DoNothing:
                                AreEqual(expected, actual);
                                break;

                            case OnFail.SaveImageToTemp:
                                AreEqual(
                                    expected,
                                    actual,
                                    (bitmap) => bitmap.Save(TempFileName(fileName), GetImageFormat(fileName)));
                                break;

                            default:
                                throw new InvalidOperationException($"Not handling OnFail {OnFail}");
                            }
                        }
                    }
                }
            }
            else
            {
                Capture.ElementToFile(element, TempFileName(fileName));
                throw AssertException.Create($"Did not find a file nor resource named {fileName}");
            }
        }
Exemple #10
0
        /// <summary>
        /// Compare Capture.Rectangle(element.Bounds) to the expected image.
        /// </summary>
        /// <param name="fileName">Can be a full file name relative filename or the name of a resource.</param>
        /// <param name="element">The automation element.</param>
        /// <param name="onFail">Useful for saving the actual image on error for example.</param>
        public static void AreEqual(string fileName, UiElement element, Action <Exception, Bitmap> onFail)
        {
            WaitForStartAnimation(element);
            if (TryGetStream(fileName, Assembly.GetCallingAssembly(), out var stream))
            {
                using (stream)
                {
                    using (var expected = (Bitmap)Image.FromStream(stream))
                    {
                        if (Equal(expected, element, RetryTime))
                        {
                            return;
                        }

                        using (var actual = Capture.Rectangle(element.Bounds))
                        {
                            try
                            {
                                AreEqual(expected, actual);
                            }
                            catch (Exception e)
                            {
                                onFail(e, actual);
                                throw;
                            }
                        }
                    }
                }
            }
            else
            {
                var exception = AssertException.Create($"Did not find a file nor resource named {fileName}");
                using (var actual = Capture.Rectangle(element.Bounds))
                {
                    onFail(exception, actual);
                }

                throw exception;
            }
        }
        public static string Details(UiElement uiElement)
        {
            try
            {
                var stringBuilder = new StringBuilder();
                var cr            = new CacheRequest {
                    AutomationElementMode = AutomationElementMode.None
                };

                // Add the element properties
                cr.Add(AutomationElementIdentifiers.AutomationIdProperty);
                cr.Add(AutomationElementIdentifiers.ControlTypeProperty);
                cr.Add(AutomationElementIdentifiers.NameProperty);
                cr.Add(AutomationElementIdentifiers.HelpTextProperty);
                cr.Add(AutomationElementIdentifiers.BoundingRectangleProperty);
                cr.Add(AutomationElementIdentifiers.ClassNameProperty);
                cr.Add(AutomationElementIdentifiers.IsOffscreenProperty);
                cr.Add(AutomationElementIdentifiers.FrameworkIdProperty);
                cr.Add(AutomationElementIdentifiers.ProcessIdProperty);

                // Add the pattern availability properties
                cr.Add(AutomationElementIdentifiers.IsDockPatternAvailableProperty);
                cr.Add(AutomationElementIdentifiers.IsExpandCollapsePatternAvailableProperty);
                cr.Add(AutomationElementIdentifiers.IsGridPatternAvailableProperty);
                cr.Add(AutomationElementIdentifiers.IsGridItemPatternAvailableProperty);
                cr.Add(AutomationElementIdentifiers.IsInvokePatternAvailableProperty);
                cr.Add(AutomationElementIdentifiers.IsItemContainerPatternAvailableProperty);
                cr.Add(AutomationElementIdentifiers.IsMultipleViewPatternAvailableProperty);
                cr.Add(AutomationElementIdentifiers.IsRangeValuePatternAvailableProperty);
                cr.Add(AutomationElementIdentifiers.IsScrollItemPatternAvailableProperty);
                cr.Add(AutomationElementIdentifiers.IsScrollPatternAvailableProperty);
                cr.Add(AutomationElementIdentifiers.IsSelectionItemPatternAvailableProperty);
                cr.Add(AutomationElementIdentifiers.IsSynchronizedInputPatternAvailableProperty);
                cr.Add(AutomationElementIdentifiers.IsTablePatternAvailableProperty);
                cr.Add(AutomationElementIdentifiers.IsTableItemPatternAvailableProperty);
                cr.Add(AutomationElementIdentifiers.IsTextPatternAvailableProperty);
                cr.Add(AutomationElementIdentifiers.IsTogglePatternAvailableProperty);
                cr.Add(AutomationElementIdentifiers.IsTransformPatternAvailableProperty);
                cr.Add(AutomationElementIdentifiers.IsValuePatternAvailableProperty);
                cr.Add(AutomationElementIdentifiers.IsVirtualizedItemPatternAvailableProperty);
                cr.Add(AutomationElementIdentifiers.IsWindowPatternAvailableProperty);

                cr.TreeScope  = TreeScope.Subtree;
                cr.TreeFilter = Condition.TrueCondition;

                // Activate the cache request
                using (cr.Activate())
                {
                    // Re-find the root element with caching activated
                    uiElement = uiElement.FindFirst(TreeScope.Element, Condition.TrueCondition);
                    Details(stringBuilder, uiElement, string.Empty);
                }

                return(stringBuilder.ToString());
            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed to dump info: " + ex);
                return(string.Empty);
            }
        }
 /// <summary>
 /// Gets the XPath to the element until the desktop or the given root element.
 /// Warning: This is quite a heavy operation.
 /// </summary>
 public static string GetXPathToElement(UiElement element, UiElement rootElement = null)
 {
     return(GetXPathToElement(element.AutomationElement, TreeWalker.ControlViewWalker, rootElement));
 }
Exemple #13
0
 public static GridViewCell Create(UiElement content)
 {
     return(new GridViewCell(content));
 }
 public AutomationElementXPathNavigator(UiElement rootElement)
 {
     this.treeWalker     = TreeWalker.ControlViewWalker;
     this.rootElement    = rootElement;
     this.currentElement = rootElement.AutomationElement;
 }
        private static string GetXPathToElement(AutomationElement element, TreeWalker treeWalker, UiElement rootElement = null)
        {
            var parent = treeWalker.GetParent(element);

            if (parent == null ||
                (rootElement != null &&
                 Equals(parent, rootElement.AutomationElement)))
            {
                return(string.Empty);
            }

            // Get the index
            var allChildren     = parent.FindAllChildren(Conditions.ByControlType(element.Current.ControlType));
            var currentItemText = $"{element.Current.ControlType}";

            if (allChildren.Count > 1)
            {
                // There is more than one matching child, find out the index
                var indexInParent = 1; // Index starts with 1
                foreach (var child in allChildren)
                {
                    if (child.Equals(element))
                    {
                        break;
                    }

                    indexInParent++;
                }

                currentItemText += $"[{indexInParent}]";
            }

            return($"{GetXPathToElement(parent, treeWalker, rootElement)}/{currentItemText}");
        }
Exemple #16
0
 /// <summary>
 /// Captures an element and returns the image.
 /// Note that a sleep may be required before if the control is newly loaded.
 /// </summary>
 public static Bitmap Element(UiElement element)
 {
     return(Rectangle(element.Bounds));
 }
 /// <summary>
 /// Dump the visual tree of <paramref name="element"/>.
 /// </summary>
 /// <param name="element">The <see cref="UiElement"/>.</param>
 /// <param name="allPropertiesAndPatterns">If all automation properties and patterns should be written to the result.</param>
 /// <returns>A string representing the automation tree of <paramref name="element"/>.</returns>
 public static string Recursive(UiElement element, bool allPropertiesAndPatterns = false)
 {
     return(Recursive(element.AutomationElement, allPropertiesAndPatterns));
 }
Exemple #18
0
        /// <summary>
        /// Finds the first element which is in the given treescope with the given condition within the given timeout period.
        /// </summary>
        public bool TryFindAt(TreeScope treeScope, System.Windows.Automation.Condition condition, int index, TimeSpan timeOut, out UiElement result)
        {
            result = null;
            var start = DateTime.Now;

            while (!Retry.IsTimeouted(start, timeOut))
            {
                result = this.AutomationElement.FindIndexed(treeScope, condition, index, FromAutomationElement);
                if (result != null)
                {
                    return(true);
                }

                Wait.For(Retry.PollInterval);
            }

            return(result != null);
        }
Exemple #19
0
 public static bool UntilResponsive(UiElement uiElement)
 {
     return(UntilResponsive(uiElement, DefaultTimeout));
 }
Exemple #20
0
 public GridViewCell(UiElement content)
     : base(content?.AutomationElement ?? throw new ArgumentNullException(nameof(content)))
 {
     this.Content = content;
 }
 public AutomationElementXPathNavigator(UiElement rootElement)
 {
     this.treeWalker     = TreeWalker.ControlViewWalker;
     this.rootElement    = rootElement ?? throw new ArgumentNullException(nameof(rootElement));
     this.currentElement = rootElement.AutomationElement;
 }