更新客户端渲染,更新了壳
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
|
||||
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
|
||||
// All Rights Reserved.
|
||||
|
||||
using FlaUI.Core;
|
||||
using FlaUI.Core.Tools;
|
||||
using FlaUI.UIA3;
|
||||
|
||||
namespace Wpf.Ui.Gallery.IntegrationTests.Fixtures;
|
||||
|
||||
/// <summary>
|
||||
/// Class managing the lifecycle of the tested application implementing <see cref="IAsyncLifetime"/>.
|
||||
/// Uses <see cref="UIA3Automation"/> for UI automation.
|
||||
/// </summary>
|
||||
public sealed class TestedApplication : IAsyncLifetime
|
||||
{
|
||||
private const string ExecutableName = "Wpf.Ui.Gallery.exe";
|
||||
|
||||
private readonly AutomationBase automation = new UIA3Automation();
|
||||
|
||||
private Application? app;
|
||||
|
||||
private Window? mainWindow;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the wrapper for an application which should be automated.
|
||||
/// </summary>
|
||||
public Application? Application => app;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the main window of the applications process.
|
||||
/// </summary>
|
||||
public Window? MainWindow => mainWindow ??= app?.GetMainWindow(automation);
|
||||
|
||||
/// <inheritdoc />
|
||||
public ValueTask InitializeAsync()
|
||||
{
|
||||
if (app is not null)
|
||||
{
|
||||
app.Close();
|
||||
app.Dispose();
|
||||
}
|
||||
|
||||
string path = Path.Combine(
|
||||
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!,
|
||||
ExecutableName
|
||||
);
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Unable to find the application executable at path \"{path}\"."
|
||||
);
|
||||
}
|
||||
|
||||
app = Application.Launch(path);
|
||||
app.WaitWhileMainHandleIsMissing(TimeSpan.FromMinutes(1));
|
||||
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
if (app is not null)
|
||||
{
|
||||
if (!app.HasExited)
|
||||
{
|
||||
app.Close();
|
||||
}
|
||||
|
||||
// ReSharper disable once AccessToDisposedClosure
|
||||
Retry.WhileFalse(() => app?.HasExited ?? true, TimeSpan.FromSeconds(2), ignoreException: true);
|
||||
|
||||
app.Dispose();
|
||||
|
||||
app = null;
|
||||
}
|
||||
|
||||
automation?.Dispose();
|
||||
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
|
||||
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
|
||||
// All Rights Reserved.
|
||||
|
||||
using System.Threading;
|
||||
using FlaUI.Core;
|
||||
using FlaUI.Core.Conditions;
|
||||
using FlaUI.Core.Input;
|
||||
using FlaUI.Core.WindowsAPI;
|
||||
|
||||
namespace Wpf.Ui.Gallery.IntegrationTests.Fixtures;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for UI tests implementing <see cref="Xunit.IAsyncLifetime"/> to manage <see cref="FlaUI.Core.Application"/> lifecycle.
|
||||
/// </summary>
|
||||
public abstract class UiTest : IAsyncLifetime
|
||||
{
|
||||
private readonly TestedApplication app = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the wrapper for an application which should be automated.
|
||||
/// </summary>
|
||||
internal Application? Application => app.Application;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the main window of the applications process.
|
||||
/// </summary>
|
||||
internal Window? MainWindow => app.MainWindow;
|
||||
|
||||
/// <inheritdoc />
|
||||
public ValueTask InitializeAsync() => app.InitializeAsync();
|
||||
|
||||
/// <inheritdoc />
|
||||
public ValueTask DisposeAsync() => app.DisposeAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Finds the first descendant with the given automation id.
|
||||
/// </summary>
|
||||
/// <param name="automationId">The automation id.</param>
|
||||
/// <returns>The found element or null if no element was found.</returns>
|
||||
protected AutomationElement? FindFirst(string automationId) =>
|
||||
app.MainWindow?.FindFirstDescendant(automationId);
|
||||
|
||||
/// <summary>Finds the first descendant with the condition.</summary>
|
||||
/// <param name="conditionFunc">The condition method.</param>
|
||||
/// <returns>The found element or null if no element was found.</returns>
|
||||
protected AutomationElement? FindFirst(Func<ConditionFactory, ConditionBase> conditionFunc) =>
|
||||
app.MainWindow?.FindFirstDescendant(conditionFunc);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Task that will complete after a time delay.
|
||||
/// </summary>
|
||||
/// <param name="seconds">The time delay in seconds.</param>
|
||||
/// <param name="cancellationToken">An optional cancellation token to cancel the delay.</param>
|
||||
/// <returns>A Task that represents the time delay.</returns>
|
||||
/// <remarks>
|
||||
/// After the specified time delay, the Task is completed in RanToCompletion state. If the <paramref name="cancellationToken"/>
|
||||
/// is cancelled, the returned task will be cancelled and an <see cref="OperationCanceledException"/> will be thrown.
|
||||
/// </remarks>
|
||||
protected Task Wait(int seconds, CancellationToken cancellationToken = default) =>
|
||||
Task.Delay(TimeSpan.FromSeconds(seconds), cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Simulate typing in text. This is slower than setting <see cref="P:FlaUI.Core.AutomationElements.TextBox.Text" /> but raises more events.
|
||||
/// </summary>
|
||||
protected void Enter(string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string[] source = value.Replace("\r\n", "\n").Split('\n');
|
||||
|
||||
Keyboard.Type(source[0]);
|
||||
|
||||
foreach (string text in ((IEnumerable<string>)source).Skip<string>(1))
|
||||
{
|
||||
Keyboard.Type(VirtualKeyShort.RETURN);
|
||||
Keyboard.Type(text);
|
||||
}
|
||||
|
||||
global::FlaUI.Core.Input.Wait.UntilInputIsProcessed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Type the given key.
|
||||
/// </summary>
|
||||
protected void Press(VirtualKeyShort virtualKey)
|
||||
{
|
||||
Keyboard.Type(virtualKey);
|
||||
|
||||
global::FlaUI.Core.Input.Wait.UntilInputIsProcessed();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user