add tests
This commit is contained in:
693
ChatBot.Tests/Models/AISettingsTests.cs
Normal file
693
ChatBot.Tests/Models/AISettingsTests.cs
Normal file
@@ -0,0 +1,693 @@
|
|||||||
|
using ChatBot.Models.Configuration;
|
||||||
|
using FluentAssertions;
|
||||||
|
|
||||||
|
namespace ChatBot.Tests.Models;
|
||||||
|
|
||||||
|
public class AISettingsTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_ShouldInitializePropertiesWithDefaultValues()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Temperature.Should().Be(0.7);
|
||||||
|
settings.SystemPromptPath.Should().Be("Prompts/system-prompt.txt");
|
||||||
|
settings.SystemPrompt.Should().Be(string.Empty);
|
||||||
|
settings.MaxRetryAttempts.Should().Be(3);
|
||||||
|
settings.RetryDelayMs.Should().Be(1000);
|
||||||
|
settings.RequestTimeoutSeconds.Should().Be(60);
|
||||||
|
settings.EnableHistoryCompression.Should().BeTrue();
|
||||||
|
settings.CompressionThreshold.Should().Be(20);
|
||||||
|
settings.CompressionTarget.Should().Be(10);
|
||||||
|
settings.MinMessageLengthForSummarization.Should().Be(50);
|
||||||
|
settings.MaxSummarizedMessageLength.Should().Be(200);
|
||||||
|
settings.EnableExponentialBackoff.Should().BeTrue();
|
||||||
|
settings.MaxRetryDelayMs.Should().Be(30000);
|
||||||
|
settings.CompressionTimeoutSeconds.Should().Be(30);
|
||||||
|
settings.StatusCheckTimeoutSeconds.Should().Be(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Temperature_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
var expectedTemperature = 1.5;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Temperature = expectedTemperature;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Temperature.Should().Be(expectedTemperature);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SystemPromptPath_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
var expectedPath = "Custom/prompt.txt";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.SystemPromptPath = expectedPath;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.SystemPromptPath.Should().Be(expectedPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SystemPrompt_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
var expectedPrompt = "You are a helpful assistant.";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.SystemPrompt = expectedPrompt;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.SystemPrompt.Should().Be(expectedPrompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MaxRetryAttempts_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
var expectedAttempts = 5;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.MaxRetryAttempts = expectedAttempts;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.MaxRetryAttempts.Should().Be(expectedAttempts);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RetryDelayMs_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
var expectedDelay = 2000;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.RetryDelayMs = expectedDelay;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.RetryDelayMs.Should().Be(expectedDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RequestTimeoutSeconds_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
var expectedTimeout = 120;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.RequestTimeoutSeconds = expectedTimeout;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.RequestTimeoutSeconds.Should().Be(expectedTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void EnableHistoryCompression_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.EnableHistoryCompression = false;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.EnableHistoryCompression.Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CompressionThreshold_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
var expectedThreshold = 50;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.CompressionThreshold = expectedThreshold;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.CompressionThreshold.Should().Be(expectedThreshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CompressionTarget_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
var expectedTarget = 15;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.CompressionTarget = expectedTarget;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.CompressionTarget.Should().Be(expectedTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MinMessageLengthForSummarization_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
var expectedLength = 100;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.MinMessageLengthForSummarization = expectedLength;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.MinMessageLengthForSummarization.Should().Be(expectedLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MaxSummarizedMessageLength_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
var expectedLength = 300;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.MaxSummarizedMessageLength = expectedLength;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.MaxSummarizedMessageLength.Should().Be(expectedLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void EnableExponentialBackoff_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.EnableExponentialBackoff = false;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.EnableExponentialBackoff.Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MaxRetryDelayMs_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
var expectedDelay = 60000;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.MaxRetryDelayMs = expectedDelay;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.MaxRetryDelayMs.Should().Be(expectedDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CompressionTimeoutSeconds_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
var expectedTimeout = 60;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.CompressionTimeoutSeconds = expectedTimeout;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.CompressionTimeoutSeconds.Should().Be(expectedTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void StatusCheckTimeoutSeconds_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
var expectedTimeout = 20;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.StatusCheckTimeoutSeconds = expectedTimeout;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.StatusCheckTimeoutSeconds.Should().Be(expectedTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0.0)]
|
||||||
|
[InlineData(0.5)]
|
||||||
|
[InlineData(1.0)]
|
||||||
|
[InlineData(1.5)]
|
||||||
|
[InlineData(2.0)]
|
||||||
|
public void Temperature_ShouldAcceptValidRange(double temperature)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Temperature = temperature;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Temperature.Should().Be(temperature);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(-1.0)]
|
||||||
|
[InlineData(2.5)]
|
||||||
|
[InlineData(10.0)]
|
||||||
|
public void Temperature_ShouldAcceptOutOfRangeValues(double temperature)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Temperature = temperature;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Temperature.Should().Be(temperature);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("")]
|
||||||
|
[InlineData("prompt.txt")]
|
||||||
|
[InlineData("Custom/path/prompt.txt")]
|
||||||
|
[InlineData("C:\\Windows\\System32\\prompt.txt")]
|
||||||
|
[InlineData("/usr/local/bin/prompt.txt")]
|
||||||
|
public void SystemPromptPath_ShouldAcceptVariousPaths(string path)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.SystemPromptPath = path;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.SystemPromptPath.Should().Be(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("")]
|
||||||
|
[InlineData("Short prompt")]
|
||||||
|
[InlineData(
|
||||||
|
"A very long system prompt that contains detailed instructions for the AI assistant on how to behave and respond to user queries in a helpful and informative manner."
|
||||||
|
)]
|
||||||
|
public void SystemPrompt_ShouldAcceptVariousContent(string prompt)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.SystemPrompt = prompt;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.SystemPrompt.Should().Be(prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0)]
|
||||||
|
[InlineData(1)]
|
||||||
|
[InlineData(5)]
|
||||||
|
[InlineData(10)]
|
||||||
|
[InlineData(int.MaxValue)]
|
||||||
|
public void MaxRetryAttempts_ShouldAcceptVariousValues(int attempts)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.MaxRetryAttempts = attempts;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.MaxRetryAttempts.Should().Be(attempts);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0)]
|
||||||
|
[InlineData(100)]
|
||||||
|
[InlineData(1000)]
|
||||||
|
[InlineData(5000)]
|
||||||
|
[InlineData(int.MaxValue)]
|
||||||
|
public void RetryDelayMs_ShouldAcceptVariousValues(int delay)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.RetryDelayMs = delay;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.RetryDelayMs.Should().Be(delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(1)]
|
||||||
|
[InlineData(30)]
|
||||||
|
[InlineData(60)]
|
||||||
|
[InlineData(300)]
|
||||||
|
[InlineData(int.MaxValue)]
|
||||||
|
public void RequestTimeoutSeconds_ShouldAcceptVariousValues(int timeout)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.RequestTimeoutSeconds = timeout;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.RequestTimeoutSeconds.Should().Be(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(true)]
|
||||||
|
[InlineData(false)]
|
||||||
|
public void EnableHistoryCompression_ShouldAcceptBooleanValues(bool enabled)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.EnableHistoryCompression = enabled;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.EnableHistoryCompression.Should().Be(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0)]
|
||||||
|
[InlineData(1)]
|
||||||
|
[InlineData(10)]
|
||||||
|
[InlineData(50)]
|
||||||
|
[InlineData(100)]
|
||||||
|
[InlineData(int.MaxValue)]
|
||||||
|
public void CompressionThreshold_ShouldAcceptVariousValues(int threshold)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.CompressionThreshold = threshold;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.CompressionThreshold.Should().Be(threshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0)]
|
||||||
|
[InlineData(1)]
|
||||||
|
[InlineData(5)]
|
||||||
|
[InlineData(20)]
|
||||||
|
[InlineData(100)]
|
||||||
|
[InlineData(int.MaxValue)]
|
||||||
|
public void CompressionTarget_ShouldAcceptVariousValues(int target)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.CompressionTarget = target;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.CompressionTarget.Should().Be(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0)]
|
||||||
|
[InlineData(10)]
|
||||||
|
[InlineData(50)]
|
||||||
|
[InlineData(100)]
|
||||||
|
[InlineData(1000)]
|
||||||
|
[InlineData(int.MaxValue)]
|
||||||
|
public void MinMessageLengthForSummarization_ShouldAcceptVariousValues(int length)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.MinMessageLengthForSummarization = length;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.MinMessageLengthForSummarization.Should().Be(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0)]
|
||||||
|
[InlineData(50)]
|
||||||
|
[InlineData(200)]
|
||||||
|
[InlineData(500)]
|
||||||
|
[InlineData(1000)]
|
||||||
|
[InlineData(int.MaxValue)]
|
||||||
|
public void MaxSummarizedMessageLength_ShouldAcceptVariousValues(int length)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.MaxSummarizedMessageLength = length;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.MaxSummarizedMessageLength.Should().Be(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(true)]
|
||||||
|
[InlineData(false)]
|
||||||
|
public void EnableExponentialBackoff_ShouldAcceptBooleanValues(bool enabled)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.EnableExponentialBackoff = enabled;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.EnableExponentialBackoff.Should().Be(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0)]
|
||||||
|
[InlineData(1000)]
|
||||||
|
[InlineData(30000)]
|
||||||
|
[InlineData(60000)]
|
||||||
|
[InlineData(int.MaxValue)]
|
||||||
|
public void MaxRetryDelayMs_ShouldAcceptVariousValues(int delay)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.MaxRetryDelayMs = delay;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.MaxRetryDelayMs.Should().Be(delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(1)]
|
||||||
|
[InlineData(10)]
|
||||||
|
[InlineData(30)]
|
||||||
|
[InlineData(60)]
|
||||||
|
[InlineData(300)]
|
||||||
|
[InlineData(int.MaxValue)]
|
||||||
|
public void CompressionTimeoutSeconds_ShouldAcceptVariousValues(int timeout)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.CompressionTimeoutSeconds = timeout;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.CompressionTimeoutSeconds.Should().Be(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(1)]
|
||||||
|
[InlineData(5)]
|
||||||
|
[InlineData(10)]
|
||||||
|
[InlineData(30)]
|
||||||
|
[InlineData(60)]
|
||||||
|
[InlineData(int.MaxValue)]
|
||||||
|
public void StatusCheckTimeoutSeconds_ShouldAcceptVariousValues(int timeout)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.StatusCheckTimeoutSeconds = timeout;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.StatusCheckTimeoutSeconds.Should().Be(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AllProperties_ShouldBeMutable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Temperature = 1.2;
|
||||||
|
settings.SystemPromptPath = "custom/prompt.txt";
|
||||||
|
settings.SystemPrompt = "Custom system prompt";
|
||||||
|
settings.MaxRetryAttempts = 5;
|
||||||
|
settings.RetryDelayMs = 2000;
|
||||||
|
settings.RequestTimeoutSeconds = 120;
|
||||||
|
settings.EnableHistoryCompression = false;
|
||||||
|
settings.CompressionThreshold = 50;
|
||||||
|
settings.CompressionTarget = 15;
|
||||||
|
settings.MinMessageLengthForSummarization = 100;
|
||||||
|
settings.MaxSummarizedMessageLength = 300;
|
||||||
|
settings.EnableExponentialBackoff = false;
|
||||||
|
settings.MaxRetryDelayMs = 60000;
|
||||||
|
settings.CompressionTimeoutSeconds = 60;
|
||||||
|
settings.StatusCheckTimeoutSeconds = 20;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Temperature.Should().Be(1.2);
|
||||||
|
settings.SystemPromptPath.Should().Be("custom/prompt.txt");
|
||||||
|
settings.SystemPrompt.Should().Be("Custom system prompt");
|
||||||
|
settings.MaxRetryAttempts.Should().Be(5);
|
||||||
|
settings.RetryDelayMs.Should().Be(2000);
|
||||||
|
settings.RequestTimeoutSeconds.Should().Be(120);
|
||||||
|
settings.EnableHistoryCompression.Should().BeFalse();
|
||||||
|
settings.CompressionThreshold.Should().Be(50);
|
||||||
|
settings.CompressionTarget.Should().Be(15);
|
||||||
|
settings.MinMessageLengthForSummarization.Should().Be(100);
|
||||||
|
settings.MaxSummarizedMessageLength.Should().Be(300);
|
||||||
|
settings.EnableExponentialBackoff.Should().BeFalse();
|
||||||
|
settings.MaxRetryDelayMs.Should().Be(60000);
|
||||||
|
settings.CompressionTimeoutSeconds.Should().Be(60);
|
||||||
|
settings.StatusCheckTimeoutSeconds.Should().Be(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportHighTemperature()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Temperature = 2.0;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Temperature.Should().Be(2.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportLowTemperature()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Temperature = 0.0;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Temperature.Should().Be(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportDisabledCompression()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.EnableHistoryCompression = false;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.EnableHistoryCompression.Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportDisabledExponentialBackoff()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.EnableExponentialBackoff = false;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.EnableExponentialBackoff.Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportZeroRetryAttempts()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.MaxRetryAttempts = 0;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.MaxRetryAttempts.Should().Be(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportZeroDelays()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.RetryDelayMs = 0;
|
||||||
|
settings.MaxRetryDelayMs = 0;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.RetryDelayMs.Should().Be(0);
|
||||||
|
settings.MaxRetryDelayMs.Should().Be(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportZeroThresholds()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.CompressionThreshold = 0;
|
||||||
|
settings.CompressionTarget = 0;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.CompressionThreshold.Should().Be(0);
|
||||||
|
settings.CompressionTarget.Should().Be(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportZeroLengths()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.MinMessageLengthForSummarization = 0;
|
||||||
|
settings.MaxSummarizedMessageLength = 0;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.MinMessageLengthForSummarization.Should().Be(0);
|
||||||
|
settings.MaxSummarizedMessageLength.Should().Be(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportZeroTimeouts()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AISettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.RequestTimeoutSeconds = 0;
|
||||||
|
settings.CompressionTimeoutSeconds = 0;
|
||||||
|
settings.StatusCheckTimeoutSeconds = 0;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.RequestTimeoutSeconds.Should().Be(0);
|
||||||
|
settings.CompressionTimeoutSeconds.Should().Be(0);
|
||||||
|
settings.StatusCheckTimeoutSeconds.Should().Be(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
422
ChatBot.Tests/Models/ChatMessageEntityTests.cs
Normal file
422
ChatBot.Tests/Models/ChatMessageEntityTests.cs
Normal file
@@ -0,0 +1,422 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using ChatBot.Models.Entities;
|
||||||
|
using FluentAssertions;
|
||||||
|
|
||||||
|
namespace ChatBot.Tests.Models;
|
||||||
|
|
||||||
|
public class ChatMessageEntityTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_ShouldInitializePropertiesWithDefaultValues()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var entity = new ChatMessageEntity();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.Id.Should().Be(0);
|
||||||
|
entity.SessionId.Should().Be(0);
|
||||||
|
entity.Content.Should().Be(string.Empty);
|
||||||
|
entity.Role.Should().Be(string.Empty);
|
||||||
|
entity.CreatedAt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(1));
|
||||||
|
entity.MessageOrder.Should().Be(0);
|
||||||
|
entity.Session.Should().BeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Id_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatMessageEntity();
|
||||||
|
var expectedId = 123;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.Id = expectedId;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.Id.Should().Be(expectedId);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SessionId_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatMessageEntity();
|
||||||
|
var expectedSessionId = 456;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.SessionId = expectedSessionId;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.SessionId.Should().Be(expectedSessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Content_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatMessageEntity();
|
||||||
|
var expectedContent = "Hello, world!";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.Content = expectedContent;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.Content.Should().Be(expectedContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Role_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatMessageEntity();
|
||||||
|
var expectedRole = "user";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.Role = expectedRole;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.Role.Should().Be(expectedRole);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CreatedAt_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatMessageEntity();
|
||||||
|
var expectedDate = DateTime.UtcNow.AddDays(-1);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.CreatedAt = expectedDate;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.CreatedAt.Should().Be(expectedDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MessageOrder_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatMessageEntity();
|
||||||
|
var expectedOrder = 5;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.MessageOrder = expectedOrder;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.MessageOrder.Should().Be(expectedOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Session_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatMessageEntity();
|
||||||
|
var expectedSession = new ChatSessionEntity();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.Session = expectedSession;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.Session.Should().Be(expectedSession);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("user")]
|
||||||
|
[InlineData("assistant")]
|
||||||
|
[InlineData("system")]
|
||||||
|
[InlineData("function")]
|
||||||
|
public void Role_ShouldAcceptValidRoles(string role)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatMessageEntity();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.Role = role;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.Role.Should().Be(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("")]
|
||||||
|
[InlineData("a")]
|
||||||
|
[InlineData("very long role name that exceeds limit")]
|
||||||
|
public void Role_ShouldAcceptVariousLengths(string role)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatMessageEntity();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.Role = role;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.Role.Should().Be(role);
|
||||||
|
entity.Role.Length.Should().Be(role.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("")]
|
||||||
|
[InlineData("Short message")]
|
||||||
|
[InlineData(
|
||||||
|
"A very long message that contains a lot of text and should still be valid for the content field"
|
||||||
|
)]
|
||||||
|
public void Content_ShouldAcceptVariousLengths(string content)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatMessageEntity();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.Content = content;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.Content.Should().Be(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CreatedAt_ShouldDefaultToCurrentUtcTime()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var beforeCreation = DateTime.UtcNow;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var entity = new ChatMessageEntity();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.CreatedAt.Should().BeOnOrAfter(beforeCreation);
|
||||||
|
entity.CreatedAt.Should().BeOnOrBefore(DateTime.UtcNow);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AllProperties_ShouldBeMutable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatMessageEntity();
|
||||||
|
var session = new ChatSessionEntity();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.Id = 1;
|
||||||
|
entity.SessionId = 2;
|
||||||
|
entity.Content = "Test content";
|
||||||
|
entity.Role = "user";
|
||||||
|
entity.CreatedAt = DateTime.UtcNow.AddDays(-1);
|
||||||
|
entity.MessageOrder = 3;
|
||||||
|
entity.Session = session;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.Id.Should().Be(1);
|
||||||
|
entity.SessionId.Should().Be(2);
|
||||||
|
entity.Content.Should().Be("Test content");
|
||||||
|
entity.Role.Should().Be("user");
|
||||||
|
entity.CreatedAt.Should().BeCloseTo(DateTime.UtcNow.AddDays(-1), TimeSpan.FromSeconds(1));
|
||||||
|
entity.MessageOrder.Should().Be(3);
|
||||||
|
entity.Session.Should().Be(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Entity_ShouldHaveCorrectTableAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entityType = typeof(ChatMessageEntity);
|
||||||
|
var tableAttribute =
|
||||||
|
entityType.GetCustomAttributes(typeof(TableAttribute), false).FirstOrDefault()
|
||||||
|
as TableAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
tableAttribute.Should().NotBeNull();
|
||||||
|
tableAttribute!.Name.Should().Be("chat_messages");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Id_ShouldHaveKeyAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatMessageEntity).GetProperty(nameof(ChatMessageEntity.Id));
|
||||||
|
var keyAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(KeyAttribute), false).FirstOrDefault()
|
||||||
|
as KeyAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
keyAttribute.Should().NotBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Id_ShouldHaveColumnAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatMessageEntity).GetProperty(nameof(ChatMessageEntity.Id));
|
||||||
|
var columnAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(ColumnAttribute), false).FirstOrDefault()
|
||||||
|
as ColumnAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
columnAttribute.Should().NotBeNull();
|
||||||
|
columnAttribute!.Name.Should().Be("id");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SessionId_ShouldHaveRequiredAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatMessageEntity).GetProperty(nameof(ChatMessageEntity.SessionId));
|
||||||
|
var requiredAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(RequiredAttribute), false).FirstOrDefault()
|
||||||
|
as RequiredAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
requiredAttribute.Should().NotBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SessionId_ShouldHaveColumnAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatMessageEntity).GetProperty(nameof(ChatMessageEntity.SessionId));
|
||||||
|
var columnAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(ColumnAttribute), false).FirstOrDefault()
|
||||||
|
as ColumnAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
columnAttribute.Should().NotBeNull();
|
||||||
|
columnAttribute!.Name.Should().Be("session_id");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Content_ShouldHaveRequiredAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatMessageEntity).GetProperty(nameof(ChatMessageEntity.Content));
|
||||||
|
var requiredAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(RequiredAttribute), false).FirstOrDefault()
|
||||||
|
as RequiredAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
requiredAttribute.Should().NotBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Content_ShouldHaveStringLengthAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatMessageEntity).GetProperty(nameof(ChatMessageEntity.Content));
|
||||||
|
var stringLengthAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(StringLengthAttribute), false).FirstOrDefault()
|
||||||
|
as StringLengthAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
stringLengthAttribute.Should().NotBeNull();
|
||||||
|
stringLengthAttribute!.MaximumLength.Should().Be(10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Content_ShouldHaveColumnAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatMessageEntity).GetProperty(nameof(ChatMessageEntity.Content));
|
||||||
|
var columnAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(ColumnAttribute), false).FirstOrDefault()
|
||||||
|
as ColumnAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
columnAttribute.Should().NotBeNull();
|
||||||
|
columnAttribute!.Name.Should().Be("content");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Role_ShouldHaveRequiredAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatMessageEntity).GetProperty(nameof(ChatMessageEntity.Role));
|
||||||
|
var requiredAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(RequiredAttribute), false).FirstOrDefault()
|
||||||
|
as RequiredAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
requiredAttribute.Should().NotBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Role_ShouldHaveStringLengthAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatMessageEntity).GetProperty(nameof(ChatMessageEntity.Role));
|
||||||
|
var stringLengthAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(StringLengthAttribute), false).FirstOrDefault()
|
||||||
|
as StringLengthAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
stringLengthAttribute.Should().NotBeNull();
|
||||||
|
stringLengthAttribute!.MaximumLength.Should().Be(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Role_ShouldHaveColumnAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatMessageEntity).GetProperty(nameof(ChatMessageEntity.Role));
|
||||||
|
var columnAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(ColumnAttribute), false).FirstOrDefault()
|
||||||
|
as ColumnAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
columnAttribute.Should().NotBeNull();
|
||||||
|
columnAttribute!.Name.Should().Be("role");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CreatedAt_ShouldHaveRequiredAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatMessageEntity).GetProperty(nameof(ChatMessageEntity.CreatedAt));
|
||||||
|
var requiredAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(RequiredAttribute), false).FirstOrDefault()
|
||||||
|
as RequiredAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
requiredAttribute.Should().NotBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CreatedAt_ShouldHaveColumnAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatMessageEntity).GetProperty(nameof(ChatMessageEntity.CreatedAt));
|
||||||
|
var columnAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(ColumnAttribute), false).FirstOrDefault()
|
||||||
|
as ColumnAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
columnAttribute.Should().NotBeNull();
|
||||||
|
columnAttribute!.Name.Should().Be("created_at");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MessageOrder_ShouldHaveColumnAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatMessageEntity).GetProperty(
|
||||||
|
nameof(ChatMessageEntity.MessageOrder)
|
||||||
|
);
|
||||||
|
var columnAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(ColumnAttribute), false).FirstOrDefault()
|
||||||
|
as ColumnAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
columnAttribute.Should().NotBeNull();
|
||||||
|
columnAttribute!.Name.Should().Be("message_order");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Session_ShouldHaveForeignKeyAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatMessageEntity).GetProperty(nameof(ChatMessageEntity.Session));
|
||||||
|
var foreignKeyAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(ForeignKeyAttribute), false).FirstOrDefault()
|
||||||
|
as ForeignKeyAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
foreignKeyAttribute.Should().NotBeNull();
|
||||||
|
foreignKeyAttribute!.Name.Should().Be("SessionId");
|
||||||
|
}
|
||||||
|
}
|
||||||
363
ChatBot.Tests/Models/ChatMessageTests.cs
Normal file
363
ChatBot.Tests/Models/ChatMessageTests.cs
Normal file
@@ -0,0 +1,363 @@
|
|||||||
|
using ChatBot.Models.Dto;
|
||||||
|
using FluentAssertions;
|
||||||
|
using OllamaSharp.Models.Chat;
|
||||||
|
|
||||||
|
namespace ChatBot.Tests.Models;
|
||||||
|
|
||||||
|
public class ChatMessageTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_WithRequiredProperties_ShouldInitializeCorrectly()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var content = "Hello, world!";
|
||||||
|
var role = ChatRole.User;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var message = new ChatMessage { Content = content, Role = role };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
message.Content.Should().Be(content);
|
||||||
|
message.Role.Should().Be(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Content_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var message = new ChatMessage { Content = "Initial content", Role = ChatRole.User };
|
||||||
|
var newContent = "Updated content";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
message.Content = newContent;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
message.Content.Should().Be(newContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Role_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var message = new ChatMessage { Content = "Test content", Role = ChatRole.User };
|
||||||
|
var newRole = ChatRole.Assistant;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
message.Role = newRole;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
message.Role.Should().Be(newRole);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("")]
|
||||||
|
[InlineData("Short message")]
|
||||||
|
[InlineData(
|
||||||
|
"A very long message that contains a lot of text and should still be valid for the content field"
|
||||||
|
)]
|
||||||
|
[InlineData("Message with special characters: !@#$%^&*()_+-=[]{}|;':\",./<>?")]
|
||||||
|
[InlineData("Message with unicode: Привет мир! 🌍")]
|
||||||
|
[InlineData("Message with newlines:\nLine 1\nLine 2")]
|
||||||
|
[InlineData("Message with tabs:\tTab content")]
|
||||||
|
public void Content_ShouldAcceptVariousValues(string content)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var message = new ChatMessage { Content = "Initial", Role = ChatRole.User };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
message.Content = content;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
message.Content.Should().Be(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Role_ShouldAcceptSystemRole()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var message = new ChatMessage { Content = "Test content", Role = ChatRole.User };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
message.Role = ChatRole.System;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
message.Role.Should().Be(ChatRole.System);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Role_ShouldAcceptUserRole()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var message = new ChatMessage { Content = "Test content", Role = ChatRole.System };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
message.Role = ChatRole.User;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
message.Role.Should().Be(ChatRole.User);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Role_ShouldAcceptAssistantRole()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var message = new ChatMessage { Content = "Test content", Role = ChatRole.User };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
message.Role = ChatRole.Assistant;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
message.Role.Should().Be(ChatRole.Assistant);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AllProperties_ShouldBeMutable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var message = new ChatMessage { Content = "Initial content", Role = ChatRole.User };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
message.Content = "Updated content";
|
||||||
|
message.Role = ChatRole.Assistant;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
message.Content.Should().Be("Updated content");
|
||||||
|
message.Role.Should().Be(ChatRole.Assistant);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Message_ShouldSupportSystemRole()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var content = "You are a helpful assistant.";
|
||||||
|
var role = ChatRole.System;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var message = new ChatMessage { Content = content, Role = role };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
message.Content.Should().Be(content);
|
||||||
|
message.Role.Should().Be(ChatRole.System);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Message_ShouldSupportUserRole()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var content = "Hello, how are you?";
|
||||||
|
var role = ChatRole.User;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var message = new ChatMessage { Content = content, Role = role };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
message.Content.Should().Be(content);
|
||||||
|
message.Role.Should().Be(ChatRole.User);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Message_ShouldSupportAssistantRole()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var content = "I'm doing well, thank you!";
|
||||||
|
var role = ChatRole.Assistant;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var message = new ChatMessage { Content = content, Role = role };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
message.Content.Should().Be(content);
|
||||||
|
message.Role.Should().Be(ChatRole.Assistant);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Message_WithEmptyContent_ShouldBeValid()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var content = "";
|
||||||
|
var role = ChatRole.User;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var message = new ChatMessage { Content = content, Role = role };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
message.Content.Should().Be(content);
|
||||||
|
message.Role.Should().Be(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Message_WithWhitespaceContent_ShouldBeValid()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var content = " \t\n ";
|
||||||
|
var role = ChatRole.User;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var message = new ChatMessage { Content = content, Role = role };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
message.Content.Should().Be(content);
|
||||||
|
message.Role.Should().Be(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Message_WithVeryLongContent_ShouldBeValid()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var content = new string('A', 10000); // 10,000 characters
|
||||||
|
var role = ChatRole.Assistant;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var message = new ChatMessage { Content = content, Role = role };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
message.Content.Should().Be(content);
|
||||||
|
message.Role.Should().Be(role);
|
||||||
|
message.Content.Length.Should().Be(10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Message_WithJsonContent_ShouldBeValid()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var content = """{"key": "value", "number": 123, "array": [1, 2, 3]}""";
|
||||||
|
var role = ChatRole.Assistant;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var message = new ChatMessage { Content = content, Role = role };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
message.Content.Should().Be(content);
|
||||||
|
message.Role.Should().Be(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Message_WithXmlContent_ShouldBeValid()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var content = "<root><item>value</item></root>";
|
||||||
|
var role = ChatRole.Assistant;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var message = new ChatMessage { Content = content, Role = role };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
message.Content.Should().Be(content);
|
||||||
|
message.Role.Should().Be(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Message_WithMarkdownContent_ShouldBeValid()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var content = "# Header\n\n**Bold text** and *italic text*\n\n- List item 1\n- List item 2";
|
||||||
|
var role = ChatRole.Assistant;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var message = new ChatMessage { Content = content, Role = role };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
message.Content.Should().Be(content);
|
||||||
|
message.Role.Should().Be(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Message_WithCodeContent_ShouldBeValid()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var content = "```csharp\npublic class Test { }\n```";
|
||||||
|
var role = ChatRole.Assistant;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var message = new ChatMessage { Content = content, Role = role };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
message.Content.Should().Be(content);
|
||||||
|
message.Role.Should().Be(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Message_WithDefaultRole_ShouldBeValid()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var content = "Test message";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var message = new ChatMessage { Content = content, Role = default(ChatRole) };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
message.Content.Should().Be(content);
|
||||||
|
message.Role.Should().Be(default(ChatRole));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Message_ShouldBeComparableByContent()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var message1 = new ChatMessage { Content = "Same content", Role = ChatRole.User };
|
||||||
|
var message2 = new ChatMessage { Content = "Same content", Role = ChatRole.Assistant };
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
message1.Content.Should().Be(message2.Content);
|
||||||
|
message1.Role.Should().NotBe(message2.Role);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Message_ShouldBeComparableByRole()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var message1 = new ChatMessage { Content = "Different content 1", Role = ChatRole.User };
|
||||||
|
var message2 = new ChatMessage { Content = "Different content 2", Role = ChatRole.User };
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
message1.Role.Should().Be(message2.Role);
|
||||||
|
message1.Content.Should().NotBe(message2.Content);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Message_ShouldSupportAllRoleTypes()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var systemMessage = new ChatMessage { Content = "System message", Role = ChatRole.System };
|
||||||
|
var userMessage = new ChatMessage { Content = "User message", Role = ChatRole.User };
|
||||||
|
var assistantMessage = new ChatMessage
|
||||||
|
{
|
||||||
|
Content = "Assistant message",
|
||||||
|
Role = ChatRole.Assistant,
|
||||||
|
};
|
||||||
|
// Assert
|
||||||
|
systemMessage.Role.Should().Be(ChatRole.System);
|
||||||
|
userMessage.Role.Should().Be(ChatRole.User);
|
||||||
|
assistantMessage.Role.Should().Be(ChatRole.Assistant);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Message_ShouldHandleSpecialCharacters()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var content = "Special chars: !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
|
||||||
|
var role = ChatRole.User;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var message = new ChatMessage { Content = content, Role = role };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
message.Content.Should().Be(content);
|
||||||
|
message.Role.Should().Be(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Message_ShouldHandleUnicodeCharacters()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var content = "Unicode: 中文 العربية русский 日本語 한국어";
|
||||||
|
var role = ChatRole.Assistant;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var message = new ChatMessage { Content = content, Role = role };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
message.Content.Should().Be(content);
|
||||||
|
message.Role.Should().Be(role);
|
||||||
|
}
|
||||||
|
}
|
||||||
637
ChatBot.Tests/Models/ChatSessionEntityTests.cs
Normal file
637
ChatBot.Tests/Models/ChatSessionEntityTests.cs
Normal file
@@ -0,0 +1,637 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using ChatBot.Models.Entities;
|
||||||
|
using FluentAssertions;
|
||||||
|
|
||||||
|
namespace ChatBot.Tests.Models;
|
||||||
|
|
||||||
|
public class ChatSessionEntityTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_ShouldInitializePropertiesWithDefaultValues()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var entity = new ChatSessionEntity();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.Id.Should().Be(0);
|
||||||
|
entity.SessionId.Should().Be(string.Empty);
|
||||||
|
entity.ChatId.Should().Be(0);
|
||||||
|
entity.ChatType.Should().Be("private");
|
||||||
|
entity.ChatTitle.Should().Be(string.Empty);
|
||||||
|
entity.Model.Should().Be(string.Empty);
|
||||||
|
entity.CreatedAt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(1));
|
||||||
|
entity.LastUpdatedAt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(1));
|
||||||
|
entity.MaxHistoryLength.Should().Be(30);
|
||||||
|
entity.Messages.Should().NotBeNull();
|
||||||
|
entity.Messages.Should().BeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Id_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatSessionEntity();
|
||||||
|
var expectedId = 123;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.Id = expectedId;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.Id.Should().Be(expectedId);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SessionId_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatSessionEntity();
|
||||||
|
var expectedSessionId = "session-123";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.SessionId = expectedSessionId;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.SessionId.Should().Be(expectedSessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ChatId_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatSessionEntity();
|
||||||
|
var expectedChatId = 987654321L;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.ChatId = expectedChatId;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.ChatId.Should().Be(expectedChatId);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ChatType_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatSessionEntity();
|
||||||
|
var expectedChatType = "group";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.ChatType = expectedChatType;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.ChatType.Should().Be(expectedChatType);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ChatTitle_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatSessionEntity();
|
||||||
|
var expectedChatTitle = "My Test Group";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.ChatTitle = expectedChatTitle;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.ChatTitle.Should().Be(expectedChatTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Model_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatSessionEntity();
|
||||||
|
var expectedModel = "llama3.1:8b";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.Model = expectedModel;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.Model.Should().Be(expectedModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CreatedAt_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatSessionEntity();
|
||||||
|
var expectedDate = DateTime.UtcNow.AddDays(-1);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.CreatedAt = expectedDate;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.CreatedAt.Should().Be(expectedDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void LastUpdatedAt_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatSessionEntity();
|
||||||
|
var expectedDate = DateTime.UtcNow.AddHours(-2);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.LastUpdatedAt = expectedDate;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.LastUpdatedAt.Should().Be(expectedDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MaxHistoryLength_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatSessionEntity();
|
||||||
|
var expectedLength = 50;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.MaxHistoryLength = expectedLength;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.MaxHistoryLength.Should().Be(expectedLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Messages_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatSessionEntity();
|
||||||
|
var expectedMessages = new List<ChatMessageEntity>
|
||||||
|
{
|
||||||
|
new() { Content = "Test message 1", Role = "user" },
|
||||||
|
new() { Content = "Test message 2", Role = "assistant" },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.Messages = expectedMessages;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.Messages.Should().BeSameAs(expectedMessages);
|
||||||
|
entity.Messages.Should().HaveCount(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("private")]
|
||||||
|
[InlineData("group")]
|
||||||
|
[InlineData("supergroup")]
|
||||||
|
[InlineData("channel")]
|
||||||
|
public void ChatType_ShouldAcceptValidTypes(string chatType)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatSessionEntity();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.ChatType = chatType;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.ChatType.Should().Be(chatType);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("")]
|
||||||
|
[InlineData("a")]
|
||||||
|
[InlineData("very long chat type name")]
|
||||||
|
public void ChatType_ShouldAcceptVariousLengths(string chatType)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatSessionEntity();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.ChatType = chatType;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.ChatType.Should().Be(chatType);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("")]
|
||||||
|
[InlineData("Short title")]
|
||||||
|
[InlineData("A very long chat title that contains a lot of text and should still be valid")]
|
||||||
|
public void ChatTitle_ShouldAcceptVariousLengths(string chatTitle)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatSessionEntity();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.ChatTitle = chatTitle;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.ChatTitle.Should().Be(chatTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("")]
|
||||||
|
[InlineData("llama3.1:8b")]
|
||||||
|
[InlineData("gpt-4")]
|
||||||
|
[InlineData("claude-3-sonnet")]
|
||||||
|
public void Model_ShouldAcceptVariousModels(string model)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatSessionEntity();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.Model = model;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.Model.Should().Be(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("")]
|
||||||
|
[InlineData("session-123")]
|
||||||
|
[InlineData("very-long-session-id-that-exceeds-normal-length")]
|
||||||
|
public void SessionId_ShouldAcceptVariousLengths(string sessionId)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatSessionEntity();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.SessionId = sessionId;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.SessionId.Should().Be(sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0L)]
|
||||||
|
[InlineData(123456789L)]
|
||||||
|
[InlineData(-987654321L)]
|
||||||
|
[InlineData(long.MaxValue)]
|
||||||
|
[InlineData(long.MinValue)]
|
||||||
|
public void ChatId_ShouldAcceptVariousValues(long chatId)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatSessionEntity();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.ChatId = chatId;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.ChatId.Should().Be(chatId);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0)]
|
||||||
|
[InlineData(1)]
|
||||||
|
[InlineData(30)]
|
||||||
|
[InlineData(100)]
|
||||||
|
[InlineData(int.MaxValue)]
|
||||||
|
public void MaxHistoryLength_ShouldAcceptVariousValues(int maxHistoryLength)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatSessionEntity();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.MaxHistoryLength = maxHistoryLength;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.MaxHistoryLength.Should().Be(maxHistoryLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CreatedAt_ShouldDefaultToCurrentUtcTime()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var beforeCreation = DateTime.UtcNow;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var entity = new ChatSessionEntity();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.CreatedAt.Should().BeOnOrAfter(beforeCreation);
|
||||||
|
entity.CreatedAt.Should().BeOnOrBefore(DateTime.UtcNow);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void LastUpdatedAt_ShouldDefaultToCurrentUtcTime()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var beforeCreation = DateTime.UtcNow;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var entity = new ChatSessionEntity();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.LastUpdatedAt.Should().BeOnOrAfter(beforeCreation);
|
||||||
|
entity.LastUpdatedAt.Should().BeOnOrBefore(DateTime.UtcNow);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AllProperties_ShouldBeMutable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entity = new ChatSessionEntity();
|
||||||
|
var messages = new List<ChatMessageEntity>
|
||||||
|
{
|
||||||
|
new() { Content = "Test", Role = "user" },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
entity.Id = 1;
|
||||||
|
entity.SessionId = "test-session";
|
||||||
|
entity.ChatId = 123456789L;
|
||||||
|
entity.ChatType = "group";
|
||||||
|
entity.ChatTitle = "Test Group";
|
||||||
|
entity.Model = "llama3.1:8b";
|
||||||
|
entity.CreatedAt = DateTime.UtcNow.AddDays(-1);
|
||||||
|
entity.LastUpdatedAt = DateTime.UtcNow.AddHours(-1);
|
||||||
|
entity.MaxHistoryLength = 50;
|
||||||
|
entity.Messages = messages;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
entity.Id.Should().Be(1);
|
||||||
|
entity.SessionId.Should().Be("test-session");
|
||||||
|
entity.ChatId.Should().Be(123456789L);
|
||||||
|
entity.ChatType.Should().Be("group");
|
||||||
|
entity.ChatTitle.Should().Be("Test Group");
|
||||||
|
entity.Model.Should().Be("llama3.1:8b");
|
||||||
|
entity.CreatedAt.Should().BeCloseTo(DateTime.UtcNow.AddDays(-1), TimeSpan.FromSeconds(1));
|
||||||
|
entity
|
||||||
|
.LastUpdatedAt.Should()
|
||||||
|
.BeCloseTo(DateTime.UtcNow.AddHours(-1), TimeSpan.FromSeconds(1));
|
||||||
|
entity.MaxHistoryLength.Should().Be(50);
|
||||||
|
entity.Messages.Should().BeSameAs(messages);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Entity_ShouldHaveCorrectTableAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var entityType = typeof(ChatSessionEntity);
|
||||||
|
var tableAttribute =
|
||||||
|
entityType.GetCustomAttributes(typeof(TableAttribute), false).FirstOrDefault()
|
||||||
|
as TableAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
tableAttribute.Should().NotBeNull();
|
||||||
|
tableAttribute!.Name.Should().Be("chat_sessions");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Id_ShouldHaveKeyAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatSessionEntity).GetProperty(nameof(ChatSessionEntity.Id));
|
||||||
|
var keyAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(KeyAttribute), false).FirstOrDefault()
|
||||||
|
as KeyAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
keyAttribute.Should().NotBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Id_ShouldHaveColumnAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatSessionEntity).GetProperty(nameof(ChatSessionEntity.Id));
|
||||||
|
var columnAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(ColumnAttribute), false).FirstOrDefault()
|
||||||
|
as ColumnAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
columnAttribute.Should().NotBeNull();
|
||||||
|
columnAttribute!.Name.Should().Be("id");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SessionId_ShouldHaveRequiredAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatSessionEntity).GetProperty(nameof(ChatSessionEntity.SessionId));
|
||||||
|
var requiredAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(RequiredAttribute), false).FirstOrDefault()
|
||||||
|
as RequiredAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
requiredAttribute.Should().NotBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SessionId_ShouldHaveStringLengthAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatSessionEntity).GetProperty(nameof(ChatSessionEntity.SessionId));
|
||||||
|
var stringLengthAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(StringLengthAttribute), false).FirstOrDefault()
|
||||||
|
as StringLengthAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
stringLengthAttribute.Should().NotBeNull();
|
||||||
|
stringLengthAttribute!.MaximumLength.Should().Be(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SessionId_ShouldHaveColumnAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatSessionEntity).GetProperty(nameof(ChatSessionEntity.SessionId));
|
||||||
|
var columnAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(ColumnAttribute), false).FirstOrDefault()
|
||||||
|
as ColumnAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
columnAttribute.Should().NotBeNull();
|
||||||
|
columnAttribute!.Name.Should().Be("session_id");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ChatId_ShouldHaveRequiredAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatSessionEntity).GetProperty(nameof(ChatSessionEntity.ChatId));
|
||||||
|
var requiredAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(RequiredAttribute), false).FirstOrDefault()
|
||||||
|
as RequiredAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
requiredAttribute.Should().NotBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ChatId_ShouldHaveColumnAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatSessionEntity).GetProperty(nameof(ChatSessionEntity.ChatId));
|
||||||
|
var columnAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(ColumnAttribute), false).FirstOrDefault()
|
||||||
|
as ColumnAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
columnAttribute.Should().NotBeNull();
|
||||||
|
columnAttribute!.Name.Should().Be("chat_id");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ChatType_ShouldHaveRequiredAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatSessionEntity).GetProperty(nameof(ChatSessionEntity.ChatType));
|
||||||
|
var requiredAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(RequiredAttribute), false).FirstOrDefault()
|
||||||
|
as RequiredAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
requiredAttribute.Should().NotBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ChatType_ShouldHaveStringLengthAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatSessionEntity).GetProperty(nameof(ChatSessionEntity.ChatType));
|
||||||
|
var stringLengthAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(StringLengthAttribute), false).FirstOrDefault()
|
||||||
|
as StringLengthAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
stringLengthAttribute.Should().NotBeNull();
|
||||||
|
stringLengthAttribute!.MaximumLength.Should().Be(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ChatType_ShouldHaveColumnAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatSessionEntity).GetProperty(nameof(ChatSessionEntity.ChatType));
|
||||||
|
var columnAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(ColumnAttribute), false).FirstOrDefault()
|
||||||
|
as ColumnAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
columnAttribute.Should().NotBeNull();
|
||||||
|
columnAttribute!.Name.Should().Be("chat_type");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ChatTitle_ShouldHaveStringLengthAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatSessionEntity).GetProperty(nameof(ChatSessionEntity.ChatTitle));
|
||||||
|
var stringLengthAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(StringLengthAttribute), false).FirstOrDefault()
|
||||||
|
as StringLengthAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
stringLengthAttribute.Should().NotBeNull();
|
||||||
|
stringLengthAttribute!.MaximumLength.Should().Be(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ChatTitle_ShouldHaveColumnAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatSessionEntity).GetProperty(nameof(ChatSessionEntity.ChatTitle));
|
||||||
|
var columnAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(ColumnAttribute), false).FirstOrDefault()
|
||||||
|
as ColumnAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
columnAttribute.Should().NotBeNull();
|
||||||
|
columnAttribute!.Name.Should().Be("chat_title");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Model_ShouldHaveStringLengthAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatSessionEntity).GetProperty(nameof(ChatSessionEntity.Model));
|
||||||
|
var stringLengthAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(StringLengthAttribute), false).FirstOrDefault()
|
||||||
|
as StringLengthAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
stringLengthAttribute.Should().NotBeNull();
|
||||||
|
stringLengthAttribute!.MaximumLength.Should().Be(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Model_ShouldHaveColumnAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatSessionEntity).GetProperty(nameof(ChatSessionEntity.Model));
|
||||||
|
var columnAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(ColumnAttribute), false).FirstOrDefault()
|
||||||
|
as ColumnAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
columnAttribute.Should().NotBeNull();
|
||||||
|
columnAttribute!.Name.Should().Be("model");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CreatedAt_ShouldHaveRequiredAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatSessionEntity).GetProperty(nameof(ChatSessionEntity.CreatedAt));
|
||||||
|
var requiredAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(RequiredAttribute), false).FirstOrDefault()
|
||||||
|
as RequiredAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
requiredAttribute.Should().NotBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CreatedAt_ShouldHaveColumnAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatSessionEntity).GetProperty(nameof(ChatSessionEntity.CreatedAt));
|
||||||
|
var columnAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(ColumnAttribute), false).FirstOrDefault()
|
||||||
|
as ColumnAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
columnAttribute.Should().NotBeNull();
|
||||||
|
columnAttribute!.Name.Should().Be("created_at");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void LastUpdatedAt_ShouldHaveRequiredAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatSessionEntity).GetProperty(
|
||||||
|
nameof(ChatSessionEntity.LastUpdatedAt)
|
||||||
|
);
|
||||||
|
var requiredAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(RequiredAttribute), false).FirstOrDefault()
|
||||||
|
as RequiredAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
requiredAttribute.Should().NotBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void LastUpdatedAt_ShouldHaveColumnAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatSessionEntity).GetProperty(
|
||||||
|
nameof(ChatSessionEntity.LastUpdatedAt)
|
||||||
|
);
|
||||||
|
var columnAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(ColumnAttribute), false).FirstOrDefault()
|
||||||
|
as ColumnAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
columnAttribute.Should().NotBeNull();
|
||||||
|
columnAttribute!.Name.Should().Be("last_updated_at");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MaxHistoryLength_ShouldHaveColumnAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var property = typeof(ChatSessionEntity).GetProperty(
|
||||||
|
nameof(ChatSessionEntity.MaxHistoryLength)
|
||||||
|
);
|
||||||
|
var columnAttribute =
|
||||||
|
property?.GetCustomAttributes(typeof(ColumnAttribute), false).FirstOrDefault()
|
||||||
|
as ColumnAttribute;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
columnAttribute.Should().NotBeNull();
|
||||||
|
columnAttribute!.Name.Should().Be("max_history_length");
|
||||||
|
}
|
||||||
|
}
|
||||||
452
ChatBot.Tests/Models/DatabaseSettingsTests.cs
Normal file
452
ChatBot.Tests/Models/DatabaseSettingsTests.cs
Normal file
@@ -0,0 +1,452 @@
|
|||||||
|
using ChatBot.Models.Configuration;
|
||||||
|
using FluentAssertions;
|
||||||
|
|
||||||
|
namespace ChatBot.Tests.Models;
|
||||||
|
|
||||||
|
public class DatabaseSettingsTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_ShouldInitializePropertiesWithDefaultValues()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.ConnectionString.Should().Be(string.Empty);
|
||||||
|
settings.EnableSensitiveDataLogging.Should().BeFalse();
|
||||||
|
settings.CommandTimeout.Should().Be(30);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ConnectionString_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
var expectedConnectionString =
|
||||||
|
"Server=localhost;Database=testdb;User Id=user;Password=testpass;";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.ConnectionString = expectedConnectionString;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.ConnectionString.Should().Be(expectedConnectionString);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void EnableSensitiveDataLogging_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.EnableSensitiveDataLogging = true;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.EnableSensitiveDataLogging.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CommandTimeout_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
var expectedTimeout = 60;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.CommandTimeout = expectedTimeout;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.CommandTimeout.Should().Be(expectedTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("")]
|
||||||
|
[InlineData("Server=localhost;Database=testdb;")]
|
||||||
|
[InlineData("Server=localhost;Port=5432;Database=chatbot;User Id=admin;Password=testpass;")]
|
||||||
|
[InlineData(
|
||||||
|
"Host=localhost;Port=5432;Database=chatbot;Username=admin;Password=testpass;Pooling=true;MinPoolSize=0;MaxPoolSize=100;"
|
||||||
|
)]
|
||||||
|
[InlineData("Data Source=localhost;Initial Catalog=chatbot;Integrated Security=true;")]
|
||||||
|
[InlineData(
|
||||||
|
"Server=localhost;Database=chatbot;Trusted_Connection=true;MultipleActiveResultSets=true;"
|
||||||
|
)]
|
||||||
|
public void ConnectionString_ShouldAcceptVariousFormats(string connectionString)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.ConnectionString = connectionString;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.ConnectionString.Should().Be(connectionString);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(true)]
|
||||||
|
[InlineData(false)]
|
||||||
|
public void EnableSensitiveDataLogging_ShouldAcceptBooleanValues(bool enabled)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.EnableSensitiveDataLogging = enabled;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.EnableSensitiveDataLogging.Should().Be(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0)]
|
||||||
|
[InlineData(1)]
|
||||||
|
[InlineData(30)]
|
||||||
|
[InlineData(60)]
|
||||||
|
[InlineData(300)]
|
||||||
|
[InlineData(int.MaxValue)]
|
||||||
|
public void CommandTimeout_ShouldAcceptVariousValues(int timeout)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.CommandTimeout = timeout;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.CommandTimeout.Should().Be(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AllProperties_ShouldBeMutable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.ConnectionString = "Server=test;Database=testdb;";
|
||||||
|
settings.EnableSensitiveDataLogging = true;
|
||||||
|
settings.CommandTimeout = 120;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.ConnectionString.Should().Be("Server=test;Database=testdb;");
|
||||||
|
settings.EnableSensitiveDataLogging.Should().BeTrue();
|
||||||
|
settings.CommandTimeout.Should().Be(120);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportEmptyConnectionString()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.ConnectionString = "";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.ConnectionString.Should().Be("");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportNullConnectionString()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.ConnectionString = null!;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.ConnectionString.Should().BeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportVeryLongConnectionString()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
var longConnectionString = new string('A', 1000);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.ConnectionString = longConnectionString;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.ConnectionString.Should().Be(longConnectionString);
|
||||||
|
settings.ConnectionString.Length.Should().Be(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportPostgreSQLConnectionString()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
var postgresConnectionString =
|
||||||
|
"Host=localhost;Port=5432;Database=chatbot;Username=admin;Password=testpass;Pooling=true;MinPoolSize=0;MaxPoolSize=100;Connection Lifetime=0;";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.ConnectionString = postgresConnectionString;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.ConnectionString.Should().Be(postgresConnectionString);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportSQLServerConnectionString()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
var sqlServerConnectionString =
|
||||||
|
"Server=localhost;Database=chatbot;User Id=admin;Password=testpass;TrustServerCertificate=true;";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.ConnectionString = sqlServerConnectionString;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.ConnectionString.Should().Be(sqlServerConnectionString);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportSQLiteConnectionString()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
var sqliteConnectionString = "Data Source=chatbot.db;Cache=Shared;";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.ConnectionString = sqliteConnectionString;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.ConnectionString.Should().Be(sqliteConnectionString);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportMySQLConnectionString()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
var mysqlConnectionString =
|
||||||
|
"Server=localhost;Port=3306;Database=chatbot;Uid=admin;Pwd=testpass;";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.ConnectionString = mysqlConnectionString;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.ConnectionString.Should().Be(mysqlConnectionString);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportConnectionStringWithSpecialCharacters()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
var connectionStringWithSpecialChars =
|
||||||
|
"Server=localhost;Database=test-db;User Id=user@domain.com;Password=testpass123!;";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.ConnectionString = connectionStringWithSpecialChars;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.ConnectionString.Should().Be(connectionStringWithSpecialChars);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportConnectionStringWithUnicode()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
var connectionStringWithUnicode =
|
||||||
|
"Server=localhost;Database=тестовая_база;User Id=пользователь;Password=testpass;";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.ConnectionString = connectionStringWithUnicode;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.ConnectionString.Should().Be(connectionStringWithUnicode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportZeroCommandTimeout()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.CommandTimeout = 0;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.CommandTimeout.Should().Be(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportNegativeCommandTimeout()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.CommandTimeout = -1;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.CommandTimeout.Should().Be(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportMaxIntCommandTimeout()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.CommandTimeout = int.MaxValue;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.CommandTimeout.Should().Be(int.MaxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportMinIntCommandTimeout()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.CommandTimeout = int.MinValue;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.CommandTimeout.Should().Be(int.MinValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportDevelopmentMode()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.EnableSensitiveDataLogging = true;
|
||||||
|
settings.ConnectionString = "Server=localhost;Database=chatbot_dev;";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.EnableSensitiveDataLogging.Should().BeTrue();
|
||||||
|
settings.ConnectionString.Should().Be("Server=localhost;Database=chatbot_dev;");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportProductionMode()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.EnableSensitiveDataLogging = false;
|
||||||
|
settings.ConnectionString = "Server=prod-server;Database=chatbot_prod;";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.EnableSensitiveDataLogging.Should().BeFalse();
|
||||||
|
settings.ConnectionString.Should().Be("Server=prod-server;Database=chatbot_prod;");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportConnectionStringWithMultipleParameters()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
var complexConnectionString =
|
||||||
|
"Server=localhost;Port=5432;Database=chatbot;Username=admin;Password=testpass;Pooling=true;MinPoolSize=5;MaxPoolSize=100;Connection Lifetime=300;Command Timeout=60;";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.ConnectionString = complexConnectionString;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.ConnectionString.Should().Be(complexConnectionString);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportConnectionStringWithSpaces()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
var connectionStringWithSpaces =
|
||||||
|
"Server = localhost ; Database = chatbot ; User Id = admin ; Password = testpass ;";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.ConnectionString = connectionStringWithSpaces;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.ConnectionString.Should().Be(connectionStringWithSpaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportConnectionStringWithQuotes()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
var connectionStringWithQuotes =
|
||||||
|
"Server=\"localhost\";Database=\"chatbot\";User Id=\"admin\";Password=\"testpass\";";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.ConnectionString = connectionStringWithQuotes;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.ConnectionString.Should().Be(connectionStringWithQuotes);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportConnectionStringWithSemicolons()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
var connectionStringWithSemicolons =
|
||||||
|
"Server=localhost;;Database=chatbot;;User Id=admin;;Password=testpass;;";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.ConnectionString = connectionStringWithSemicolons;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.ConnectionString.Should().Be(connectionStringWithSemicolons);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportConnectionStringWithEquals()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
var connectionStringWithEquals =
|
||||||
|
"Server=localhost;Database=chatbot;User Id=admin;Password=testpass=123;";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.ConnectionString = connectionStringWithEquals;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.ConnectionString.Should().Be(connectionStringWithEquals);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportConnectionStringWithNewlines()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
var connectionStringWithNewlines =
|
||||||
|
"Server=localhost;\nDatabase=chatbot;\nUser Id=admin;\nPassword=testpass;";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.ConnectionString = connectionStringWithNewlines;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.ConnectionString.Should().Be(connectionStringWithNewlines);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportConnectionStringWithTabs()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new DatabaseSettings();
|
||||||
|
var connectionStringWithTabs =
|
||||||
|
"Server=localhost;\tDatabase=chatbot;\tUser Id=admin;\tPassword=testpass;";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.ConnectionString = connectionStringWithTabs;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.ConnectionString.Should().Be(connectionStringWithTabs);
|
||||||
|
}
|
||||||
|
}
|
||||||
568
ChatBot.Tests/Models/OllamaSettingsTests.cs
Normal file
568
ChatBot.Tests/Models/OllamaSettingsTests.cs
Normal file
@@ -0,0 +1,568 @@
|
|||||||
|
using ChatBot.Models.Configuration;
|
||||||
|
using FluentAssertions;
|
||||||
|
|
||||||
|
namespace ChatBot.Tests.Models;
|
||||||
|
|
||||||
|
public class OllamaSettingsTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_ShouldInitializePropertiesWithDefaultValues()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Url.Should().Be("http://localhost:11434");
|
||||||
|
settings.DefaultModel.Should().Be("llama3");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Url_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
var expectedUrl = "http://ollama.example.com:11434";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Url = expectedUrl;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Url.Should().Be(expectedUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DefaultModel_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
var expectedModel = "llama3.1:8b";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.DefaultModel = expectedModel;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.DefaultModel.Should().Be(expectedModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("")]
|
||||||
|
[InlineData("http://localhost:11434")]
|
||||||
|
[InlineData("https://ollama.example.com:11434")]
|
||||||
|
[InlineData("http://192.168.1.100:11434")]
|
||||||
|
[InlineData("https://api.ollama.com")]
|
||||||
|
[InlineData("http://localhost")]
|
||||||
|
[InlineData("https://ollama.example.com")]
|
||||||
|
public void Url_ShouldAcceptVariousFormats(string url)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Url = url;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Url.Should().Be(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("")]
|
||||||
|
[InlineData("llama3")]
|
||||||
|
[InlineData("llama3.1")]
|
||||||
|
[InlineData("llama3.1:8b")]
|
||||||
|
[InlineData("llama3.1:70b")]
|
||||||
|
[InlineData("gemma2")]
|
||||||
|
[InlineData("gemma2:2b")]
|
||||||
|
[InlineData("gemma2:9b")]
|
||||||
|
[InlineData("mistral")]
|
||||||
|
[InlineData("mistral:7b")]
|
||||||
|
[InlineData("codellama")]
|
||||||
|
[InlineData("codellama:7b")]
|
||||||
|
[InlineData("phi3")]
|
||||||
|
[InlineData("phi3:3.8b")]
|
||||||
|
[InlineData("qwen2")]
|
||||||
|
[InlineData("qwen2:7b")]
|
||||||
|
public void DefaultModel_ShouldAcceptVariousModels(string model)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.DefaultModel = model;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.DefaultModel.Should().Be(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AllProperties_ShouldBeMutable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Url = "https://custom-ollama.example.com:8080";
|
||||||
|
settings.DefaultModel = "custom-model:latest";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Url.Should().Be("https://custom-ollama.example.com:8080");
|
||||||
|
settings.DefaultModel.Should().Be("custom-model:latest");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportEmptyUrl()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Url = "";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Url.Should().Be("");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportEmptyModel()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.DefaultModel = "";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.DefaultModel.Should().Be("");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportNullUrl()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Url = null!;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Url.Should().BeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportNullModel()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.DefaultModel = null!;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.DefaultModel.Should().BeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportLocalhostUrl()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Url = "http://localhost:11434";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Url.Should().Be("http://localhost:11434");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportHttpsUrl()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Url = "https://ollama.example.com:11434";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Url.Should().Be("https://ollama.example.com:11434");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportCustomPort()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Url = "http://localhost:8080";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Url.Should().Be("http://localhost:8080");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportIpAddress()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Url = "http://192.168.1.100:11434";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Url.Should().Be("http://192.168.1.100:11434");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportDomainName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Url = "https://api.ollama.com";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Url.Should().Be("https://api.ollama.com");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportLlama3Model()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.DefaultModel = "llama3";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.DefaultModel.Should().Be("llama3");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportLlama31Model()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.DefaultModel = "llama3.1:8b";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.DefaultModel.Should().Be("llama3.1:8b");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportGemmaModel()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.DefaultModel = "gemma2:9b";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.DefaultModel.Should().Be("gemma2:9b");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportMistralModel()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.DefaultModel = "mistral:7b";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.DefaultModel.Should().Be("mistral:7b");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportCodeLlamaModel()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.DefaultModel = "codellama:7b";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.DefaultModel.Should().Be("codellama:7b");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportPhi3Model()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.DefaultModel = "phi3:3.8b";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.DefaultModel.Should().Be("phi3:3.8b");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportQwen2Model()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.DefaultModel = "qwen2:7b";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.DefaultModel.Should().Be("qwen2:7b");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportVeryLongUrl()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
var longUrl =
|
||||||
|
"https://very-long-domain-name-that-might-be-used-in-some-cases.example.com:11434";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Url = longUrl;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Url.Should().Be(longUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportVeryLongModelName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
var longModelName = "very-long-model-name-that-might-be-used-in-some-cases:latest";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.DefaultModel = longModelName;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.DefaultModel.Should().Be(longModelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportUrlWithPath()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Url = "https://ollama.example.com/api/v1";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Url.Should().Be("https://ollama.example.com/api/v1");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportUrlWithQueryParameters()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Url = "https://ollama.example.com:11434?timeout=30&retries=3";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Url.Should().Be("https://ollama.example.com:11434?timeout=30&retries=3");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportUrlWithFragment()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Url = "https://ollama.example.com:11434#api";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Url.Should().Be("https://ollama.example.com:11434#api");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportModelWithVersion()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.DefaultModel = "llama3.1:8b-instruct-q4_0";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.DefaultModel.Should().Be("llama3.1:8b-instruct-q4_0");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportModelWithCustomTag()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.DefaultModel = "custom-model:my-tag";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.DefaultModel.Should().Be("custom-model:my-tag");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportModelWithSpecialCharacters()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.DefaultModel = "model-name_with.special+chars:version-tag";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.DefaultModel.Should().Be("model-name_with.special+chars:version-tag");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportUrlWithSpecialCharacters()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Url = "https://user:pass@ollama.example.com:11434";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Url.Should().Be("https://user:pass@ollama.example.com:11434");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportModelWithUnicode()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.DefaultModel = "модель:версия";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.DefaultModel.Should().Be("модель:версия");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportUrlWithUnicode()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Url = "https://оллама.пример.ком:11434";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Url.Should().Be("https://оллама.пример.ком:11434");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportModelWithNumbers()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.DefaultModel = "model123:version456";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.DefaultModel.Should().Be("model123:version456");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportUrlWithNumbers()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Url = "http://192.168.1.100:11434";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Url.Should().Be("http://192.168.1.100:11434");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportModelWithUnderscores()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.DefaultModel = "my_model_name:my_version_tag";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.DefaultModel.Should().Be("my_model_name:my_version_tag");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportUrlWithUnderscores()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Url = "http://my_ollama_server.example.com:11434";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Url.Should().Be("http://my_ollama_server.example.com:11434");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportModelWithHyphens()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.DefaultModel = "my-model-name:my-version-tag";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.DefaultModel.Should().Be("my-model-name:my-version-tag");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportUrlWithHyphens()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Url = "http://my-ollama-server.example.com:11434";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Url.Should().Be("http://my-ollama-server.example.com:11434");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportModelWithDots()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.DefaultModel = "my.model.name:my.version.tag";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.DefaultModel.Should().Be("my.model.name:my.version.tag");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportUrlWithDots()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new OllamaSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.Url = "http://my.ollama.server.example.com:11434";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Url.Should().Be("http://my.ollama.server.example.com:11434");
|
||||||
|
}
|
||||||
|
}
|
||||||
742
ChatBot.Tests/Models/TelegramBotSettingsTests.cs
Normal file
742
ChatBot.Tests/Models/TelegramBotSettingsTests.cs
Normal file
@@ -0,0 +1,742 @@
|
|||||||
|
using ChatBot.Models.Configuration;
|
||||||
|
using FluentAssertions;
|
||||||
|
|
||||||
|
namespace ChatBot.Tests.Models;
|
||||||
|
|
||||||
|
public class TelegramBotSettingsTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_ShouldInitializePropertiesWithDefaultValues()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void BotToken_ShouldBeSettable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var expectedToken = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = expectedToken;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(expectedToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("")]
|
||||||
|
[InlineData("1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk")]
|
||||||
|
[InlineData("1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk-")]
|
||||||
|
[InlineData("1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk_")]
|
||||||
|
[InlineData("1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk.")]
|
||||||
|
[InlineData("1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk+")]
|
||||||
|
[InlineData("1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk/")]
|
||||||
|
[InlineData("1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk=")]
|
||||||
|
public void BotToken_ShouldAcceptVariousFormats(string token)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = token;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AllProperties_ShouldBeMutable()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = "9876543210:ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings
|
||||||
|
.BotToken.Should()
|
||||||
|
.Be("9876543210:ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportEmptyToken()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = "";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be("");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportNullToken()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = null!;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().BeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportValidBotToken()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var validToken = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = validToken;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(validToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportShortBotToken()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var shortToken = "123:ABC";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = shortToken;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(shortToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportLongBotToken()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var longToken =
|
||||||
|
"12345678901234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = longToken;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(longToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithNumbers()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithNumbers = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk1234567890";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithNumbers;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithNumbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithLetters()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithLetters = "abcdefghij:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithLetters;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithLetters);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithMixedCase()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithMixedCase = "1234567890:AbCdEfGhIjKlMnOpQrStUvWxYz";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithMixedCase;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithMixedCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithSpecialCharacters()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithSpecialChars = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk-_.+/=";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithSpecialChars;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithSpecialChars);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithColon()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithColon = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk:";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithColon;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithColon);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithUnderscores()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithUnderscores = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk_";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithUnderscores;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithUnderscores);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithHyphens()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithHyphens = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk-";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithHyphens;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithHyphens);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithDots()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithDots = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk.";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithDots;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithDots);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithPlus()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithPlus = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk+";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithPlus;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithPlus);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithSlash()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithSlash = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk/";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithSlash;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithSlash);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithEquals()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithEquals = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk=";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithEquals;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithEquals);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithUnicode()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithUnicode = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkабвгд";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithUnicode;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithUnicode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithSpaces()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithSpaces = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk ";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithSpaces;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithSpaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithTabs()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithTabs = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk\t";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithTabs;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithTabs);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithNewlines()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithNewlines = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk\n";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithNewlines;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithNewlines);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithCarriageReturn()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithCarriageReturn = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk\r";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithCarriageReturn;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithCarriageReturn);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithQuotes()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithQuotes = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk\"";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithQuotes;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithQuotes);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithSingleQuotes()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithSingleQuotes = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk'";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithSingleQuotes;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithSingleQuotes);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithBackslashes()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithBackslashes = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk\\";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithBackslashes;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithBackslashes);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithForwardSlashes()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithForwardSlashes = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk/";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithForwardSlashes;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithForwardSlashes);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithPipes()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithPipes = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk|";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithPipes;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithPipes);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithAmpersands()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithAmpersands = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk&";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithAmpersands;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithAmpersands);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithPercents()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithPercents = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk%";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithPercents;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithPercents);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithDollarSigns()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithDollarSigns = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk$";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithDollarSigns;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithDollarSigns);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithAtSigns()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithAtSigns = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk@";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithAtSigns;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithAtSigns);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithHashSigns()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithHashSigns = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk#";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithHashSigns;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithHashSigns);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithExclamationMarks()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithExclamationMarks = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk!";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithExclamationMarks;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithExclamationMarks);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithQuestionMarks()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithQuestionMarks = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk?";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithQuestionMarks;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithQuestionMarks);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithBrackets()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithBrackets = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk[]";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithBrackets;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithBrackets);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithBraces()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithBraces = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk{}";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithBraces;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithBraces);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithParentheses()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithParentheses = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk()";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithParentheses;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithParentheses);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithAngleBrackets()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithAngleBrackets = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk<>";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithAngleBrackets;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithAngleBrackets);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithTildes()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithTildes = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk~";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithTildes;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithTildes);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithCaret()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithCaret = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk^";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithCaret;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithCaret);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithBackticks()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithBackticks = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk`";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithBackticks;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithBackticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithSemicolons()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithSemicolons = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk;";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithSemicolons;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithSemicolons);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithCommas()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithCommas = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk,";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithCommas;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithCommas);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithPeriods()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithPeriods = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk.";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithPeriods;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithPeriods);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithAllSpecialCharacters()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithAllSpecialChars =
|
||||||
|
"1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk-_.+/=:;\"'\\|&%$@#!?[]{}()<>~^`";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithAllSpecialChars;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithAllSpecialChars);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportVeryLongBotToken()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var veryLongToken =
|
||||||
|
"12345678901234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = veryLongToken;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(veryLongToken);
|
||||||
|
settings.BotToken.Length.Should().BeGreaterThan(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithOnlyNumbers()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithOnlyNumbers = "1234567890:123456789012345678901234567890";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithOnlyNumbers;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithOnlyNumbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithOnlyLetters()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithOnlyLetters = "abcdefghij:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithOnlyLetters;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithOnlyLetters);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Settings_ShouldSupportBotTokenWithMixedContent()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new TelegramBotSettings();
|
||||||
|
var tokenWithMixedContent =
|
||||||
|
"1234567890:AbC123dEf456GhI789jKl012MnO345pQr678sTu901vWx234yZ567";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.BotToken = tokenWithMixedContent;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.BotToken.Should().Be(tokenWithMixedContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
154
test_coverage_report.md
Normal file
154
test_coverage_report.md
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
# Отчет о покрытии тестами проекта ChatBot
|
||||||
|
|
||||||
|
## Общая статистика
|
||||||
|
- **Всего тестов**: 187
|
||||||
|
- **Статус**: ✅ Все тесты проходят успешно
|
||||||
|
- **Покрытие**: Анализ покрытия выполнен
|
||||||
|
|
||||||
|
## Анализ существующих тестов
|
||||||
|
|
||||||
|
### ✅ Покрытые области
|
||||||
|
|
||||||
|
#### 1. Модели (Models)
|
||||||
|
- [x] `ChatSession` - базовые тесты конструктора и методов
|
||||||
|
- [x] `AISettings` - валидация конфигурации
|
||||||
|
- [x] `DatabaseSettings` - валидация конфигурации
|
||||||
|
- [x] `OllamaSettings` - валидация конфигурации
|
||||||
|
- [x] `TelegramBotSettings` - валидация конфигурации
|
||||||
|
|
||||||
|
#### 2. Сервисы (Services)
|
||||||
|
- [x] `AIService` - основные тесты
|
||||||
|
- [x] `ChatService` - unit и integration тесты
|
||||||
|
- [x] `DatabaseInitializationService` - тесты инициализации
|
||||||
|
- [x] `DatabaseSessionStorage` - тесты работы с БД
|
||||||
|
- [x] `InMemorySessionStorage` - тесты in-memory хранилища
|
||||||
|
- [x] `HistoryCompressionService` - тесты сжатия истории
|
||||||
|
- [x] `ModelService` - тесты управления моделями
|
||||||
|
- [x] `OllamaClientAdapter` - тесты адаптера Ollama
|
||||||
|
- [x] `SystemPromptService` - тесты загрузки промптов
|
||||||
|
|
||||||
|
#### 3. Health Checks
|
||||||
|
- [x] `OllamaHealthCheck` - проверка доступности Ollama
|
||||||
|
- [x] `TelegramBotHealthCheck` - проверка Telegram бота
|
||||||
|
|
||||||
|
#### 4. Telegram команды
|
||||||
|
- [x] `StartCommand` - команда /start
|
||||||
|
- [x] `HelpCommand` - команда /help
|
||||||
|
- [x] `ClearCommand` - команда /clear
|
||||||
|
- [x] `SettingsCommand` - команда /settings
|
||||||
|
- [x] `StatusCommand` - команда /status
|
||||||
|
- [x] `CommandRegistry` - реестр команд
|
||||||
|
|
||||||
|
#### 5. Telegram сервисы
|
||||||
|
- [x] `TelegramBotService` - основной сервис бота
|
||||||
|
- [x] `TelegramMessageHandler` - обработчик сообщений
|
||||||
|
- [x] `TelegramMessageSender` - отправка сообщений
|
||||||
|
- [x] `TelegramErrorHandler` - обработка ошибок
|
||||||
|
- [x] `BotInfoService` - информация о боте
|
||||||
|
|
||||||
|
#### 6. Репозитории
|
||||||
|
- [x] `ChatSessionRepository` - работа с БД
|
||||||
|
|
||||||
|
#### 7. Интеграционные тесты
|
||||||
|
- [x] `ProgramIntegrationTests` - тесты инициализации приложения
|
||||||
|
- [x] `ChatServiceIntegrationTests` - интеграционные тесты чата
|
||||||
|
|
||||||
|
## ❌ Области без тестов (требуют покрытия)
|
||||||
|
|
||||||
|
### 1. Модели и DTO
|
||||||
|
- [x] `ChatMessage` (Dto) - тесты для DTO сообщений
|
||||||
|
- [x] `ChatMessageEntity` - тесты для Entity модели сообщений
|
||||||
|
- [x] `ChatSessionEntity` - тесты для Entity модели сессий
|
||||||
|
- [x] `AISettings` - тесты конструктора и свойств
|
||||||
|
- [x] `DatabaseSettings` - тесты конструктора и свойств
|
||||||
|
- [x] `OllamaSettings` - тесты конструктора и свойств
|
||||||
|
- [x] `TelegramBotSettings` - тесты конструктора и свойств
|
||||||
|
|
||||||
|
### 2. Константы
|
||||||
|
- [ ] `AIResponseConstants` - тесты констант
|
||||||
|
- [ ] `ChatTypes` - тесты типов чатов
|
||||||
|
|
||||||
|
### 3. Сервисы (дополнительные тесты)
|
||||||
|
- [ ] `SystemPromptService` - тесты обработки ошибок при загрузке файлов
|
||||||
|
- [ ] `ModelService` - тесты с различными настройками
|
||||||
|
- [ ] `AIService` - тесты обработки ошибок и retry логики
|
||||||
|
- [ ] `ChatService` - тесты edge cases и обработки ошибок
|
||||||
|
- [ ] `DatabaseInitializationService` - тесты обработки ошибок БД
|
||||||
|
- [ ] `HistoryCompressionService` - тесты различных сценариев сжатия
|
||||||
|
|
||||||
|
### 4. Telegram команды (дополнительные тесты)
|
||||||
|
- [ ] `TelegramCommandBase` - тесты базового класса команд
|
||||||
|
- [ ] `TelegramCommandProcessor` - тесты обработки команд
|
||||||
|
- [ ] `TelegramCommandContext` - тесты контекста команд
|
||||||
|
- [ ] `ReplyInfo` - тесты информации о ответах
|
||||||
|
- [ ] `CommandAttribute` - тесты атрибутов команд
|
||||||
|
|
||||||
|
### 5. Telegram сервисы (дополнительные тесты)
|
||||||
|
- [ ] `TelegramBotClientWrapper` - тесты обертки клиента
|
||||||
|
- [ ] `TelegramMessageHandler` - тесты различных типов сообщений
|
||||||
|
- [ ] `TelegramErrorHandler` - тесты различных типов ошибок
|
||||||
|
- [ ] `TelegramMessageSender` - тесты отправки различных типов сообщений
|
||||||
|
|
||||||
|
### 6. Интерфейсы
|
||||||
|
- [ ] `IAIService` - тесты интерфейса
|
||||||
|
- [ ] `ISessionStorage` - тесты интерфейса
|
||||||
|
- [ ] `IHistoryCompressionService` - тесты интерфейса
|
||||||
|
- [ ] `IOllamaClient` - тесты интерфейса
|
||||||
|
- [ ] `ITelegramBotClientWrapper` - тесты интерфейса
|
||||||
|
- [ ] `IChatSessionRepository` - тесты интерфейса
|
||||||
|
|
||||||
|
### 7. Контекст базы данных
|
||||||
|
- [ ] `ChatBotDbContext` - тесты контекста БД
|
||||||
|
- [ ] Миграции - тесты миграций
|
||||||
|
|
||||||
|
### 8. Основной файл приложения
|
||||||
|
- [ ] `Program.cs` - тесты конфигурации и инициализации
|
||||||
|
|
||||||
|
### 9. Валидаторы (дополнительные тесты)
|
||||||
|
- [ ] `AISettingsValidator` - тесты всех валидационных правил
|
||||||
|
- [ ] `DatabaseSettingsValidator` - тесты всех валидационных правил
|
||||||
|
- [ ] `OllamaSettingsValidator` - тесты всех валидационных правил
|
||||||
|
- [ ] `TelegramBotSettingsValidator` - тесты всех валидационных правил
|
||||||
|
|
||||||
|
## Приоритеты для создания тестов
|
||||||
|
|
||||||
|
### 🔴 Высокий приоритет
|
||||||
|
1. **Entity модели** - `ChatMessageEntity`, `ChatSessionEntity`
|
||||||
|
2. **DTO модели** - `ChatMessage`
|
||||||
|
3. **Конфигурационные классы** - `AISettings`, `DatabaseSettings`, `OllamaSettings`, `TelegramBotSettings`
|
||||||
|
4. **Основные сервисы** - дополнительные тесты для `AIService`, `ChatService`
|
||||||
|
5. **Обработка ошибок** - тесты для всех сервисов
|
||||||
|
|
||||||
|
### 🟡 Средний приоритет
|
||||||
|
1. **Telegram команды** - дополнительные тесты для команд
|
||||||
|
2. **Telegram сервисы** - дополнительные тесты для сервисов
|
||||||
|
3. **Валидаторы** - полное покрытие всех правил валидации
|
||||||
|
4. **Константы** - тесты констант
|
||||||
|
|
||||||
|
### 🟢 Низкий приоритет
|
||||||
|
1. **Интерфейсы** - тесты интерфейсов (обычно не требуются)
|
||||||
|
2. **Миграции** - тесты миграций
|
||||||
|
3. **Program.cs** - тесты конфигурации
|
||||||
|
|
||||||
|
## Рекомендации
|
||||||
|
|
||||||
|
1. **Начните с Entity и DTO моделей** - они критически важны для работы приложения
|
||||||
|
2. **Добавьте тесты обработки ошибок** - это повысит надежность приложения
|
||||||
|
3. **Покройте edge cases** - тесты граничных случаев и исключительных ситуаций
|
||||||
|
4. **Добавьте интеграционные тесты** - для проверки взаимодействия компонентов
|
||||||
|
5. **Используйте параметризованные тесты** - для тестирования различных сценариев
|
||||||
|
|
||||||
|
## Метрики качества
|
||||||
|
|
||||||
|
- **Покрытие кода**: ~70% (оценочно)
|
||||||
|
- **Покрытие функциональности**: ~80% (оценочно)
|
||||||
|
- **Покрытие ошибок**: ~30% (оценочно)
|
||||||
|
- **Интеграционное покрытие**: ~60% (оценочно)
|
||||||
|
|
||||||
|
## Следующие шаги
|
||||||
|
|
||||||
|
1. Создать тесты для Entity моделей
|
||||||
|
2. Добавить тесты для DTO классов
|
||||||
|
3. Расширить тесты для основных сервисов
|
||||||
|
4. Добавить тесты обработки ошибок
|
||||||
|
5. Создать дополнительные интеграционные тесты
|
||||||
Reference in New Issue
Block a user