using System.Net.Http.Json; using System.Text.Json; namespace HSchool.AppHost.Tests; [Collection(AppHostCollection.Name)] public class GoldenSaveTests(AppHostFixture fixture) { [Fact] public async Task CurrentFormatSave_LoadsTheSamePeopleAndTime() { using var client = fixture.App.CreateHttpClient("server"); await SchoolApiTests.ResetAsync(client); await InstallAsync(client, "current"); var state = await SchoolApiTests.GetSchoolsAsync(client); var school = Assert.Single(state.Schools); Assert.Equal(1, school.Id); Assert.Equal(1, school.Seed); Assert.Equal("Золотая", school.Name); Assert.Equal(new DateTime(2012, 3, 31, 6, 0, 0, DateTimeKind.Utc), school.GameTime); Assert.False(school.Running); var people = await PeopleAsync(client, school.Id); Assert.Equal(ExpectedNames(), people.Select(row => row.FullName).OrderBy(name => name, StringComparer.Ordinal).ToArray()); Assert.Contains(people, person => person.Roles.Contains("student")); } [Fact] public async Task SaveWithoutNativeLanguage_LoadsWithoutReshuffling() { using var client = fixture.App.CreateHttpClient("server"); await SchoolApiTests.ResetAsync(client); await InstallAsync(client, "legacy-no-native"); var state = await SchoolApiTests.GetSchoolsAsync(client); var school = Assert.Single(state.Schools); Assert.Equal(1, school.Id); Assert.Equal(1, school.Seed); Assert.Equal("Золотая", school.Name); var people = await PeopleAsync(client, school.Id); Assert.Equal(ExpectedNames(), people.Select(row => row.FullName).OrderBy(name => name, StringComparer.Ordinal).ToArray()); } private async Task InstallAsync(HttpClient client, string folder) { var directory = await SavesDirectoryAsync(client); var source = Path.Combine(AppContext.BaseDirectory, "golden", folder); foreach (var file in Directory.EnumerateFiles(source)) { File.Copy(file, Path.Combine(directory, Path.GetFileName(file)), overwrite: true); } using var reload = await client.PostAsync("/api/dev/reload-schools", content: null, TestContext.Current.CancellationToken); reload.EnsureSuccessStatusCode(); } private static async Task SavesDirectoryAsync(HttpClient client) { var payload = await client.GetFromJsonAsync( "/api/dev/saves-directory", TestContext.Current.CancellationToken); Assert.NotNull(payload); Assert.False(string.IsNullOrWhiteSpace(payload.Path)); return payload.Path; } private static async Task> PeopleAsync(HttpClient client, int schoolId) { var page = await client.GetFromJsonAsync( $"/api/schools/{schoolId}/people?pageSize=100", TestContext.Current.CancellationToken); Assert.NotNull(page); return page.People .OrderBy(row => row.Id, StringComparer.Ordinal) .ToArray(); } private static string[] ExpectedNames() { var json = File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "golden", "current", "1.people.json")); using var document = JsonDocument.Parse(json); return document.RootElement.GetProperty("people") .EnumerateArray() .Select(person => { var name = person.GetProperty("name"); var surname = name.GetProperty("surname").GetString() ?? ""; var given = name.GetProperty("given").GetString() ?? ""; var patronymic = name.GetProperty("patronymic").GetString() ?? ""; return string.Join(' ', new[] { surname, given, patronymic }.Where(part => part.Length > 0)); }) .OrderBy(full => full, StringComparer.Ordinal) .ToArray(); } private sealed record SavesDirectoryResponse(string Path); private sealed record PeoplePage(IReadOnlyList People); private sealed record PersonRow(string Id, string FullName, IReadOnlyList Roles); }