|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Threading.Tasks;
using Roslyn.Utilities;
using UIAutomationClient;
using AutomationElementIdentifiers = System.Windows.Automation.AutomationElementIdentifiers;
namespace Microsoft.VisualStudio.IntegrationTest.Utilities
{
public class AutomationElementHelper
{
/// <summary>
/// Finds the automation element by <paramref name="elementName"/> and clicks on it asynchronously.
/// <paramref name="elementName"/> should be set to true if performing a recursive search.
/// </summary>
public static async Task ClickAutomationElementAsync(string elementName, bool recursive = false)
{
var element = await FindAutomationElementAsync(elementName, recursive).ConfigureAwait(false);
if (element != null)
{
var tcs = new TaskCompletionSource<VoidResult>();
Helper.Automation.AddAutomationEventHandler(
UIA_EventIds.UIA_Invoke_InvokedEventId,
element,
TreeScope.TreeScope_Element,
cacheRequest: null,
new AutomationEventHandler((src, e) => tcs.SetResult(default)));
element.Invoke();
await tcs.Task;
}
}
/// <summary>
/// Finds the automation element by <paramref name="elementName"/>.
/// <paramref name="elementName"/> should be set to true if performing a recursive search.
/// </summary>
/// <returns>The task referrign to the element finding.</returns>
public static async Task<IUIAutomationElement> FindAutomationElementAsync(string elementName, bool recursive = false)
{
IUIAutomationElement? element = null;
var scope = recursive ? TreeScope.TreeScope_Descendants : TreeScope.TreeScope_Children;
var condition = Helper.Automation.CreatePropertyCondition(AutomationElementIdentifiers.NameProperty.Id, elementName);
// TODO(Dustin): This is code is a bit terrifying. If anything goes wrong and the automation
// element can't be found, it'll continue to spin until the heat death of the universe.
await IntegrationHelper.WaitForResultAsync(
() => (element = Helper.Automation.GetRootElement().FindFirst(scope, condition)) != null, expectedResult: true
).ConfigureAwait(false);
Contract.ThrowIfNull(element);
return element;
}
private class AutomationEventHandler : IUIAutomationEventHandler
{
private readonly Action<IUIAutomationElement, int> _action;
public AutomationEventHandler(Action<IUIAutomationElement, int> action)
{
_action = action ?? throw new ArgumentNullException(nameof(action));
}
public void HandleAutomationEvent(IUIAutomationElement sender, int eventId)
=> _action(sender, eventId);
}
}
}
|