// 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;
///
/// Class managing the lifecycle of the tested application implementing .
/// Uses for UI automation.
///
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;
///
/// Gets the wrapper for an application which should be automated.
///
public Application? Application => app;
///
/// Gets the main window of the applications process.
///
public Window? MainWindow => mainWindow ??= app?.GetMainWindow(automation);
///
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;
}
///
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;
}
}