using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Threading;
using IFSRenderer.AvaloniaShell.Tests.Fakes;
using Xunit;
namespace IFSRenderer.AvaloniaShell.Tests;
/// <summary>Brings up the real window against a GPU-less queue.</summary>
public static class MainWindowHarness
{
/// <summary>
/// Shows <see cref="MainWindow"/> with a <see cref="FakeRenderQueue"/> and waits for
/// startup to settle.
/// </summary>
/// <remarks>
/// Settings are redirected to a scratch directory: the suite must never read or write the
/// developer's real <c>~/.config/ifsrenderer</c>, and the Welcome window has to stay shut
/// or startup would block on a dialog.
/// </remarks>
public static (MainWindow Window, FakeRenderQueue Queue) Start()
{
string config = Path.Combine(Path.GetTempPath(),
"ifsrenderer-tests-" + Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(Path.Combine(config, "ifsrenderer"));
File.WriteAllText(Path.Combine(config, "ifsrenderer", "settings.json"),
"{\"ShowWelcomeOnStartup\":false}");
Environment.SetEnvironmentVariable("XDG_CONFIG_HOME", config);
var queue = new FakeRenderQueue();
var window = new MainWindow(queue);
window.Show();
// Startup is an async void handler: pump until it has produced a fractal.
Pump(() => queue.Current is not null);
Settle(queue);
Assert.NotNull(queue.Current);
return (window, queue);
}
/// <summary>Runs dispatcher jobs until <paramref name="until"/> holds, or fails.</summary>
public static void Pump(Func<bool> until, int timeoutMs = 20000)
{
var clock = Stopwatch.StartNew();
while (clock.ElapsedMilliseconds < timeoutMs)
{
Dispatcher.UIThread.RunJobs();
if (until())
return;
Thread.Sleep(10);
}
Assert.Fail($"timed out after {timeoutMs} ms waiting for the window to settle");
}
/// <summary>Performs the gesture's engine work, then the UI refresh it posted back.</summary>
public static void Settle(FakeRenderQueue queue)
{
queue.Drain();
Dispatcher.UIThread.RunJobs();
}
public static void Click(Control root, string name)
{
var button = root.FindControl<Button>(name);
Assert.NotNull(button);
button.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
}
}