neon-sprawl/server/NeonSprawl.Server.Tests/Game/Items/ItemDefinitionRegistryTests.cs

191 lines
6.7 KiB
C#

using NeonSprawl.Server.Game.Items;
namespace NeonSprawl.Server.Tests.Game.Items;
public class ItemDefinitionRegistryTests
{
private static ItemDefinitionRegistry CreateRegistryFromRows(IReadOnlyDictionary<string, ItemDefRow> byId)
{
var catalog = new ItemDefinitionCatalog("/tmp/catalog", byId, catalogJsonFileCount: 1);
return new ItemDefinitionRegistry(catalog);
}
[Fact]
public void TryGetDefinition_ShouldReturnTrueAndExpectedMetadata_WhenIdExists()
{
// Arrange
var rows = new Dictionary<string, ItemDefRow>(StringComparer.Ordinal)
{
["scrap_metal_bulk"] = new ItemDefRow(
"scrap_metal_bulk",
"Scrap Metal (Bulk)",
"material",
StackMax: 999,
InventorySlotKind: "bag",
Rarity: null,
BindPolicy: null,
DurabilityMax: null),
};
var registry = CreateRegistryFromRows(rows);
// Act
var found = registry.TryGetDefinition("scrap_metal_bulk", out var def);
// Assert
Assert.True(found);
Assert.NotNull(def);
Assert.Equal("material", def.PrototypeRole);
Assert.Equal("Scrap Metal (Bulk)", def.DisplayName);
Assert.Equal(999, def.StackMax);
Assert.Equal("bag", def.InventorySlotKind);
}
[Fact]
public void TryGetDefinition_ShouldReturnFalse_WhenItemIdIsNull()
{
// Arrange
var rows = new Dictionary<string, ItemDefRow>(StringComparer.Ordinal)
{
["scrap_metal_bulk"] = new ItemDefRow(
"scrap_metal_bulk",
"Scrap Metal (Bulk)",
"material",
StackMax: 999,
InventorySlotKind: "bag",
Rarity: null,
BindPolicy: null,
DurabilityMax: null),
};
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, ItemDefRow>(StringComparer.Ordinal)
{
["scrap_metal_bulk"] = new ItemDefRow(
"scrap_metal_bulk",
"Scrap Metal (Bulk)",
"material",
StackMax: 999,
InventorySlotKind: "bag",
Rarity: null,
BindPolicy: null,
DurabilityMax: null),
};
var registry = CreateRegistryFromRows(rows);
// Act
var found = registry.TryGetDefinition("not_a_real_item", out var def);
// Assert
Assert.False(found);
Assert.Null(def);
}
[Fact]
public void GetDefinitionsInIdOrder_ShouldListAllRowsOrderedById_WhenMultipleItems()
{
// Arrange
var rows = new Dictionary<string, ItemDefRow>(StringComparer.Ordinal)
{
["survey_drone_kit"] = new ItemDefRow(
"survey_drone_kit",
"Survey Drone Kit",
"utility",
StackMax: 1,
InventorySlotKind: "bag",
Rarity: null,
BindPolicy: null,
DurabilityMax: null),
["scrap_metal_bulk"] = new ItemDefRow(
"scrap_metal_bulk",
"Scrap Metal (Bulk)",
"material",
StackMax: 999,
InventorySlotKind: "bag",
Rarity: null,
BindPolicy: null,
DurabilityMax: null),
["prototype_armor_shell"] = new ItemDefRow(
"prototype_armor_shell",
"Prototype Armor Shell",
"equip_stub",
StackMax: 1,
InventorySlotKind: "equipment",
Rarity: null,
BindPolicy: null,
DurabilityMax: null),
};
var registry = CreateRegistryFromRows(rows);
// Act
var list = registry.GetDefinitionsInIdOrder();
// Assert
Assert.Equal(3, list.Count);
Assert.Equal("prototype_armor_shell", list[0].Id);
Assert.Equal("scrap_metal_bulk", list[1].Id);
Assert.Equal("survey_drone_kit", list[2].Id);
}
[Fact]
public void TryGetDefinition_ShouldMatchLoaderCatalog_WhenUsingPrototypeFixture()
{
// Arrange
var root = Directory.CreateTempSubdirectory("neon-sprawl-item-registry-loader-");
try
{
var itemsDir = Path.Combine(root.FullName, "content", "items");
var schemaDir = Path.Combine(root.FullName, "content", "schemas");
Directory.CreateDirectory(itemsDir);
Directory.CreateDirectory(schemaDir);
var schemaPath = Path.Combine(schemaDir, "item-def.schema.json");
File.Copy(ItemCatalogTestPaths.DiscoverRepoItemDefSchemaPath(), schemaPath, overwrite: true);
File.Copy(
Path.Combine(ItemCatalogTestPaths.DiscoverRepoItemsDirectory(), "prototype_items.json"),
Path.Combine(itemsDir, "prototype_items.json"),
overwrite: true);
var loaded = ItemDefinitionCatalogLoader.Load(itemsDir, schemaPath, NullLogger.Instance);
var registry = new ItemDefinitionRegistry(loaded);
// Act
var ok = registry.TryGetDefinition("prototype_armor_shell", out var equipStub);
// Assert
Assert.True(ok);
Assert.NotNull(equipStub);
Assert.Equal("equip_stub", equipStub.PrototypeRole);
Assert.Equal("equipment", equipStub.InventorySlotKind);
Assert.Equal(1, equipStub.StackMax);
}
finally
{
try
{
Directory.Delete(root.FullName, recursive: true);
}
catch (IOException)
{
// Best-effort: transient lock or race on some hosts; temp dir is unique per run.
}
}
}
[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<IItemDefinitionRegistry>();
var found = registry.TryGetDefinition("scrap_metal_bulk", out var scrap);
// Assert
Assert.True(found);
Assert.NotNull(scrap);
Assert.Equal("material", scrap.PrototypeRole);
Assert.Equal(999, scrap.StackMax);
}
}