158 lines
6.1 KiB
C#
158 lines
6.1 KiB
C#
using System.Net;
|
|
using System.Text;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
using NeonSprawl.Server.Game.Skills;
|
|
using NeonSprawl.Server.Tests;
|
|
using Xunit;
|
|
|
|
namespace NeonSprawl.Server.Tests.Game.Skills;
|
|
|
|
public class SkillDefinitionRegistryTests
|
|
{
|
|
private static SkillDefinitionRegistry CreateRegistryFromRows(IReadOnlyDictionary<string, SkillDefRow> byId)
|
|
{
|
|
var catalog = new SkillDefinitionCatalog("/tmp/catalog", byId, catalogJsonFileCount: 1);
|
|
return new SkillDefinitionRegistry(catalog);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryGetDefinition_ShouldReturnTrueAndExpectedXpKinds_WhenIdExists()
|
|
{
|
|
// Arrange
|
|
var rows = new Dictionary<string, SkillDefRow>(StringComparer.Ordinal)
|
|
{
|
|
["intrusion"] = new SkillDefRow(
|
|
"intrusion",
|
|
"tech",
|
|
"Intrusion",
|
|
new[] { "activity", "mission_reward", "book_or_item" }),
|
|
};
|
|
var registry = CreateRegistryFromRows(rows);
|
|
// Act
|
|
var found = registry.TryGetDefinition("intrusion", out var def);
|
|
// Assert
|
|
Assert.True(found);
|
|
Assert.NotNull(def);
|
|
Assert.Equal("tech", def.Category);
|
|
Assert.Equal("Intrusion", def.DisplayName);
|
|
Assert.Contains("activity", def.AllowedXpSourceKinds, StringComparer.Ordinal);
|
|
Assert.Contains("book_or_item", def.AllowedXpSourceKinds, StringComparer.Ordinal);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryGetDefinition_ShouldReturnFalse_WhenIdUnknown()
|
|
{
|
|
// Arrange
|
|
var rows = new Dictionary<string, SkillDefRow>(StringComparer.Ordinal)
|
|
{
|
|
["salvage"] = new SkillDefRow("salvage", "gather", "Salvage", new[] { "activity" }),
|
|
};
|
|
var registry = CreateRegistryFromRows(rows);
|
|
// Act
|
|
var found = registry.TryGetDefinition("not_a_real_skill", out var def);
|
|
// Assert
|
|
Assert.False(found);
|
|
Assert.Null(def);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetDefinitionsInIdOrder_ShouldListAllRowsOrderedById_WhenMultipleSkills()
|
|
{
|
|
// Arrange
|
|
var rows = new Dictionary<string, SkillDefRow>(StringComparer.Ordinal)
|
|
{
|
|
["salvage"] = new SkillDefRow("salvage", "gather", "Salvage", new[] { "activity", "mission_reward" }),
|
|
["refine"] = new SkillDefRow("refine", "process", "Refine", new[] { "activity" }),
|
|
["intrusion"] = new SkillDefRow("intrusion", "tech", "Intrusion", new[] { "trainer" }),
|
|
};
|
|
var registry = CreateRegistryFromRows(rows);
|
|
// Act
|
|
var list = registry.GetDefinitionsInIdOrder();
|
|
// Assert
|
|
Assert.Equal(3, list.Count);
|
|
Assert.Equal("intrusion", list[0].Id);
|
|
Assert.Equal("refine", list[1].Id);
|
|
Assert.Equal("salvage", list[2].Id);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryGetDefinition_ShouldMatchLoaderCatalog_WhenUsingPrototypeFixture()
|
|
{
|
|
// Arrange
|
|
var root = Directory.CreateTempSubdirectory("neon-sprawl-registry-loader-");
|
|
try
|
|
{
|
|
var skillsDir = Path.Combine(root.FullName, "content", "skills");
|
|
var schemaDir = Path.Combine(root.FullName, "content", "schemas");
|
|
Directory.CreateDirectory(skillsDir);
|
|
Directory.CreateDirectory(schemaDir);
|
|
var schemaPath = Path.Combine(schemaDir, "skill-def.schema.json");
|
|
File.Copy(SkillCatalogTestPaths.DiscoverRepoSkillDefSchemaPath(), schemaPath, overwrite: true);
|
|
var json = """
|
|
{
|
|
"skills": [
|
|
{
|
|
"id": "salvage",
|
|
"category": "gather",
|
|
"displayName": "Salvage",
|
|
"allowedXpSourceKinds": ["activity", "mission_reward"]
|
|
},
|
|
{
|
|
"id": "refine",
|
|
"category": "process",
|
|
"displayName": "Refine",
|
|
"allowedXpSourceKinds": ["activity", "mission_reward", "trainer"]
|
|
},
|
|
{
|
|
"id": "intrusion",
|
|
"category": "tech",
|
|
"displayName": "Intrusion",
|
|
"allowedXpSourceKinds": ["activity", "mission_reward", "book_or_item"]
|
|
}
|
|
]
|
|
}
|
|
""";
|
|
File.WriteAllText(Path.Combine(skillsDir, "prototype.json"), json, Encoding.UTF8);
|
|
var loaded = SkillDefinitionCatalogLoader.Load(skillsDir, schemaPath, NullLogger.Instance);
|
|
var registry = new SkillDefinitionRegistry(loaded);
|
|
// Act
|
|
var ok = registry.TryGetDefinition("refine", out var refine);
|
|
// Assert
|
|
Assert.True(ok);
|
|
Assert.NotNull(refine);
|
|
Assert.Equal("process", refine.Category);
|
|
Assert.Contains("trainer", refine.AllowedXpSourceKinds, StringComparer.Ordinal);
|
|
}
|
|
finally
|
|
{
|
|
try
|
|
{
|
|
Directory.Delete(root.FullName, recursive: true);
|
|
}
|
|
catch
|
|
{
|
|
// best-effort cleanup for temp dir
|
|
}
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Host_ShouldResolveRegistryFromDi_WhenStartupSucceeds()
|
|
{
|
|
// Arrange
|
|
await using var factory = new InMemoryWebApplicationFactory();
|
|
using var client = factory.CreateClient();
|
|
// Act
|
|
var response = await client.GetAsync("/health");
|
|
var registry = factory.Services.GetRequiredService<ISkillDefinitionRegistry>();
|
|
var found = registry.TryGetDefinition("salvage", out var salvage);
|
|
var status = response.StatusCode;
|
|
// Assert
|
|
Assert.Equal(HttpStatusCode.OK, status);
|
|
Assert.True(found);
|
|
Assert.NotNull(salvage);
|
|
Assert.Contains("activity", salvage.AllowedXpSourceKinds, StringComparer.Ordinal);
|
|
}
|
|
}
|