67 lines
2.3 KiB
C#
67 lines
2.3 KiB
C#
using NeonSprawl.Server.Game.Encounters;
|
|
|
|
namespace NeonSprawl.Server.Tests.Game.Encounters;
|
|
|
|
public sealed class InMemoryEncounterCompleteEventStoreTests
|
|
{
|
|
private const string PlayerId = "dev-local-1";
|
|
private const string EncounterId = "prototype_combat_pocket";
|
|
private static readonly DateTimeOffset CompletedAt = new(2026, 5, 31, 20, 0, 0, TimeSpan.Zero);
|
|
|
|
[Fact]
|
|
public void TryRecord_ShouldBeIdempotent_AtStoreLayer()
|
|
{
|
|
// Arrange
|
|
var store = new InMemoryEncounterCompleteEventStore();
|
|
var completeEvent = CreatePrototypeEvent();
|
|
// Act
|
|
var first = store.TryRecord(completeEvent);
|
|
var second = store.TryRecord(completeEvent with { CompletedAt = CompletedAt.AddHours(1) });
|
|
// Assert
|
|
Assert.True(first);
|
|
Assert.False(second);
|
|
Assert.True(store.TryGet(PlayerId, EncounterId, out var stored));
|
|
Assert.Equal(completeEvent.IdempotencyKey, stored.IdempotencyKey);
|
|
Assert.Equal(CompletedAt, stored.CompletedAt);
|
|
Assert.Equal(2, stored.GrantedItems.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryRecord_ShouldFailClosed_WhenPlayerIdIsEmpty()
|
|
{
|
|
// Arrange
|
|
var store = new InMemoryEncounterCompleteEventStore();
|
|
var invalidEvent = CreatePrototypeEvent() with { PlayerId = " " };
|
|
// Act
|
|
var recorded = store.TryRecord(invalidEvent);
|
|
// Assert
|
|
Assert.False(recorded);
|
|
Assert.False(store.TryGet(" ", EncounterId, out _));
|
|
}
|
|
|
|
[Fact]
|
|
public void TryRecord_ShouldFailClosed_WhenEncounterIdIsEmpty()
|
|
{
|
|
// Arrange
|
|
var store = new InMemoryEncounterCompleteEventStore();
|
|
var invalidEvent = CreatePrototypeEvent() with { EncounterId = " " };
|
|
// Act
|
|
var recorded = store.TryRecord(invalidEvent);
|
|
// Assert
|
|
Assert.False(recorded);
|
|
Assert.False(store.TryGet(PlayerId, " ", out _));
|
|
}
|
|
|
|
private static EncounterCompleteEvent CreatePrototypeEvent() =>
|
|
new(
|
|
PlayerId,
|
|
EncounterId,
|
|
"prototype_combat_pocket_clear",
|
|
[
|
|
new EncounterGrantApplied("scrap_metal_bulk", 10),
|
|
new EncounterGrantApplied("contract_handoff_token", 1),
|
|
],
|
|
CompletedAt,
|
|
$"{PlayerId}:{EncounterId}");
|
|
}
|