168 lines
6.8 KiB
C#
168 lines
6.8 KiB
C#
using NeonSprawl.Server.Game.Contracts;
|
|
using NeonSprawl.Server.Game.Encounters;
|
|
using NeonSprawl.Server.Game.Factions;
|
|
using NeonSprawl.Server.Game.Items;
|
|
using NeonSprawl.Server.Game.Mastery;
|
|
using NeonSprawl.Server.Game.Quests;
|
|
using NeonSprawl.Server.Game.Rewards;
|
|
|
|
namespace NeonSprawl.Server.Tests.Game.Contracts;
|
|
|
|
public sealed class ContractCompletionOperationsIntegrationTests
|
|
{
|
|
private const string PlayerId = "dev-local-1";
|
|
private const string TemplateId = "prototype_contract_clear_combat_pocket";
|
|
private const string EncounterId = "prototype_combat_pocket";
|
|
private const string MeleeNpc = "prototype_npc_melee";
|
|
private const string RangedNpc = "prototype_npc_ranged";
|
|
private const string EliteNpc = "prototype_npc_elite";
|
|
private const string SeedBucket = "2026-06-22";
|
|
|
|
[Fact]
|
|
public async Task TryIssueThenEncounterComplete_ShouldMarkContractCompleted_WhenResolvedFromDi()
|
|
{
|
|
// Arrange
|
|
await using var factory = new InMemoryWebApplicationFactory();
|
|
using var client = factory.CreateClient();
|
|
_ = await client.GetAsync("/health");
|
|
var deps = ResolveDependencies(factory);
|
|
var issued = ContractGeneratorOperations.TryIssue(
|
|
PlayerId,
|
|
TemplateId,
|
|
SeedBucket,
|
|
zoneDifficultyBand: null,
|
|
deps.TemplateRegistry,
|
|
deps.InstanceStore,
|
|
deps.StandingStore,
|
|
deps.TimeProvider);
|
|
Assert.True(issued.Success);
|
|
var instanceId = issued.Snapshot!.ContractInstanceId;
|
|
DefeatAllRequiredTargets(deps);
|
|
|
|
// Act
|
|
var encounterResult = EncounterCompletionOperations.TryCompleteAndGrant(
|
|
PlayerId,
|
|
EncounterId,
|
|
deps.EncounterRegistry,
|
|
deps.RewardTableRegistry,
|
|
deps.ProgressStore,
|
|
deps.CompletionStore,
|
|
deps.EventStore,
|
|
deps.ItemRegistry,
|
|
deps.InventoryStore,
|
|
deps.QuestRegistry,
|
|
deps.QuestProgressStore,
|
|
deps.SkillRegistry,
|
|
deps.SkillProgressionStore,
|
|
deps.LevelCurve,
|
|
deps.PerkUnlockEngine,
|
|
deps.PerkStore,
|
|
deps.DeliveryStore,
|
|
deps.StandingStore,
|
|
deps.AuditStore,
|
|
deps.InstanceStore,
|
|
deps.OutcomeStore,
|
|
deps.TemplateRegistry,
|
|
deps.TimeProvider);
|
|
|
|
// Assert
|
|
Assert.True(encounterResult.Success);
|
|
Assert.True(deps.InstanceStore.TryGet(PlayerId, instanceId, out var instance));
|
|
Assert.Equal(ContractInstanceStatus.Completed, instance.Status);
|
|
Assert.True(
|
|
deps.DeliveryStore.TryGet(
|
|
PlayerId,
|
|
RewardDeliverySourceKinds.ContractCompletion,
|
|
instanceId,
|
|
out _));
|
|
Assert.Single(deps.OutcomeStore.GetOutcomesForInstance(instanceId));
|
|
deps.InventoryStore.TryGetSnapshot(PlayerId, out var inventory);
|
|
Assert.Equal(15, CountBagItem(inventory!, "scrap_metal_bulk"));
|
|
Assert.Equal(1, CountBagItem(inventory!, "contract_handoff_token"));
|
|
}
|
|
|
|
private static void DefeatAllRequiredTargets(IntegrationTestDependencies deps)
|
|
{
|
|
foreach (var npcId in new[] { MeleeNpc, RangedNpc, EliteNpc })
|
|
{
|
|
_ = EncounterProgressOperations.TryActivateOnFirstEngagement(
|
|
PlayerId,
|
|
npcId,
|
|
deps.EncounterRegistry,
|
|
deps.ProgressStore,
|
|
deps.CompletionStore);
|
|
_ = EncounterProgressOperations.TryMarkTargetDefeated(
|
|
PlayerId,
|
|
npcId,
|
|
deps.EncounterRegistry,
|
|
deps.ProgressStore,
|
|
deps.CompletionStore);
|
|
}
|
|
}
|
|
|
|
private static int CountBagItem(PlayerInventorySnapshot snapshot, string itemId)
|
|
{
|
|
var total = 0;
|
|
foreach (var slot in snapshot.BagSlots)
|
|
{
|
|
if (string.Equals(slot.ItemId, itemId, StringComparison.Ordinal))
|
|
{
|
|
total += slot.Quantity;
|
|
}
|
|
}
|
|
|
|
return total;
|
|
}
|
|
|
|
private static IntegrationTestDependencies ResolveDependencies(InMemoryWebApplicationFactory factory)
|
|
{
|
|
using var scope = factory.Services.CreateScope();
|
|
var services = scope.ServiceProvider;
|
|
return new IntegrationTestDependencies(
|
|
services.GetRequiredService<IContractTemplateRegistry>(),
|
|
services.GetRequiredService<IContractInstanceStore>(),
|
|
services.GetRequiredService<IContractOutcomeStore>(),
|
|
services.GetRequiredService<IEncounterDefinitionRegistry>(),
|
|
services.GetRequiredService<IRewardTableDefinitionRegistry>(),
|
|
services.GetRequiredService<IEncounterProgressStore>(),
|
|
services.GetRequiredService<IEncounterCompletionStore>(),
|
|
services.GetRequiredService<IEncounterCompleteEventStore>(),
|
|
services.GetRequiredService<IItemDefinitionRegistry>(),
|
|
services.GetRequiredService<IPlayerInventoryStore>(),
|
|
services.GetRequiredService<IQuestDefinitionRegistry>(),
|
|
services.GetRequiredService<IPlayerQuestStateStore>(),
|
|
services.GetRequiredService<ISkillDefinitionRegistry>(),
|
|
services.GetRequiredService<IPlayerSkillProgressionStore>(),
|
|
services.GetRequiredService<ISkillLevelCurve>(),
|
|
services.GetRequiredService<PerkUnlockEngine>(),
|
|
services.GetRequiredService<IPlayerPerkStateStore>(),
|
|
services.GetRequiredService<IRewardDeliveryStore>(),
|
|
services.GetRequiredService<IFactionStandingStore>(),
|
|
services.GetRequiredService<IReputationDeltaStore>(),
|
|
services.GetRequiredService<TimeProvider>());
|
|
}
|
|
|
|
private sealed record IntegrationTestDependencies(
|
|
IContractTemplateRegistry TemplateRegistry,
|
|
IContractInstanceStore InstanceStore,
|
|
IContractOutcomeStore OutcomeStore,
|
|
IEncounterDefinitionRegistry EncounterRegistry,
|
|
IRewardTableDefinitionRegistry RewardTableRegistry,
|
|
IEncounterProgressStore ProgressStore,
|
|
IEncounterCompletionStore CompletionStore,
|
|
IEncounterCompleteEventStore EventStore,
|
|
IItemDefinitionRegistry ItemRegistry,
|
|
IPlayerInventoryStore InventoryStore,
|
|
IQuestDefinitionRegistry QuestRegistry,
|
|
IPlayerQuestStateStore QuestProgressStore,
|
|
ISkillDefinitionRegistry SkillRegistry,
|
|
IPlayerSkillProgressionStore SkillProgressionStore,
|
|
ISkillLevelCurve LevelCurve,
|
|
PerkUnlockEngine PerkUnlockEngine,
|
|
IPlayerPerkStateStore PerkStore,
|
|
IRewardDeliveryStore DeliveryStore,
|
|
IFactionStandingStore StandingStore,
|
|
IReputationDeltaStore AuditStore,
|
|
TimeProvider TimeProvider);
|
|
}
|