using System.Net; using System.Net.Http.Json; using System.Text.Json; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using SVSim.Database; using SVSim.Database.Enums; using SVSim.EmulatedEntrypoint.Models.Dtos.Requests.Admin; using SVSim.EmulatedEntrypoint.Models.Dtos.Responses.Admin; using SVSim.UnitTests.Infrastructure; namespace SVSim.UnitTests.Controllers; /// /// End-to-end coverage for /admin/import_viewer. The endpoint is [AllowAnonymous] so /// these tests don't need to seed a viewer first; the fresh-user path exercises the just-fixed /// nav-graph NRE inside ViewerRepository.RegisterViewer, and the existing-user path /// exercises the owned-type lookup used to dedupe by Steam id. /// public class AdminControllerTests { private static readonly JsonSerializerOptions JsonOptions = new() { PropertyNameCaseInsensitive = true }; [Test] public async Task ImportViewer_fresh_user_creates_viewer_and_returns_ids() { using var factory = new SVSimTestFactory(); using var client = factory.CreateClient(); var response = await client.PostAsJsonAsync("/admin/import_viewer", new ImportViewerRequest { SteamId = 76_561_198_222_333_444UL, DisplayName = "Fresh User", CountryCode = "USA", TutorialState = 100, Currency = new ImportCurrency { Crystals = 12345 } }); Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK), await response.Content.ReadAsStringAsync()); var body = await response.Content.ReadFromJsonAsync(JsonOptions); Assert.That(body, Is.Not.Null); Assert.That(body!.ViewerId, Is.GreaterThan(0), "RegisterViewer must persist and return a non-zero id."); Assert.That(body.WasCreated, Is.True); using var scope = factory.Services.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); var stored = await db.Viewers .Include(v => v.SocialAccountConnections) .Include(v => v.Currency) .Include(v => v.Info) .FirstAsync(v => v.Id == body.ViewerId); Assert.That(stored.DisplayName, Is.EqualTo("Fresh User")); Assert.That(stored.Currency.Crystals, Is.EqualTo(12345UL), "ImportViewer should overwrite the seed-config crystal default with the requested value."); Assert.That(stored.Info.CountryCode, Is.EqualTo("USA")); Assert.That(stored.SocialAccountConnections.Count, Is.EqualTo(1)); Assert.That(stored.SocialAccountConnections[0].AccountId, Is.EqualTo(76_561_198_222_333_444UL)); Assert.That(stored.SocialAccountConnections[0].AccountType, Is.EqualTo(SocialAccountType.Steam)); } [Test] public async Task ImportViewer_existing_user_updates_in_place() { using var factory = new SVSimTestFactory(); const ulong steamId = 76_561_198_555_666_777UL; long seededId = await factory.SeedViewerAsync(steamId: steamId, displayName: "Original Name"); using var client = factory.CreateClient(); var response = await client.PostAsJsonAsync("/admin/import_viewer", new ImportViewerRequest { SteamId = steamId, DisplayName = "Updated Name", CountryCode = "JPN" }); Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK), await response.Content.ReadAsStringAsync()); var body = await response.Content.ReadFromJsonAsync(JsonOptions); Assert.That(body, Is.Not.Null); Assert.That(body!.ViewerId, Is.EqualTo(seededId), "Re-importing the same SteamId must reuse the existing viewer row, not create a new one."); Assert.That(body.WasCreated, Is.False); using var scope = factory.Services.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); var stored = await db.Viewers .Include(v => v.Info) .FirstAsync(v => v.Id == seededId); Assert.That(stored.DisplayName, Is.EqualTo("Updated Name")); Assert.That(stored.Info.CountryCode, Is.EqualTo("JPN")); var viewerCount = await db.Viewers.CountAsync(v => v.SocialAccountConnections.Any(s => s.AccountType == SocialAccountType.Steam && s.AccountId == steamId)); Assert.That(viewerCount, Is.EqualTo(1), "Owned-type dedup must not produce a second row."); } [Test] public async Task ImportViewer_missing_steam_id_returns_400() { using var factory = new SVSimTestFactory(); using var client = factory.CreateClient(); var response = await client.PostAsJsonAsync("/admin/import_viewer", new ImportViewerRequest { SteamId = 0, DisplayName = "No Steam" }); Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest)); } }