92 lines
2.8 KiB
C#
92 lines
2.8 KiB
C#
using System.Diagnostics;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
|
|
namespace Enciphered.Blazor.UIComponents.Tests;
|
|
|
|
/// <summary>
|
|
/// Launches the demo Blazor app as a separate process on a random free port.
|
|
/// Shared across all tests in the assembly via [SetUpFixture].
|
|
/// </summary>
|
|
public sealed class DemoServerFixture : IDisposable
|
|
{
|
|
private Process? _process;
|
|
|
|
public string BaseUrl { get; private set; } = string.Empty;
|
|
|
|
public async Task StartAsync()
|
|
{
|
|
var port = GetFreePort();
|
|
BaseUrl = $"http://localhost:{port}";
|
|
|
|
// Resolve the demo project directory (navigate up from test bin output)
|
|
var testDir = AppContext.BaseDirectory; // …Tests/bin/Debug/net9.0
|
|
var solutionRoot = Path.GetFullPath(Path.Combine(testDir, "..", "..", "..", ".."));
|
|
var demoProjectDir = Path.Combine(solutionRoot, "Enciphered.Blazor.UIComponents.Demo");
|
|
|
|
if (!Directory.Exists(demoProjectDir))
|
|
throw new DirectoryNotFoundException($"Demo project not found at: {demoProjectDir}");
|
|
|
|
_process = new Process
|
|
{
|
|
StartInfo = new ProcessStartInfo
|
|
{
|
|
FileName = "dotnet",
|
|
Arguments = $"run --no-build --urls {BaseUrl}",
|
|
WorkingDirectory = demoProjectDir,
|
|
UseShellExecute = false,
|
|
RedirectStandardOutput = true,
|
|
RedirectStandardError = true,
|
|
CreateNoWindow = true,
|
|
Environment =
|
|
{
|
|
["ASPNETCORE_ENVIRONMENT"] = "Development",
|
|
["DOTNET_NOLOGO"] = "1"
|
|
}
|
|
}
|
|
};
|
|
|
|
_process.Start();
|
|
|
|
// Wait for the server to be ready by polling the URL
|
|
using var httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(2) };
|
|
var deadline = DateTime.UtcNow.AddSeconds(30);
|
|
|
|
while (DateTime.UtcNow < deadline)
|
|
{
|
|
try
|
|
{
|
|
var response = await httpClient.GetAsync(BaseUrl);
|
|
if (response.IsSuccessStatusCode)
|
|
return;
|
|
}
|
|
catch
|
|
{
|
|
// Server not ready yet
|
|
}
|
|
await Task.Delay(500);
|
|
}
|
|
|
|
throw new TimeoutException($"Demo server did not start within 30 seconds at {BaseUrl}");
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (_process is not null && !_process.HasExited)
|
|
{
|
|
_process.Kill(entireProcessTree: true);
|
|
_process.WaitForExit(5000);
|
|
_process.Dispose();
|
|
}
|
|
}
|
|
|
|
private static int GetFreePort()
|
|
{
|
|
using var listener = new TcpListener(IPAddress.Loopback, 0);
|
|
listener.Start();
|
|
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
|
|
listener.Stop();
|
|
return port;
|
|
}
|
|
}
|