using LANCommander.SDK.Enums; using LANCommander.Server.Data; using LANCommander.Server.Data.Models; using LANCommander.Server.Services; using LANCommander.Server.Settings.Enums; using LANCommander.Server.UI.Tests.Pages; using Microsoft.Extensions.DependencyInjection; using Microsoft.Playwright; namespace LANCommander.Server.UI.Tests; /// /// Shared fixture that starts the server via WebApplicationFactory, programmatically creates /// the admin user, and makes it available for all tests in the collection. /// Shared across the "Server" collection via ICollectionFixture<ConfiguredServerFixture>. /// public class ConfiguredServerFixture : IAsyncLifetime { public PlaywrightFixture Playwright { get; private set; } = null!; public UITestApplicationFactory Factory { get; private set; } = null!; /// /// ID of a game created via the service layer for edit tests. /// public Guid TestGameId { get; private set; } public const string TestGameTitle = "Test Game"; public async Task InitializeAsync() { Playwright = new PlaywrightFixture(); await Playwright.InitializeAsync(); Factory = new UITestApplicationFactory(); // Trigger the factory to start the Kestrel server _ = Factory.Services; // Create the admin user via the service layer (before setting Provider // so OnConfiguring doesn't try to add a conflicting SQLite provider) using var scope = Factory.RealServices.CreateScope(); var roleService = scope.ServiceProvider.GetRequiredService(); var userService = scope.ServiceProvider.GetRequiredService(); await roleService.AddAsync(new Role { Name = RoleService.AdministratorRoleName }); var user = await userService.AddAsync(new User { UserName = TestConstants.AdminUserName }); await userService.ChangePassword(user.UserName, TestConstants.AdminPassword); await userService.AddToRoleAsync(user.UserName, RoleService.AdministratorRoleName); // Seed default storage locations so the import dialog can initialize var storageLocationService = scope.ServiceProvider.GetRequiredService(); var archivePath = Path.Combine(Path.GetTempPath(), "LANCommander_UITest_Archives"); Directory.CreateDirectory(archivePath); await storageLocationService.AddAsync(new StorageLocation { Path = archivePath, Type = StorageLocationType.Archive, Default = true }); var savePath = Path.Combine(Path.GetTempPath(), "LANCommander_UITest_Saves"); Directory.CreateDirectory(savePath); await storageLocationService.AddAsync(new StorageLocation { Path = savePath, Type = StorageLocationType.Save, Default = true }); var mediaPath = Path.Combine(Path.GetTempPath(), "LANCommander_UITest_Media"); Directory.CreateDirectory(mediaPath); await storageLocationService.AddAsync(new StorageLocation { Path = mediaPath, Type = StorageLocationType.Media, Default = true }); // Seed a test game via the service layer for edit tests var gameService = scope.ServiceProvider.GetRequiredService(); var game = await gameService.AddAsync(new Game { Title = TestGameTitle, Type = GameType.MainGame, Singleplayer = true }); TestGameId = game.Id; // Now set the database provider so the server doesn't redirect to /FirstTimeSetup DatabaseContext.Provider = DatabaseProvider.SQLite; } public async Task DisposeAsync() { // Reset the static provider so other tests can use a fresh state DatabaseContext.Provider = DatabaseProvider.Unknown; await Factory.DisposeAsync(); await Playwright.DisposeAsync(); } /// /// Creates a new browser context and page, already logged in as admin. /// public async Task<(IBrowserContext Context, IPage Page)> CreateLoggedInPageAsync() { var context = await Playwright.NewContextAsync(Factory.BaseAddress); var page = await context.NewPageAsync(); var loginPage = new LoginPage(page); await loginPage.NavigateAsync(); await loginPage.LoginAsync(TestConstants.AdminUserName, TestConstants.AdminPassword); await page.WaitForSelectorAsync("text=Dashboard", new() { Timeout = 15000 }); return (context, page); } /// /// Creates a new browser context and page (not logged in). /// public async Task<(IBrowserContext Context, IPage Page)> CreateAnonymousPageAsync() { var context = await Playwright.NewContextAsync(Factory.BaseAddress); var page = await context.NewPageAsync(); return (context, page); } }