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);
}
}