neon-sprawl/server/NeonSprawl.Server.Tests/Game/Encounters/RewardTableDefinitionRegist...

185 lines
7.0 KiB
C#

using NeonSprawl.Server.Game.Encounters;
namespace NeonSprawl.Server.Tests.Game.Encounters;
public class RewardTableDefinitionRegistryTests
{
private const string PrototypeCombatPocketClear = "prototype_combat_pocket_clear";
private static RewardTableDefinitionRegistry CreateRegistryFromRows(IReadOnlyDictionary<string, RewardTableDefRow> byId)
{
var catalog = new RewardTableDefinitionCatalog("/tmp/reward-tables", byId, catalogJsonFileCount: 1);
return new RewardTableDefinitionRegistry(catalog);
}
private static RewardTableDefRow CreatePrototypeCombatPocketClearRow() =>
new(
PrototypeCombatPocketClear,
"Prototype Combat Pocket Clear",
[
new RewardGrantRow("scrap_metal_bulk", 10),
new RewardGrantRow("contract_handoff_token", 1),
]);
[Fact]
public void TryGetDefinition_ShouldReturnTrueAndExpectedMetadata_WhenIdExists()
{
// Arrange
var rows = new Dictionary<string, RewardTableDefRow>(StringComparer.Ordinal)
{
[PrototypeCombatPocketClear] = CreatePrototypeCombatPocketClearRow(),
};
var registry = CreateRegistryFromRows(rows);
// Act
var found = registry.TryGetDefinition(PrototypeCombatPocketClear, out var def);
// Assert
Assert.True(found);
Assert.NotNull(def);
Assert.Equal("Prototype Combat Pocket Clear", def!.DisplayName);
Assert.Equal(10, def.FixedGrants.First(g => g.ItemId == "scrap_metal_bulk").Quantity);
Assert.Equal(1, def.FixedGrants.First(g => g.ItemId == "contract_handoff_token").Quantity);
}
[Fact]
public void TryGetDefinition_ShouldReturnFalse_WhenRewardTableIdIsNull()
{
// Arrange
var rows = new Dictionary<string, RewardTableDefRow>(StringComparer.Ordinal)
{
[PrototypeCombatPocketClear] = CreatePrototypeCombatPocketClearRow(),
};
var registry = CreateRegistryFromRows(rows);
// Act
var found = registry.TryGetDefinition(null, out var def);
// Assert
Assert.False(found);
Assert.Null(def);
}
[Fact]
public void TryGetDefinition_ShouldReturnFalse_WhenIdUnknown()
{
// Arrange
var rows = new Dictionary<string, RewardTableDefRow>(StringComparer.Ordinal)
{
[PrototypeCombatPocketClear] = CreatePrototypeCombatPocketClearRow(),
};
var registry = CreateRegistryFromRows(rows);
// Act
var found = registry.TryGetDefinition("not_a_real_reward_table", out var def);
// Assert
Assert.False(found);
Assert.Null(def);
}
[Fact]
public void TryNormalizeKnown_ShouldReturnTrueAndLowercaseId_WhenInputHasWhitespaceAndMixedCase()
{
// Arrange
var rows = new Dictionary<string, RewardTableDefRow>(StringComparer.Ordinal)
{
[PrototypeCombatPocketClear] = CreatePrototypeCombatPocketClearRow(),
};
var registry = CreateRegistryFromRows(rows);
// Act
var found = registry.TryNormalizeKnown(" Prototype_Combat_Pocket_Clear ", out var normalized);
// Assert
Assert.True(found);
Assert.Equal(PrototypeCombatPocketClear, normalized);
}
[Fact]
public void TryNormalizeKnown_ShouldReturnFalse_WhenInputIsNull()
{
// Arrange
var rows = new Dictionary<string, RewardTableDefRow>(StringComparer.Ordinal)
{
[PrototypeCombatPocketClear] = CreatePrototypeCombatPocketClearRow(),
};
var registry = CreateRegistryFromRows(rows);
// Act
var found = registry.TryNormalizeKnown(null, out var normalized);
// Assert
Assert.False(found);
Assert.Equal(string.Empty, normalized);
}
[Fact]
public void TryNormalizeKnown_ShouldReturnFalse_WhenInputIsWhitespaceOnly()
{
// Arrange
var rows = new Dictionary<string, RewardTableDefRow>(StringComparer.Ordinal)
{
[PrototypeCombatPocketClear] = CreatePrototypeCombatPocketClearRow(),
};
var registry = CreateRegistryFromRows(rows);
// Act
var found = registry.TryNormalizeKnown(" ", out var normalized);
// Assert
Assert.False(found);
Assert.Equal(string.Empty, normalized);
}
[Fact]
public void TryNormalizeKnown_ShouldReturnFalse_WhenIdNotInCatalog()
{
// Arrange
var rows = new Dictionary<string, RewardTableDefRow>(StringComparer.Ordinal)
{
[PrototypeCombatPocketClear] = CreatePrototypeCombatPocketClearRow(),
};
var registry = CreateRegistryFromRows(rows);
// Act
var found = registry.TryNormalizeKnown("prototype_unknown", out var normalized);
// Assert
Assert.False(found);
Assert.Equal("prototype_unknown", normalized);
}
[Fact]
public void GetDefinitionsInIdOrder_ShouldListAllRowsOrderedById_WhenMultipleRewardTables()
{
// Arrange
var rows = new Dictionary<string, RewardTableDefRow>(StringComparer.Ordinal)
{
["z_table"] = new RewardTableDefRow("z_table", "Z", [new RewardGrantRow("scrap_metal_bulk", 1)]),
[PrototypeCombatPocketClear] = CreatePrototypeCombatPocketClearRow(),
["a_table"] = new RewardTableDefRow("a_table", "A", [new RewardGrantRow("scrap_metal_bulk", 1)]),
};
var registry = CreateRegistryFromRows(rows);
// Act
var list = registry.GetDefinitionsInIdOrder();
// Assert
Assert.Equal(3, list.Count);
Assert.Equal("a_table", list[0].Id);
Assert.Equal(PrototypeCombatPocketClear, list[1].Id);
Assert.Equal("z_table", list[2].Id);
}
[Fact]
public async Task Host_ShouldResolveRegistryFromDi_WhenStartupSucceeds()
{
// Arrange
await using var factory = new InMemoryWebApplicationFactory();
using var client = factory.CreateClient();
_ = await client.GetAsync("/health");
// Act
var registry = factory.Services.GetRequiredService<IRewardTableDefinitionRegistry>();
var found = registry.TryGetDefinition(PrototypeCombatPocketClear, out var rewardTable);
var unknown = registry.TryGetDefinition("not_a_real_reward_table", out var missing);
var normalized = registry.TryNormalizeKnown(" Prototype_Combat_Pocket_Clear ", out var rewardTableId);
var list = registry.GetDefinitionsInIdOrder();
// Assert
Assert.True(found);
Assert.NotNull(rewardTable);
Assert.Equal(10, rewardTable!.FixedGrants.First(g => g.ItemId == "scrap_metal_bulk").Quantity);
Assert.Equal(1, rewardTable.FixedGrants.First(g => g.ItemId == "contract_handoff_token").Quantity);
Assert.False(unknown);
Assert.Null(missing);
Assert.True(normalized);
Assert.Equal(PrototypeCombatPocketClear, rewardTableId);
Assert.Single(list);
Assert.Equal(PrototypeCombatPocketClear, list[0].Id);
}
}