neon-sprawl/server/NeonSprawl.Server.Tests/Game/Skills/ContentBackedSkillLevelCurv...

113 lines
3.5 KiB
C#

namespace NeonSprawl.Server.Tests.Game.Skills;
public sealed class ContentBackedSkillLevelCurveTests
{
private const string LevelCurveSchemaJson =
"""
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"additionalProperties": false,
"required": ["schemaVersion", "levels"],
"properties": {
"schemaVersion": { "type": "integer", "const": 1 },
"levels": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["level", "requiredXp"],
"properties": {
"level": { "type": "integer", "minimum": 1 },
"requiredXp": { "type": "integer", "minimum": 0 }
}
}
}
}
}
""";
private static ContentBackedSkillLevelCurve BuildCurve() =>
new(
[
new ContentBackedSkillLevelCurve.LevelThresholdRow(1, 0),
new ContentBackedSkillLevelCurve.LevelThresholdRow(2, 100),
new ContentBackedSkillLevelCurve.LevelThresholdRow(3, 250),
new ContentBackedSkillLevelCurve.LevelThresholdRow(4, 450),
]);
[Theory]
[InlineData(-5, 1)]
[InlineData(0, 1)]
[InlineData(99, 1)]
[InlineData(100, 2)]
[InlineData(249, 2)]
[InlineData(250, 3)]
[InlineData(449, 3)]
[InlineData(450, 4)]
[InlineData(9999, 4)]
public void LevelFromTotalXp_ShouldResolveExpectedLevelAcrossBoundaries(int xp, int expectedLevel)
{
// Arrange
var curve = BuildCurve();
// Act
var level = curve.LevelFromTotalXp(xp);
// Assert
Assert.Equal(expectedLevel, level);
}
[Fact]
public void Load_ShouldThrow_WhenCurveHasUnexpectedTopLevelProperty()
{
// Arrange
var root = Directory.CreateTempSubdirectory("neon-sprawl-level-curve-");
try
{
var skillsDir = Path.Combine(root.FullName, "content", "skills");
var schemaDir = Path.Combine(root.FullName, "content", "schemas");
Directory.CreateDirectory(skillsDir);
Directory.CreateDirectory(schemaDir);
var curvePath = Path.Combine(skillsDir, "prototype_level_curve.json");
var schemaPath = Path.Combine(schemaDir, "level-curve.schema.json");
File.WriteAllText(schemaPath, LevelCurveSchemaJson, Encoding.UTF8);
File.WriteAllText(
curvePath,
"""
{
"schemaVersion": 1,
"levels": [
{ "level": 1, "requiredXp": 0 },
{ "level": 2, "requiredXp": 100 }
],
"extraField": "should-fail"
}
""",
Encoding.UTF8);
// Act
var ex = Record.Exception(() =>
ContentBackedSkillLevelCurve.Load(skillsDir, curvePath, schemaPath, NullLogger.Instance));
// Assert
var ioe = Assert.IsType<InvalidOperationException>(ex);
Assert.Contains("extraField", ioe.Message, StringComparison.Ordinal);
}
finally
{
try
{
Directory.Delete(root.FullName, recursive: true);
}
catch (IOException)
{
// Best-effort cleanup only.
}
}
}
}