WIP phase 39: school owners, my/others menu, guest restrictions.

This commit is contained in:
Leonid Pershin
2026-08-20 07:58:12 +03:00
parent 40929aa3ce
commit 26be7c87f8
27 changed files with 919 additions and 81 deletions
+91 -6
View File
@@ -19,7 +19,8 @@ public class SchoolApiTests(AppHostFixture fixture)
var state = await GetSchoolsAsync(client);
Assert.Equal(6, state.MaxSchools);
Assert.Equal(2, state.MaxSchools);
Assert.Equal(7, state.MaxSchoolsTotal);
Assert.Equal(ExpectedDefaultStart, state.DefaultStartDate);
// Without the "Z" the browser would read the start date in its own time zone and the
@@ -493,7 +494,7 @@ public class SchoolApiTests(AppHostFixture fixture)
Assert.NotNull(status);
Assert.Equal(20, status.TickRate);
Assert.Equal(6, status.MaxSchools);
Assert.Equal(2, status.MaxSchools);
Assert.True(status.Tick > 0, "The loop should have ticked by now.");
}
@@ -526,6 +527,21 @@ public class SchoolApiTests(AppHostFixture fixture)
_ = await LoginAndGetCookieAsync(client, userName);
}
internal static async Task<HttpClient> CreateIsolatedClientAsync(DistributedApplication app, string userName)
{
var login = app.CreateHttpClient("server");
var cookie = await LoginAndGetCookieAsync(login, userName);
login.Dispose();
var handler = new HttpClientHandler { UseCookies = false };
var client = new HttpClient(handler)
{
BaseAddress = new Uri(app.GetEndpoint("server", "http").ToString()),
};
client.DefaultRequestHeaders.Add("Cookie", cookie);
return client;
}
internal static async Task<string> LoginAndGetCookieAsync(HttpClient client, string userName = TestUserName)
{
using var first = await client.PostAsJsonAsync(
@@ -585,6 +601,62 @@ public class SchoolApiTests(AppHostFixture fixture)
using var response = await client.DeleteAsync($"/api/schools/{school.Id}", TestContext.Current.CancellationToken);
response.EnsureSuccessStatusCode();
}
foreach (var school in state.Others)
{
using var response = await client.DeleteAsync($"/api/schools/{school.Id}", TestContext.Current.CancellationToken);
if (response.StatusCode == HttpStatusCode.Forbidden)
{
continue;
}
response.EnsureSuccessStatusCode();
}
}
internal static async Task WipeAllSavesAsync(HttpClient client)
{
await LoginAsync(client);
for (var pass = 0; pass < 4; pass++)
{
var state = await GetSchoolsAsync(client);
if (state.Schools.Count == 0 && state.Others.Count == 0)
{
break;
}
foreach (var school in state.Schools)
{
using var response = await client.DeleteAsync($"/api/schools/{school.Id}", TestContext.Current.CancellationToken);
response.EnsureSuccessStatusCode();
}
foreach (var other in state.Others)
{
using var response = await client.DeleteAsync($"/api/schools/{other.Id}", TestContext.Current.CancellationToken);
if (response.StatusCode == HttpStatusCode.Forbidden)
{
continue;
}
response.EnsureSuccessStatusCode();
}
}
var directory = await SavesDirectoryAsync(client);
foreach (var path in Directory.EnumerateFiles(directory))
{
File.Delete(path);
}
foreach (var path in Directory.EnumerateDirectories(directory))
{
Directory.Delete(path, recursive: true);
}
using var reload = await client.PostAsync("/api/dev/reload-schools", content: null, TestContext.Current.CancellationToken);
reload.EnsureSuccessStatusCode();
}
internal static async Task<SchoolsResponse> GetSchoolsAsync(HttpClient client)
@@ -649,7 +721,7 @@ public class SchoolApiTests(AppHostFixture fixture)
return save;
}
private static async Task<string> SavesDirectoryAsync(HttpClient client)
internal static async Task<string> SavesDirectoryAsync(HttpClient client)
{
var payload = await client.GetFromJsonAsync<PathResponse>(
"/api/dev/saves-directory",
@@ -659,7 +731,7 @@ public class SchoolApiTests(AppHostFixture fixture)
return payload.Path;
}
private sealed record SchoolSaveFile(string? CountryId, string? ClimatePresetId, string? NativeLanguage);
private sealed record SchoolSaveFile(string? CountryId, string? ClimatePresetId, string? NativeLanguage, string? Owner);
internal static readonly object SimpleCustomMap = new
{
@@ -673,7 +745,7 @@ public class SchoolApiTests(AppHostFixture fixture)
links = new[] { new { a = "yard", b = "office" } },
};
private static Task<HttpResponseMessage> PostAsync(
internal static Task<HttpResponseMessage> PostAsync(
HttpClient client,
string name,
DateTime startDate,
@@ -696,14 +768,27 @@ public class SchoolApiTests(AppHostFixture fixture)
bool Running,
byte SpeedIndex,
int Seed,
bool Mine,
IReadOnlyList<string>? ModIds = null);
internal sealed record OtherSchoolResponse(
int Id,
string Name,
DateTime GameTime,
bool Running,
byte SpeedIndex,
int Seed,
string? Owner,
IReadOnlyList<string>? ModIds = null);
internal sealed record SchoolsResponse(
int MaxSchools,
int MaxSchoolsTotal,
DateTime DefaultStartDate,
double GameMinutesPerRealSecond,
int SchoolWeekDays,
IReadOnlyList<SchoolResponse> Schools);
IReadOnlyList<SchoolResponse> Schools,
IReadOnlyList<OtherSchoolResponse> Others);
private sealed record RandomNameResponse(string Name);