using System.Net.Http.Json; namespace HSchool.AppHost.Tests; /// /// The shipped mods/example folder: catalog, create, reload and a map that uses its room. /// Temp packs in other tests stay disposable; this one has to survive a restart. /// [Collection(AppHostCollection.Name)] public class ExamplePackTests(AppHostFixture fixture) { private static readonly DateTime ExpectedDefaultStart = new(2012, 3, 31, 6, 0, 0, DateTimeKind.Utc); [Fact] public async Task Catalog_WithExample_AddsPackTypesAndLabelsOnTopOfCore() { using var client = fixture.App.CreateHttpClient("server"); var ru = await client.GetFromJsonAsync( "/api/catalog?lang=ru&mods=example", TestContext.Current.CancellationToken); var en = await client.GetFromJsonAsync( "/api/catalog?lang=en&mods=example", TestContext.Current.CancellationToken); Assert.NotNull(ru); Assert.NotNull(en); Assert.Equal("Кабинет директора", Assert.Single(ru.Rooms, room => room.DefName == "PrincipalsOffice").Label); Assert.Equal("Кладовая", Assert.Single(ru.Rooms, room => room.DefName == "ExampleStore").Label); Assert.Equal("Storeroom", Assert.Single(en.Rooms, room => room.DefName == "ExampleStore").Label); Assert.Equal("Примерные имена", Assert.Single(ru.Countries, set => set.DefName == "ExampleNames").Label); Assert.Equal("Example names", Assert.Single(en.Countries, set => set.DefName == "ExampleNames").Label); Assert.Equal("yard", ru.DefaultMap.Territory?.Id); } [Fact] public async Task Catalog_PackPatch_IsVisibleOnlyWhenThePackIsSelected() { using var client = fixture.App.CreateHttpClient("server"); var vanilla = await client.GetFromJsonAsync("/api/catalog?lang=ru", TestContext.Current.CancellationToken); var withPack = await client.GetFromJsonAsync( "/api/catalog?lang=ru&mods=example", TestContext.Current.CancellationToken); Assert.NotNull(vanilla); Assert.NotNull(withPack); Assert.DoesNotContain( Assert.Single(vanilla.Rooms, room => room.DefName == "PrincipalsOffice").Slots, slot => slot.Key == "exampleLocker"); Assert.Contains( Assert.Single(withPack.Rooms, room => room.DefName == "PrincipalsOffice").Slots, slot => slot.Key == "exampleLocker"); Assert.DoesNotContain(vanilla.Rooms, room => room.DefName == "ExampleStore"); } [Fact] public async Task CreateSchool_WithExample_SurvivesReload() { using var client = fixture.App.CreateHttpClient("server"); await SchoolApiTests.ResetAsync(client); var created = await CreateWithModsAsync(client, "С примером", ["example"]); Assert.Equal(["core", "example"], created.ModIds); using var reload = await client.PostAsync("/api/dev/reload-schools", content: null, TestContext.Current.CancellationToken); reload.EnsureSuccessStatusCode(); var restored = (await SchoolApiTests.GetSchoolsAsync(client)).Schools.Single(school => school.Id == created.Id); Assert.Equal(created.Name, restored.Name); Assert.Equal(["core", "example"], restored.ModIds); Assert.True(restored.Running); } [Fact] public async Task CreateSchool_WithThePackRoomOnTheMap_Succeeds() { using var client = fixture.App.CreateHttpClient("server"); await SchoolApiTests.ResetAsync(client); using var response = await client.PostAsJsonAsync( "/api/schools", new { name = "Кладовая во дворе", startDate = ExpectedDefaultStart, modIds = new[] { "example" }, map = PackRoomMap, }, TestContext.Current.CancellationToken); response.EnsureSuccessStatusCode(); var created = await response.Content.ReadFromJsonAsync(TestContext.Current.CancellationToken); Assert.NotNull(created); Assert.Equal(["core", "example"], created.ModIds); } [Fact] public async Task CreateSchool_WithoutThePack_StaysVanilla() { using var client = fixture.App.CreateHttpClient("server"); await SchoolApiTests.ResetAsync(client); var created = await SchoolApiTests.CreateAsync(client, "Без примера", ExpectedDefaultStart); Assert.Equal(["core"], created.ModIds); } private static async Task CreateWithModsAsync( HttpClient client, string name, string[] modIds) { using var response = await client.PostAsJsonAsync( "/api/schools", new { name, startDate = ExpectedDefaultStart, modIds }, TestContext.Current.CancellationToken); response.EnsureSuccessStatusCode(); var created = await response.Content.ReadFromJsonAsync(TestContext.Current.CancellationToken); Assert.NotNull(created); return created; } private static readonly object PackRoomMap = new { territory = new { id = "yard", def = "SchoolYard" }, buildings = new[] { new { id = "main", def = "MainBuilding" } }, floors = new[] { new { id = "floor-1", def = "StandardFloor", building = "main", label = "1" } }, rooms = new[] { new { id = "store", def = "ExampleStore", building = "main", floor = "floor-1", slots = Array.Empty() }, }, links = new[] { new { a = "yard", b = "store" } }, }; private sealed record CatalogResponse( IReadOnlyList Territories, IReadOnlyList Buildings, IReadOnlyList Floors, IReadOnlyList Rooms, IReadOnlyList Things, IReadOnlyList Countries, DayFrameResponse? DayFrame, IReadOnlyList Holidays, MapLayoutResponse DefaultMap); private sealed record DefInfoResponse(string DefName, string Label); private sealed record CountryInfoResponse(string DefName, string Label); private sealed record RoomInfoResponse( string DefName, string Label, IReadOnlyList Slots); private sealed record RoomSlotResponse(string Key, string Thing); private sealed record DayFrameResponse(string DefName, string Label); private sealed record HolidayInfoResponse(string DefName, string Label); private sealed record MapLayoutResponse(TerritoryResponse? Territory); private sealed record TerritoryResponse(string Id, string Def); }