Radicade Public Code

This commit is contained in:
JogmansonReal
2026-10-16 23:33:13 -07:00
commit 55175acdf6
832 changed files with 363261 additions and 0 deletions
+126
View File
@@ -0,0 +1,126 @@
using System.Text.Json;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using RadicadeServer.Admin;
using RadicadeServer.DB;
using RadicadeServer.RecNet.Auth;
using RadicadeServer.RecNet.Auth.Cached;
using RadicadeServer.RecNet.Enums.Players;
using Xunit;
namespace RadicadeServer.Tests;
/// <summary>
/// The players list sends joined_at and last_online_at so the panel can render them in the
/// admin's own time zone. SQL Server hands a datetime2 back with Kind=Unspecified, and
/// System.Text.Json writes such a value with no trailing "Z"; a browser parses a zone-less ISO
/// string as already-local time, so an offline player's "Last Online" sat one admin time-zone
/// offset away from the truth - it looked hours into the future. Only the online branch carried
/// the marker, because there the value is DateTime.UtcNow. These tests pin the instants down
/// exactly: the fix is the marker, never a shift of the clock itself.
/// </summary>
public class AdminPanelPlayerTimesTests
{
private const string Secret = "test-bot-secret";
private const long Player = 2;
/// <summary>Unspecified is what SQL Server gives back for a datetime2, so that is what the fixtures store.</summary>
private static readonly DateTime SignedUp = new(2026, 7, 29, 0, 56, 0, DateTimeKind.Unspecified);
private static readonly DateTime LastLogin = new(2026, 9, 30, 21, 38, 0, DateTimeKind.Unspecified);
private static RecDBContext NewDb() => new(
TestDbOptions.Create()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options);
/// <summary>A database holding one player, with or without the cached login row that records their last sign-in.</summary>
private static async Task<RecDBContext> WithPlayer(bool withLogin)
{
var db = NewDb();
db.Profiles.Add(new Profile
{
accountId = Player,
username = "coach",
displayName = "Coach",
profileImage = "",
createdAt = SignedUp
});
if (withLogin)
{
db.CachedLogins.Add(new CachedLogin
{
accountId = Player,
platform = Platforms.Steam,
platformId = "76561198000000000",
lastLoginTime = LastLogin
});
}
await db.SaveChangesAsync();
return db;
}
/// <summary>The two timestamps exactly as the panel's JSON.parse receives them.</summary>
private static async Task<(string Joined, string LastOnline)> PlayerTimes(RecDBContext db)
{
var context = new DefaultHttpContext();
context.Request.QueryString = new QueryString("?key=" + Secret);
var api = new AdminPanelAPI(db)
{
ControllerContext = new ControllerContext { HttpContext = context }
};
var original = DBConfig.AdminApiKey;
DBConfig.AdminApiKey = Secret;
try
{
var ok = Assert.IsType<OkObjectResult>(await api.List("players", Secret, null, null, null, true));
// Same writer the panel is served by, so this is the wire text the browser sees
// rather than a stand-in for it.
using var document = JsonDocument.Parse(JsonSerializer.Serialize(ok.Value));
var row = document.RootElement[0];
return (row.GetProperty("joined_at").GetString()!, row.GetProperty("last_online_at").GetString()!);
}
finally
{
DBConfig.AdminApiKey = original;
}
}
[Fact]
public async Task AnOfflinePlayersLastOnlineIsMarkedAsUtc()
{
var db = await WithPlayer(withLogin: true);
var (_, lastOnline) = await PlayerTimes(db);
// 21:38 UTC is the moment they signed out, and the panel turns that into whatever o'clock
// the admin's own zone reads it as. Without the "Z" the browser read it as 21:38 local.
Assert.Equal("2026-09-30T21:38:00Z", lastOnline);
}
[Fact]
public async Task TheAccountAgeIsMarkedAsUtcToo()
{
var db = await WithPlayer(withLogin: true);
var (joined, _) = await PlayerTimes(db);
Assert.Equal("2026-07-29T00:56:00Z", joined);
}
[Fact]
public async Task APlayerWhoNeverLoggedInFallsBackToTheirAccountAge()
{
var db = await WithPlayer(withLogin: false);
var (joined, lastOnline) = await PlayerTimes(db);
// No cached login row means the profile's own createdAt is the newest thing known about them.
Assert.Equal("2026-07-29T00:56:00Z", joined);
Assert.Equal("2026-07-29T00:56:00Z", lastOnline);
}
}