273 lines
9.6 KiB
C#
273 lines
9.6 KiB
C#
using Microsoft.Extensions.DependencyInjection;
|
|
using NeonSprawl.Server.Game.Quests;
|
|
using NeonSprawl.Server.Tests;
|
|
using Xunit;
|
|
|
|
namespace NeonSprawl.Server.Tests.Game.Quests;
|
|
|
|
public class QuestDefinitionRegistryTests
|
|
{
|
|
private const string GatherIntroId = "prototype_quest_gather_intro";
|
|
private const string OperatorChainId = "prototype_quest_operator_chain";
|
|
|
|
public static TheoryData<string> FrozenQuestIds =>
|
|
new(PrototypeE7M1QuestCatalogRules.ExpectedQuestIds.Order(StringComparer.Ordinal));
|
|
|
|
private static QuestDefinitionRegistry CreateRegistryFromRows(IReadOnlyDictionary<string, QuestDefRow> byId)
|
|
{
|
|
var catalog = new QuestDefinitionCatalog("/tmp/quests", byId, catalogJsonFileCount: 1);
|
|
return new QuestDefinitionRegistry(catalog);
|
|
}
|
|
|
|
private static QuestDefRow CreateGatherIntroRow() =>
|
|
new(
|
|
GatherIntroId,
|
|
"Intro: Salvage Run",
|
|
[],
|
|
[
|
|
new QuestStepDefRow(
|
|
"gather_intro_step_salvage",
|
|
"Gather scrap metal",
|
|
[
|
|
new QuestObjectiveDefRow(
|
|
"gather_intro_obj_scrap",
|
|
"gather_item",
|
|
"scrap_metal_bulk",
|
|
3,
|
|
null,
|
|
null),
|
|
]),
|
|
]);
|
|
|
|
[Theory]
|
|
[MemberData(nameof(FrozenQuestIds))]
|
|
public void TryGetDefinition_ShouldReturnTrue_WhenFrozenQuestIdExists(string questId)
|
|
{
|
|
// Arrange
|
|
var rows = new Dictionary<string, QuestDefRow>(StringComparer.Ordinal)
|
|
{
|
|
[questId] = new QuestDefRow(questId, "Test Quest", [], []),
|
|
};
|
|
var registry = CreateRegistryFromRows(rows);
|
|
// Act
|
|
var found = registry.TryGetDefinition(questId, out var def);
|
|
// Assert
|
|
Assert.True(found);
|
|
Assert.NotNull(def);
|
|
Assert.Equal(questId, def!.Id);
|
|
Assert.Equal("Test Quest", def.DisplayName);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryGetDefinition_ShouldReturnTrueAndExpectedMetadata_WhenGatherIntroExists()
|
|
{
|
|
// Arrange
|
|
var rows = new Dictionary<string, QuestDefRow>(StringComparer.Ordinal)
|
|
{
|
|
[GatherIntroId] = CreateGatherIntroRow(),
|
|
};
|
|
var registry = CreateRegistryFromRows(rows);
|
|
// Act
|
|
var found = registry.TryGetDefinition(GatherIntroId, out var def);
|
|
// Assert
|
|
Assert.True(found);
|
|
Assert.NotNull(def);
|
|
Assert.Equal("Intro: Salvage Run", def!.DisplayName);
|
|
Assert.Single(def.Steps);
|
|
Assert.Equal("gather_intro_step_salvage", def.Steps[0].Id);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryGetDefinition_ShouldReturnTrueAndFourSteps_WhenOperatorChainExists()
|
|
{
|
|
// Arrange
|
|
var rows = new Dictionary<string, QuestDefRow>(StringComparer.Ordinal)
|
|
{
|
|
[OperatorChainId] = new QuestDefRow(
|
|
OperatorChainId,
|
|
"Operator Chain",
|
|
["prototype_quest_gather_intro"],
|
|
[
|
|
new QuestStepDefRow("chain_step_gather", "Bulk salvage", []),
|
|
new QuestStepDefRow("chain_step_refine", "Refine stock", []),
|
|
new QuestStepDefRow("chain_step_stim", "Craft field stim", []),
|
|
new QuestStepDefRow("chain_step_token", "Hand off contract token", []),
|
|
]),
|
|
};
|
|
var registry = CreateRegistryFromRows(rows);
|
|
// Act
|
|
var found = registry.TryGetDefinition(OperatorChainId, out var def);
|
|
// Assert
|
|
Assert.True(found);
|
|
Assert.NotNull(def);
|
|
Assert.Equal(4, def!.Steps.Count);
|
|
Assert.Equal("chain_step_token", def.Steps[3].Id);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryGetDefinition_ShouldReturnFalse_WhenQuestIdIsNull()
|
|
{
|
|
// Arrange
|
|
var rows = new Dictionary<string, QuestDefRow>(StringComparer.Ordinal)
|
|
{
|
|
[GatherIntroId] = CreateGatherIntroRow(),
|
|
};
|
|
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_WhenQuestIdIsEmpty()
|
|
{
|
|
// Arrange
|
|
var rows = new Dictionary<string, QuestDefRow>(StringComparer.Ordinal)
|
|
{
|
|
[GatherIntroId] = CreateGatherIntroRow(),
|
|
};
|
|
var registry = CreateRegistryFromRows(rows);
|
|
// Act
|
|
var found = registry.TryGetDefinition(string.Empty, out var def);
|
|
// Assert
|
|
Assert.False(found);
|
|
Assert.Null(def);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryGetDefinition_ShouldReturnFalse_WhenIdUnknown()
|
|
{
|
|
// Arrange
|
|
var rows = new Dictionary<string, QuestDefRow>(StringComparer.Ordinal)
|
|
{
|
|
[GatherIntroId] = CreateGatherIntroRow(),
|
|
};
|
|
var registry = CreateRegistryFromRows(rows);
|
|
// Act
|
|
var found = registry.TryGetDefinition("not_a_real_quest", out var def);
|
|
// Assert
|
|
Assert.False(found);
|
|
Assert.Null(def);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryNormalizeKnown_ShouldReturnTrueAndLowercaseId_WhenInputHasWhitespaceAndMixedCase()
|
|
{
|
|
// Arrange
|
|
var rows = new Dictionary<string, QuestDefRow>(StringComparer.Ordinal)
|
|
{
|
|
[GatherIntroId] = CreateGatherIntroRow(),
|
|
};
|
|
var registry = CreateRegistryFromRows(rows);
|
|
// Act
|
|
var found = registry.TryNormalizeKnown(" Prototype_Quest_Gather_Intro ", out var normalized);
|
|
// Assert
|
|
Assert.True(found);
|
|
Assert.Equal(GatherIntroId, normalized);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryNormalizeKnown_ShouldReturnFalse_WhenInputIsNull()
|
|
{
|
|
// Arrange
|
|
var rows = new Dictionary<string, QuestDefRow>(StringComparer.Ordinal)
|
|
{
|
|
[GatherIntroId] = CreateGatherIntroRow(),
|
|
};
|
|
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, QuestDefRow>(StringComparer.Ordinal)
|
|
{
|
|
[GatherIntroId] = CreateGatherIntroRow(),
|
|
};
|
|
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, QuestDefRow>(StringComparer.Ordinal)
|
|
{
|
|
[GatherIntroId] = CreateGatherIntroRow(),
|
|
};
|
|
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_WhenMultipleQuests()
|
|
{
|
|
// Arrange
|
|
var rows = new Dictionary<string, QuestDefRow>(StringComparer.Ordinal)
|
|
{
|
|
["z_quest"] = new QuestDefRow("z_quest", "Z", [], []),
|
|
[GatherIntroId] = CreateGatherIntroRow(),
|
|
["a_quest"] = new QuestDefRow("a_quest", "A", [], []),
|
|
};
|
|
var registry = CreateRegistryFromRows(rows);
|
|
// Act
|
|
var list = registry.GetDefinitionsInIdOrder();
|
|
// Assert
|
|
Assert.Equal(3, list.Count);
|
|
Assert.Equal("a_quest", list[0].Id);
|
|
Assert.Equal(GatherIntroId, list[1].Id);
|
|
Assert.Equal("z_quest", 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<IQuestDefinitionRegistry>();
|
|
var gatherFound = registry.TryGetDefinition(GatherIntroId, out var gather);
|
|
var unknown = registry.TryGetDefinition("not_a_real_quest", out var missing);
|
|
var normalized = registry.TryNormalizeKnown(" Prototype_Quest_Gather_Intro ", out var questId);
|
|
var unknownNormalized = registry.TryNormalizeKnown("prototype_unknown", out var unknownQuestId);
|
|
var list = registry.GetDefinitionsInIdOrder();
|
|
// Assert
|
|
Assert.True(gatherFound);
|
|
Assert.NotNull(gather);
|
|
Assert.Equal("Intro: Salvage Run", gather!.DisplayName);
|
|
Assert.False(unknown);
|
|
Assert.Null(missing);
|
|
Assert.True(normalized);
|
|
Assert.Equal(GatherIntroId, questId);
|
|
Assert.False(unknownNormalized);
|
|
Assert.Equal("prototype_unknown", unknownQuestId);
|
|
Assert.Equal(4, list.Count);
|
|
Assert.Equal(PrototypeE7M1QuestCatalogRules.ExpectedQuestIds.Order(StringComparer.Ordinal), list.Select(q => q.Id));
|
|
foreach (var expectedId in PrototypeE7M1QuestCatalogRules.ExpectedQuestIds)
|
|
{
|
|
Assert.True(registry.TryGetDefinition(expectedId, out var def));
|
|
Assert.NotNull(def);
|
|
Assert.False(string.IsNullOrWhiteSpace(def!.DisplayName));
|
|
}
|
|
}
|
|
}
|