using ChatBot.Models.Configuration; using ChatBot.Models.Configuration.Validators; using FluentAssertions; namespace ChatBot.Tests.Configuration.Validators; public class AISettingsValidatorTests { private readonly AISettingsValidator _validator = new(); [Fact] public void Validate_ShouldReturnSuccess_WhenSettingsAreValid() { // Arrange var settings = new AISettings { Temperature = 0.7, SystemPromptPath = "Prompts/system-prompt.txt", MaxRetryAttempts = 3, RetryDelayMs = 1000, MaxRetryDelayMs = 10000, EnableExponentialBackoff = true, RequestTimeoutSeconds = 30, EnableHistoryCompression = true, CompressionThreshold = 10, CompressionTarget = 5, MinMessageLengthForSummarization = 50, MaxSummarizedMessageLength = 200, CompressionTimeoutSeconds = 15, StatusCheckTimeoutSeconds = 5, }; // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeTrue(); } [Fact] public void Validate_ShouldReturnFailure_WhenTemperatureIsInvalid() { // Arrange var settings = new AISettings { Temperature = 3.0, // Invalid: > 2.0 SystemPromptPath = "Prompts/system-prompt.txt", MaxRetryAttempts = 3, RetryDelayMs = 1000, MaxRetryDelayMs = 10000, EnableExponentialBackoff = true, RequestTimeoutSeconds = 30, EnableHistoryCompression = true, CompressionThreshold = 10, CompressionTarget = 5, MinMessageLengthForSummarization = 50, MaxSummarizedMessageLength = 200, CompressionTimeoutSeconds = 15, StatusCheckTimeoutSeconds = 5, }; // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeFalse(); result .Failures.Should() .Contain(f => f.Contains("Temperature must be between 0.0 and 2.0")); } [Fact] public void Validate_ShouldReturnFailure_WhenSystemPromptPathIsEmpty() { // Arrange var settings = new AISettings { Temperature = 0.7, SystemPromptPath = "", // Invalid: empty MaxRetryAttempts = 3, RetryDelayMs = 1000, MaxRetryDelayMs = 10000, EnableExponentialBackoff = true, RequestTimeoutSeconds = 30, EnableHistoryCompression = true, CompressionThreshold = 10, CompressionTarget = 5, MinMessageLengthForSummarization = 50, MaxSummarizedMessageLength = 200, CompressionTimeoutSeconds = 15, StatusCheckTimeoutSeconds = 5, }; // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeFalse(); result.Failures.Should().Contain(f => f.Contains("System prompt path cannot be empty")); } [Fact] public void Validate_ShouldReturnFailure_WhenMaxRetryAttemptsIsInvalid() { // Arrange var settings = new AISettings { Temperature = 0.7, SystemPromptPath = "Prompts/system-prompt.txt", MaxRetryAttempts = 15, // Invalid: > 10 RetryDelayMs = 1000, MaxRetryDelayMs = 10000, EnableExponentialBackoff = true, RequestTimeoutSeconds = 30, EnableHistoryCompression = true, CompressionThreshold = 10, CompressionTarget = 5, MinMessageLengthForSummarization = 50, MaxSummarizedMessageLength = 200, CompressionTimeoutSeconds = 15, StatusCheckTimeoutSeconds = 5, }; // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeFalse(); result.Failures.Should().Contain(f => f.Contains("Max retry attempts cannot exceed 10")); } [Fact] public void Validate_ShouldReturnFailure_WhenCompressionSettingsAreInvalid() { // Arrange var settings = new AISettings { Temperature = 0.7, SystemPromptPath = "Prompts/system-prompt.txt", MaxRetryAttempts = 3, RetryDelayMs = 1000, MaxRetryDelayMs = 10000, EnableExponentialBackoff = true, RequestTimeoutSeconds = 30, EnableHistoryCompression = true, CompressionThreshold = 5, // Invalid: same as target CompressionTarget = 5, MinMessageLengthForSummarization = 50, MaxSummarizedMessageLength = 200, CompressionTimeoutSeconds = 15, StatusCheckTimeoutSeconds = 5, }; // Act var result = _validator.Validate(null, settings); // Assert result.Succeeded.Should().BeFalse(); result .Failures.Should() .Contain(f => f.Contains("Compression target must be less than compression threshold")); } }