using LANCommander.Server.UI.Tests.Pages; using Microsoft.Playwright; using Xunit.Abstractions; namespace LANCommander.Server.UI.Tests.Tests; /// /// Tests for the first-time setup wizard when the server has no existing configuration. /// Runs in its own collection to avoid conflicts with ConfiguredServerFixture over /// the static DatabaseContext.Provider. /// [Collection("FirstTimeSetup")] public class FirstTimeSetupTests : IAsyncLifetime { private readonly FreshServerFixture _fixture; private readonly ITestOutputHelper _output; private IBrowserContext _context = null!; private IPage _page = null!; public FirstTimeSetupTests(FreshServerFixture fixture, ITestOutputHelper output) { _fixture = fixture; _output = output; } public async Task InitializeAsync() { (_context, _page) = await _fixture.CreatePageAsync(); } public async Task DisposeAsync() { await ScreenshotHelper.CaptureAsync(_page, _output); if (_page != null) await _page.CloseAsync(); if (_context != null) await _context.DisposeAsync(); } [Fact] public async Task FreshServer_RedirectsToFirstTimeSetup() { await _page.GotoAsync("/"); // A fresh server should show the First Time Setup page await _page.WaitForSelectorAsync("text=First Time Setup", new() { Timeout = 10000 }); var setupPage = new FirstTimeSetupPage(_page); Assert.True(await setupPage.IsDisplayedAsync()); } [Fact] public async Task FirstTimeSetup_ShowsFourSteps() { var setupPage = new FirstTimeSetupPage(_page); await setupPage.NavigateAsync(); // Verify all 4 steps are visible in the wizard await Assertions.Expect(_page.GetByText("Database").First).ToBeVisibleAsync(); await Assertions.Expect(_page.GetByText("Paths")).ToBeVisibleAsync(); // "Metadata" may be truncated in UI to "Metad" but the text node still exists await Assertions.Expect(_page.Locator("text=/Metad/").First).ToBeVisibleAsync(); await Assertions.Expect(_page.GetByText("Administrator")).ToBeVisibleAsync(); } [Fact] public async Task FirstTimeSetup_DatabaseStep_ShowsProviderOptions() { var setupPage = new FirstTimeSetupPage(_page); await setupPage.NavigateAsync(); // Open the database provider dropdown await _page.GetByRole(AriaRole.Combobox).ClickAsync(); // Wait for the dropdown listbox to appear await _page.WaitForSelectorAsync("[role='listbox']", new() { Timeout = 5000 }); // Verify all expected providers are shown await Assertions.Expect(_page.GetByRole(AriaRole.Option, new() { Name = "SQLite" })).ToBeVisibleAsync(); await Assertions.Expect(_page.GetByRole(AriaRole.Option, new() { Name = "MySQL" })).ToBeVisibleAsync(); await Assertions.Expect(_page.GetByRole(AriaRole.Option, new() { Name = "PostgreSQL" })).ToBeVisibleAsync(); } [Fact(Skip = "Requires real database and file I/O - not supported with in-memory WebApplicationFactory")] public async Task FirstTimeSetup_CompleteWizardAndLogin() { var setupPage = new FirstTimeSetupPage(_page); await setupPage.NavigateAsync(); await setupPage.CompleteFullSetupAsync( adminUsername: TestConstants.AdminUserName, adminPassword: TestConstants.AdminPassword); // After setup, we should be on the login page Assert.Contains("/Login", _page.Url); var loginPage = new LoginPage(_page); Assert.True(await loginPage.IsDisplayedAsync()); // Now log in with the admin credentials that were just created await loginPage.LoginAsync(TestConstants.AdminUserName, TestConstants.AdminPassword); // Wait for the Blazor app to render the dashboard await _page.WaitForSelectorAsync("text=Dashboard", new() { Timeout = 15000 }); var dashboard = new AdminDashboardPage(_page); Assert.True(await dashboard.IsDisplayedAsync()); } }