Ship a disk example pack so last-wins, patches and create-with-a-mod are tested for real.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
using System.Net.Http.Json;
|
||||
|
||||
namespace HSchool.AppHost.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// The shipped <c>mods/example</c> 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.
|
||||
/// </summary>
|
||||
[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<CatalogResponse>(
|
||||
"/api/catalog?lang=ru&mods=example",
|
||||
TestContext.Current.CancellationToken);
|
||||
var en = await client.GetFromJsonAsync<CatalogResponse>(
|
||||
"/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.NameSets, set => set.DefName == "ExampleNames").Label);
|
||||
Assert.Equal("Example names", Assert.Single(en.NameSets, 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<CatalogResponse>("/api/catalog?lang=ru", TestContext.Current.CancellationToken);
|
||||
var withPack = await client.GetFromJsonAsync<CatalogResponse>(
|
||||
"/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<SchoolApiTests.SchoolResponse>(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<SchoolApiTests.SchoolResponse> 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<SchoolApiTests.SchoolResponse>(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<object>() },
|
||||
},
|
||||
links = new[] { new { a = "yard", b = "store" } },
|
||||
};
|
||||
|
||||
private sealed record CatalogResponse(
|
||||
IReadOnlyList<DefInfoResponse> Territories,
|
||||
IReadOnlyList<DefInfoResponse> Buildings,
|
||||
IReadOnlyList<DefInfoResponse> Floors,
|
||||
IReadOnlyList<RoomInfoResponse> Rooms,
|
||||
IReadOnlyList<DefInfoResponse> Things,
|
||||
IReadOnlyList<NameSetInfoResponse> NameSets,
|
||||
DayFrameResponse? DayFrame,
|
||||
IReadOnlyList<HolidayInfoResponse> Holidays,
|
||||
MapLayoutResponse DefaultMap);
|
||||
|
||||
private sealed record DefInfoResponse(string DefName, string Label);
|
||||
|
||||
private sealed record NameSetInfoResponse(string DefName, string Label);
|
||||
|
||||
private sealed record RoomInfoResponse(
|
||||
string DefName,
|
||||
string Label,
|
||||
IReadOnlyList<RoomSlotResponse> 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);
|
||||
}
|
||||
Reference in New Issue
Block a user