mirror of
https://github.com/JogmansonReal/Radicade.git
synced 2026-10-25 23:18:56 -07:00
111 lines
3.4 KiB
C#
111 lines
3.4 KiB
C#
using System.Text.Json;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using RadicadeServer.Admin;
|
|
using RadicadeServer.DB;
|
|
using RadicadeServer.RecNet.Auth;
|
|
using RadicadeServer.RecNet.Moderation;
|
|
using Xunit;
|
|
|
|
namespace RadicadeServer.Tests;
|
|
|
|
/// <summary>
|
|
/// PATCH admin/panel/players/{id} with the values the panel echoes back from its own GET.
|
|
///
|
|
/// Noteriety and ReputationScore are doubles on Reputation (NoterietyPerCheer is 0.5), so an account
|
|
/// that has been cheered carries a fractional value. The endpoint used to read them with GetInt32,
|
|
/// which throws System.FormatException on a fractional JSON number - the whole edit answered 500 and
|
|
/// saved nothing. Because only accounts with a fractional score hit it, it looked account-specific.
|
|
/// </summary>
|
|
public class AdminPanelFractionalReputationTests
|
|
{
|
|
private const string Secret = "test-bot-secret";
|
|
private const long Player = 3;
|
|
|
|
private static RecDBContext NewDb() => new(
|
|
TestDbOptions.Create()
|
|
.UseInMemoryDatabase(Guid.NewGuid().ToString())
|
|
.Options);
|
|
|
|
private static async Task<RecDBContext> WithPlayer()
|
|
{
|
|
var db = NewDb();
|
|
db.Profiles.Add(new Profile
|
|
{
|
|
accountId = Player,
|
|
username = "fractional",
|
|
displayName = "Fractional Player",
|
|
profileImage = ""
|
|
});
|
|
db.Reputations.Add(new Reputation
|
|
{
|
|
AccountId = Player,
|
|
Noteriety = 0.5,
|
|
ReputationScore = 7.5
|
|
});
|
|
await db.SaveChangesAsync();
|
|
return db;
|
|
}
|
|
|
|
private static async Task<IActionResult> Patch(RecDBContext db, string json)
|
|
{
|
|
var payload = JsonDocument.Parse(json).RootElement.Clone();
|
|
var api = new AdminPanelAPI(db);
|
|
var original = DBConfig.AdminApiKey;
|
|
DBConfig.AdminApiKey = Secret;
|
|
try
|
|
{
|
|
return await api.Update("players", Player, Secret, payload);
|
|
}
|
|
finally
|
|
{
|
|
DBConfig.AdminApiKey = original;
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public async Task AFractionalNoterietyIsAcceptedAndStoredAsADouble()
|
|
{
|
|
using var db = await WithPlayer();
|
|
|
|
// Exactly what the panel sends for an account whose score is not a whole number.
|
|
var result = await Patch(db, """
|
|
{
|
|
"display_name": "Fractional Player",
|
|
"reputation": 9.5,
|
|
"noteriety": 1.5,
|
|
"cheer_general": 3
|
|
}
|
|
""");
|
|
|
|
Assert.IsType<OkObjectResult>(result);
|
|
|
|
var rep = await db.Reputations.SingleAsync(x => x.AccountId == Player);
|
|
Assert.Equal(1.5, rep.Noteriety);
|
|
Assert.Equal(9.5, rep.ReputationScore);
|
|
Assert.Equal(3, rep.CheerGeneral);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task AnOutOfRangeOrNumericStringIntegerDoesNotThrow()
|
|
{
|
|
using var db = await WithPlayer();
|
|
|
|
// A value Int32 cannot hold, and an integer sent as a string, must both land (clamped /
|
|
// parsed) rather than 500 the edit.
|
|
var result = await Patch(db, """
|
|
{
|
|
"noteriety": 0.5,
|
|
"cheer_helpful": "4",
|
|
"cheer_creative": 9999999999999999999
|
|
}
|
|
""");
|
|
|
|
Assert.IsType<OkObjectResult>(result);
|
|
|
|
var rep = await db.Reputations.SingleAsync(x => x.AccountId == Player);
|
|
Assert.Equal(4, rep.CheerHelpful);
|
|
Assert.Equal(int.MaxValue, rep.CheerCreative);
|
|
}
|
|
}
|