diff --git a/tests/TarninaHub.Tests/Matchmaking/MatchmakingLlmTests.cs b/tests/TarninaHub.Tests/Matchmaking/MatchmakingLlmTests.cs new file mode 100644 index 0000000..54a5c8b --- /dev/null +++ b/tests/TarninaHub.Tests/Matchmaking/MatchmakingLlmTests.cs @@ -0,0 +1,78 @@ +using TarninaHub.Application.Matchmaking; +using TarninaHub.Infrastructure.Llm; + +namespace TarninaHub.Tests.Matchmaking; + +public class MatchmakingLlmTests +{ + [Fact] + public void MatchScoring_ReturnsZeroWhenUnavailable() + { + Assert.Equal(0, MatchScoring.Combine(0.9, challengeMatch: true, locationMatch: true, available: false)); + } + + [Fact] + public void MatchScoring_AppliesContextBoostsAndClamps() + { + var baseScore = MatchScoring.Combine(0.5, challengeMatch: false, locationMatch: false, available: true); + var boosted = MatchScoring.Combine(0.5, challengeMatch: true, locationMatch: true, available: true); + var clamped = MatchScoring.Combine(0.98, challengeMatch: true, locationMatch: true, available: true); + + Assert.Equal(0.5, baseScore, precision: 5); + Assert.Equal(0.65, boosted, precision: 5); + Assert.Equal(1.0, clamped, precision: 5); + } + + [Fact] + public void RationaleBuilder_MentionsContextAndScore() + { + var strong = RationaleBuilder.Build(challengeMatch: true, locationMatch: true, score: 0.4); + var weak = RationaleBuilder.Build(challengeMatch: false, locationMatch: false, score: 0.1); + + Assert.Contains("obszar", strong); + Assert.Contains("lokalizacja", strong); + Assert.Contains("wysoka", strong); + Assert.Contains("semantyczna", weak); + } + + [Fact] + public void MatchPromptBuilder_IncludesProblemAndInnovation() + { + var prompt = MatchPromptBuilder.BuildExplanation( + "Brak miejsc spotkań", + "Seniorzy są samotni", + "social_challenge:seniorzy", + "Klub sąsiedzki", + "Miejsce spotkań", + "pilot", + 0.42); + + Assert.Contains("Brak miejsc spotkań", prompt.User); + Assert.Contains("Klub sąsiedzki", prompt.User); + Assert.Contains("pilot", prompt.User); + Assert.False(string.IsNullOrWhiteSpace(prompt.System)); + } + + [Fact] + public async Task NullLlmProvider_IsNotConfiguredAndReturnsNull() + { + var provider = new NullLlmProvider(); + + Assert.False(provider.IsConfigured); + Assert.Null(await provider.CompleteAsync("s", "u", CancellationToken.None)); + } + + [Fact] + public async Task InMemoryLlmRequestLimiter_EnforcesWindow() + { + var limiter = new InMemoryLlmRequestLimiter(maxRequestsPerMinute: 2, window: TimeSpan.FromMilliseconds(60)); + + Assert.True(limiter.TryAcquire()); + Assert.True(limiter.TryAcquire()); + Assert.False(limiter.TryAcquire()); + + await Task.Delay(90); + + Assert.True(limiter.TryAcquire()); + } +}