Merge branch 'review/slice-7-a-recheck'
This commit is contained in:
@@ -5,49 +5,31 @@ using System.Text.Json.Nodes;
|
||||
namespace HSchool.AppHost.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Phase 25 goldens. The folders stay historic (format 2, no country): that shape must not start.
|
||||
/// Load tests stamp today's format, country and owner onto a copy so missing-field defaults and
|
||||
/// seed-equals-id still have a host assertion after later slices raised <c>CanStart</c>.
|
||||
/// Phase 25 goldens stay historic (format 2, <c>nameSetId: Slavic</c>). Phase 29 lifts that to
|
||||
/// Russia in memory; the file is not rewritten until the school saves itself. Slice 6 recheck
|
||||
/// treated format 2 as unstartable — that gate contradicted the lift, so these tests load.
|
||||
/// </summary>
|
||||
[Collection(AppHostCollection.Name)]
|
||||
public class GoldenSaveTests(AppHostFixture fixture)
|
||||
{
|
||||
[Fact]
|
||||
public async Task HistoricFormat2Golden_LeavesTheSchoolUnstartedAndTheFileUntouched()
|
||||
public async Task CurrentFormatSave_LoadsTheSamePeopleAndTime()
|
||||
{
|
||||
using var client = fixture.App.CreateHttpClient("server");
|
||||
await SchoolApiTests.ResetAsync(client);
|
||||
var directory = await SchoolApiTests.SavesDirectoryAsync(client);
|
||||
await InstallAsync(client, "current");
|
||||
|
||||
try
|
||||
{
|
||||
InstallFolder(directory, "current");
|
||||
var path = Path.Combine(directory, "1.json");
|
||||
var before = File.ReadAllBytes(path);
|
||||
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);
|
||||
|
||||
using var reload = await client.PostAsync("/api/dev/reload-schools", content: null, TestContext.Current.CancellationToken);
|
||||
reload.EnsureSuccessStatusCode();
|
||||
|
||||
var state = await SchoolApiTests.GetSchoolsAsync(client);
|
||||
Assert.Empty(state.Schools);
|
||||
var broken = Assert.Single(state.Others);
|
||||
Assert.Equal(1, broken.Id);
|
||||
Assert.Equal("Золотая", broken.Name);
|
||||
Assert.Equal(1, broken.Seed);
|
||||
|
||||
using var people = await client.GetAsync(
|
||||
$"/api/schools/{broken.Id}/people?pageSize=1",
|
||||
TestContext.Current.CancellationToken);
|
||||
Assert.Equal(HttpStatusCode.NotFound, people.StatusCode);
|
||||
|
||||
Assert.Equal(before, File.ReadAllBytes(path));
|
||||
}
|
||||
finally
|
||||
{
|
||||
DeleteSchoolFiles(directory, 1);
|
||||
using var cleanup = await client.PostAsync("/api/dev/reload-schools", content: null, TestContext.Current.CancellationToken);
|
||||
cleanup.EnsureSuccessStatusCode();
|
||||
}
|
||||
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]
|
||||
@@ -55,84 +37,46 @@ public class GoldenSaveTests(AppHostFixture fixture)
|
||||
{
|
||||
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());
|
||||
|
||||
var directory = await SchoolApiTests.SavesDirectoryAsync(client);
|
||||
|
||||
try
|
||||
{
|
||||
await InstallRunnableAsync(client, directory, "legacy-no-native", includeNative: false);
|
||||
|
||||
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());
|
||||
Assert.Contains(people, person => person.Roles.Contains("student"));
|
||||
Assert.Equal(new DateTime(2012, 3, 31, 6, 0, 0, DateTimeKind.Utc), school.GameTime);
|
||||
}
|
||||
finally
|
||||
{
|
||||
DeleteSchoolFiles(directory, 1);
|
||||
using var cleanup = await client.PostAsync("/api/dev/reload-schools", content: null, TestContext.Current.CancellationToken);
|
||||
cleanup.EnsureSuccessStatusCode();
|
||||
}
|
||||
Assert.Contains("\"items\"", File.ReadAllText(Path.Combine(directory, "1.people.json")), StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private static async Task InstallRunnableAsync(
|
||||
HttpClient client,
|
||||
string directory,
|
||||
string folder,
|
||||
bool includeNative)
|
||||
{
|
||||
InstallFolder(directory, folder);
|
||||
StampRunnable(Path.Combine(directory, "1.json"), includeNative);
|
||||
|
||||
using var reload = await client.PostAsync("/api/dev/reload-schools", content: null, TestContext.Current.CancellationToken);
|
||||
reload.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
private static void InstallFolder(string directory, string folder)
|
||||
private async Task InstallAsync(HttpClient client, string folder)
|
||||
{
|
||||
var directory = await SchoolApiTests.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);
|
||||
}
|
||||
|
||||
var session = await client.GetFromJsonAsync<SessionResponse>("/api/session", TestContext.Current.CancellationToken);
|
||||
Assert.NotNull(session);
|
||||
StampOwner(Path.Combine(directory, "1.json"), session.UserName);
|
||||
|
||||
using var reload = await client.PostAsync("/api/dev/reload-schools", content: null, TestContext.Current.CancellationToken);
|
||||
reload.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
private static void StampRunnable(string path, bool includeNative)
|
||||
private static void StampOwner(string path, string userName)
|
||||
{
|
||||
var node = JsonNode.Parse(File.ReadAllText(path))
|
||||
?? throw new InvalidOperationException($"Save {path} parsed to nothing.");
|
||||
node["format"] = 3;
|
||||
node["countryId"] = "Russia";
|
||||
node["climatePresetId"] = "TemperateContinental";
|
||||
node["owner"] = SchoolApiTests.TestUserName;
|
||||
node.AsObject().Remove("nameSetId");
|
||||
if (includeNative)
|
||||
{
|
||||
node["nativeLanguage"] = "RussianLanguage";
|
||||
}
|
||||
else
|
||||
{
|
||||
node.AsObject().Remove("nativeLanguage");
|
||||
}
|
||||
|
||||
File.WriteAllText(path, node.ToJsonString(new JsonSerializerOptions { WriteIndented = true }));
|
||||
}
|
||||
|
||||
private static void DeleteSchoolFiles(string directory, int id)
|
||||
{
|
||||
foreach (var name in new[] { $"{id}.json", $"{id}.people.json", $"{id}.timetable.json" })
|
||||
{
|
||||
var path = Path.Combine(directory, name);
|
||||
if (File.Exists(path))
|
||||
{
|
||||
File.Delete(path);
|
||||
}
|
||||
}
|
||||
node["owner"] = userName;
|
||||
File.WriteAllText(
|
||||
path,
|
||||
node.ToJsonString(new JsonSerializerOptions { WriteIndented = true }));
|
||||
}
|
||||
|
||||
private static async Task<IReadOnlyList<PersonRow>> PeopleAsync(HttpClient client, int schoolId)
|
||||
@@ -164,6 +108,8 @@ public class GoldenSaveTests(AppHostFixture fixture)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private sealed record SessionResponse(string UserName);
|
||||
|
||||
private sealed record PeoplePage(IReadOnlyList<PersonRow> People);
|
||||
|
||||
private sealed record PersonRow(string Id, string FullName, IReadOnlyList<string> Roles);
|
||||
|
||||
@@ -130,9 +130,9 @@ public class DressGeneratorTests
|
||||
roster.Families,
|
||||
roster.Classes);
|
||||
|
||||
Assert.True(DressGenerator.NeedsDressing(stripped, ApplicantPool.Empty));
|
||||
Assert.True(DressGenerator.NeedsDressing(catalog, stripped, ApplicantPool.Empty));
|
||||
var dressed = DressGenerator.EnsureRoster(catalog, stripped, Fixtures.SchoolSeed, Fixtures.AsOf);
|
||||
Assert.False(DressGenerator.NeedsDressing(dressed, ApplicantPool.Empty));
|
||||
Assert.False(DressGenerator.NeedsDressing(catalog, dressed, ApplicantPool.Empty));
|
||||
Assert.Equal(ItemsSnapshot(roster), ItemsSnapshot(dressed));
|
||||
}
|
||||
|
||||
@@ -180,6 +180,34 @@ public class DressGeneratorTests
|
||||
Assert.All(roster.People, person => Assert.True(person.Skills.ContainsKey("Hauling")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AbstractUnderwearInASave_IsRedressedOnEnsure()
|
||||
{
|
||||
var catalog = Fixtures.Catalog();
|
||||
var roster = Fixtures.Generate(Fixtures.Classrooms(4));
|
||||
var broken = new Roster(
|
||||
roster.People.Select(person =>
|
||||
{
|
||||
var items = person.Items.Select(item =>
|
||||
item.Def.Equals("Briefs", StringComparison.Ordinal)
|
||||
|| item.Def.Equals("Boxers", StringComparison.Ordinal)
|
||||
|| item.Def.Equals("Panties", StringComparison.Ordinal)
|
||||
? item with { Def = "Underwear" }
|
||||
: item).ToArray();
|
||||
return person with { Items = items };
|
||||
}).ToArray(),
|
||||
roster.Families,
|
||||
roster.Classes);
|
||||
|
||||
Assert.True(DressGenerator.NeedsDressing(catalog, broken, ApplicantPool.Empty));
|
||||
var dressed = DressGenerator.EnsureRoster(catalog, broken, Fixtures.SchoolSeed, Fixtures.AsOf);
|
||||
Assert.False(DressGenerator.NeedsDressing(catalog, dressed, ApplicantPool.Empty));
|
||||
Assert.Equal(ItemsSnapshot(roster), ItemsSnapshot(dressed));
|
||||
Assert.DoesNotContain(
|
||||
dressed.People.SelectMany(person => person.Items),
|
||||
item => item.Def.Equals("Underwear", StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
private static string ItemsSnapshot(Roster roster) =>
|
||||
string.Join(
|
||||
'\n',
|
||||
|
||||
Reference in New Issue
Block a user