143 lines
4.9 KiB
C#
143 lines
4.9 KiB
C#
using NeonSprawl.Server.Game.Factions;
|
|
using Xunit;
|
|
|
|
namespace NeonSprawl.Server.Tests.Game.Factions;
|
|
|
|
public sealed class InMemoryReputationDeltaStoreTests
|
|
{
|
|
private const string PlayerId = "dev-local-1";
|
|
private const string GridFactionId = "prototype_faction_grid_operators";
|
|
private static readonly DateTimeOffset RecordedAt = new(2026, 6, 15, 12, 0, 0, TimeSpan.Zero);
|
|
|
|
[Fact]
|
|
public void TryAppend_ShouldReturnTrueAndQueryRow_WhenFirstAppend()
|
|
{
|
|
// Arrange
|
|
var store = CreateStore();
|
|
var row = CreateRow("delta-001", 15, 15);
|
|
// Act
|
|
var appended = store.TryAppend(row);
|
|
var rows = store.GetDeltasForPlayer(PlayerId);
|
|
// Assert
|
|
Assert.True(appended);
|
|
var read = Assert.Single(rows);
|
|
Assert.Equal(row.Id, read.Id);
|
|
Assert.Equal(15, read.DeltaAmount);
|
|
Assert.Equal(15, read.ResultingStanding);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryAppend_ShouldReturnFalse_WhenDuplicateId()
|
|
{
|
|
// Arrange
|
|
var store = CreateStore();
|
|
var row = CreateRow("delta-dup", 10, 10);
|
|
Assert.True(store.TryAppend(row));
|
|
// Act
|
|
var duplicate = store.TryAppend(row with { DeltaAmount = 99, ResultingStanding = 99 });
|
|
// Assert
|
|
Assert.False(duplicate);
|
|
var read = Assert.Single(store.GetDeltasForPlayer(PlayerId));
|
|
Assert.Equal(10, read.DeltaAmount);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryAppend_ShouldReturnTrueTwice_WhenDistinctIds()
|
|
{
|
|
// Arrange
|
|
var store = CreateStore();
|
|
// Act
|
|
var first = store.TryAppend(CreateRow("delta-a", 15, 15));
|
|
var second = store.TryAppend(CreateRow("delta-b", 10, 25));
|
|
// Assert
|
|
Assert.True(first);
|
|
Assert.True(second);
|
|
Assert.Equal(2, store.GetDeltasForPlayer(PlayerId).Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryAppend_ShouldReturnFalse_WhenRowInvalid()
|
|
{
|
|
// Arrange
|
|
var store = CreateStore();
|
|
var emptyId = CreateRow("", 5, 5);
|
|
var emptyPlayer = CreateRow("delta-x", 5, 5) with { PlayerId = " " };
|
|
var emptyFaction = CreateRow("delta-y", 5, 5) with { FactionId = "" };
|
|
// Act
|
|
var noId = store.TryAppend(emptyId);
|
|
var noPlayer = store.TryAppend(emptyPlayer);
|
|
var noFaction = store.TryAppend(emptyFaction);
|
|
// Assert
|
|
Assert.False(noId);
|
|
Assert.False(noPlayer);
|
|
Assert.False(noFaction);
|
|
Assert.Empty(store.GetDeltasForPlayer(PlayerId));
|
|
}
|
|
|
|
[Fact]
|
|
public void GetDeltasForPlayer_ShouldOrderByRecordedAtThenId()
|
|
{
|
|
// Arrange
|
|
var store = CreateStore();
|
|
Assert.True(store.TryAppend(CreateRow("delta-z", 1, 1) with { RecordedAt = RecordedAt.AddMinutes(2) }));
|
|
Assert.True(store.TryAppend(CreateRow("delta-a", 2, 3) with { RecordedAt = RecordedAt }));
|
|
Assert.True(store.TryAppend(CreateRow("delta-m", 3, 6) with { RecordedAt = RecordedAt }));
|
|
// Act
|
|
var rows = store.GetDeltasForPlayer(PlayerId);
|
|
// Assert
|
|
Assert.Equal(["delta-a", "delta-m", "delta-z"], [.. rows.Select(static r => r.Id)]);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetDeltasForPlayer_ShouldRespectLimit_WhenProvided()
|
|
{
|
|
// Arrange
|
|
var store = CreateStore();
|
|
Assert.True(store.TryAppend(CreateRow("delta-1", 1, 1)));
|
|
Assert.True(store.TryAppend(CreateRow("delta-2", 1, 2)));
|
|
// Act
|
|
var rows = store.GetDeltasForPlayer(PlayerId, limit: 1);
|
|
// Assert
|
|
Assert.Single(rows);
|
|
Assert.Equal("delta-1", rows[0].Id);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryClearQuestCompletionAudit_ShouldRemoveMatchingRows_WhenPresent()
|
|
{
|
|
// Arrange
|
|
var store = CreateStore();
|
|
Assert.True(store.TryAppend(CreateRow("delta-forward", 15, 15)));
|
|
Assert.True(store.TryAppend(CreateRow("delta-rollback", -15, 0) with
|
|
{
|
|
Id = "delta-forward:rollback",
|
|
}));
|
|
Assert.True(store.TryAppend(CreateRow("delta-other-quest", 10, 10) with
|
|
{
|
|
Id = "other-quest-delta",
|
|
SourceId = "prototype_quest_gather_intro",
|
|
}));
|
|
// Act
|
|
var cleared = store.TryClearQuestCompletionAudit(PlayerId, "prototype_quest_operator_chain");
|
|
// Assert
|
|
Assert.True(cleared);
|
|
Assert.DoesNotContain(
|
|
store.GetDeltasForPlayer(PlayerId),
|
|
row => row.SourceId == "prototype_quest_operator_chain");
|
|
Assert.Single(store.GetDeltasForPlayer(PlayerId));
|
|
}
|
|
|
|
private static InMemoryReputationDeltaStore CreateStore() => new();
|
|
|
|
private static ReputationDeltaRow CreateRow(string id, int delta, int resulting) =>
|
|
new(
|
|
id,
|
|
PlayerId,
|
|
GridFactionId,
|
|
delta,
|
|
resulting,
|
|
ReputationDeltaSourceKinds.QuestCompletion,
|
|
"prototype_quest_operator_chain",
|
|
RecordedAt);
|
|
}
|