using Microsoft.Extensions.DependencyInjection; using NeonSprawl.Server.Game.Contracts; using NeonSprawl.Server.Game.Factions; using NeonSprawl.Server.Tests; using Xunit; namespace NeonSprawl.Server.Tests.Game.Contracts; public sealed class ContractGeneratorOperationsIntegrationTests { 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 SeedBucket = "2026-06-22"; [Fact] public async Task TryIssue_ShouldCreateActiveInstanceWithEncounterBinding_WhenResolvedFromDi() { // Arrange await using var factory = new InMemoryWebApplicationFactory(); using var client = factory.CreateClient(); _ = await client.GetAsync("/health"); using var scope = factory.Services.CreateScope(); var templateRegistry = scope.ServiceProvider.GetRequiredService(); var instanceStore = scope.ServiceProvider.GetRequiredService(); var standingStore = scope.ServiceProvider.GetRequiredService(); var timeProvider = scope.ServiceProvider.GetRequiredService(); var expectedInstanceId = ContractInstanceIds.MakeDeterministicInstanceId( PlayerId, TemplateId, SeedBucket); // Act var result = ContractGeneratorOperations.TryIssue( PlayerId, TemplateId, SeedBucket, zoneDifficultyBand: null, templateRegistry, instanceStore, standingStore, timeProvider); // Assert Assert.True(result.Success); Assert.Null(result.ReasonCode); Assert.NotNull(result.Snapshot); Assert.Equal(expectedInstanceId, result.Snapshot!.ContractInstanceId); Assert.Equal(TemplateId, result.Snapshot.TemplateId); Assert.Equal(EncounterId, result.EncounterTemplateId); Assert.Equal(ContractInstanceStatus.Active, result.Snapshot.Status); Assert.True(instanceStore.TryGetActiveForPlayer(PlayerId, out var active)); Assert.Equal(expectedInstanceId, active.ContractInstanceId); } }