using ChatBot.Data; using ChatBot.Data.Interfaces; using ChatBot.Data.Repositories; using ChatBot.Models.Entities; using ChatBot.Tests.TestUtilities; using FluentAssertions; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Moq; namespace ChatBot.Tests.Data.Repositories; public class ChatSessionRepositoryTests : TestBase { private ChatBotDbContext _dbContext = null!; private ChatSessionRepository _repository = null!; public ChatSessionRepositoryTests() { SetupServices(); } protected override void ConfigureServices(IServiceCollection services) { // Add in-memory database with unique name per test services.AddDbContext(options => options.UseInMemoryDatabase(Guid.NewGuid().ToString()) ); // Add logger services.AddSingleton(Mock.Of>()); // Add repository services.AddScoped(); } protected override void SetupServices() { base.SetupServices(); _dbContext = ServiceProvider.GetRequiredService(); _repository = (ChatSessionRepository) ServiceProvider.GetRequiredService(); // Ensure database is created _dbContext.Database.EnsureCreated(); } private void CleanupDatabase() { _dbContext.ChatSessions.RemoveRange(_dbContext.ChatSessions); _dbContext.ChatMessages.RemoveRange(_dbContext.ChatMessages); _dbContext.SaveChanges(); } [Fact] public async Task GetOrCreateAsync_ShouldReturnExistingSession_WhenSessionExists() { // Arrange CleanupDatabase(); var chatId = 12345L; var chatType = "private"; var chatTitle = "Test Chat"; var existingSession = TestDataBuilder.Mocks.CreateChatSessionEntity( 1, chatId, "existing-session", chatType, chatTitle ); _dbContext.ChatSessions.Add(existingSession); await _dbContext.SaveChangesAsync(); // Act var result = await _repository.GetOrCreateAsync(chatId, chatType, chatTitle); // Assert result.Should().NotBeNull(); result.ChatId.Should().Be(chatId); result.SessionId.Should().Be("existing-session"); } [Fact] public async Task GetOrCreateAsync_ShouldCreateNewSession_WhenSessionDoesNotExist() { // Arrange CleanupDatabase(); var chatId = 12345L; var chatType = "private"; var chatTitle = "Test Chat"; // Act var result = await _repository.GetOrCreateAsync(chatId, chatType, chatTitle); // Assert result.Should().NotBeNull(); result.ChatId.Should().Be(chatId); result.ChatType.Should().Be(chatType); result.ChatTitle.Should().Be(chatTitle); result.SessionId.Should().NotBeNullOrEmpty(); } [Fact] public async Task GetByChatIdAsync_ShouldReturnSession_WhenSessionExists() { // Arrange CleanupDatabase(); var chatId = 12345L; var session = TestDataBuilder.Mocks.CreateChatSessionEntity(1, chatId); _dbContext.ChatSessions.Add(session); await _dbContext.SaveChangesAsync(); // Act var result = await _repository.GetByChatIdAsync(chatId); // Assert result.Should().NotBeNull(); result.ChatId.Should().Be(chatId); } [Fact] public async Task GetByChatIdAsync_ShouldReturnNull_WhenSessionDoesNotExist() { // Arrange CleanupDatabase(); var chatId = 12345L; // Act var result = await _repository.GetByChatIdAsync(chatId); // Assert result.Should().BeNull(); } [Fact] public async Task GetBySessionIdAsync_ShouldReturnSession_WhenSessionExists() { // Arrange CleanupDatabase(); var sessionId = "test-session"; var session = TestDataBuilder.Mocks.CreateChatSessionEntity(1, 12345, sessionId); _dbContext.ChatSessions.Add(session); await _dbContext.SaveChangesAsync(); // Act var result = await _repository.GetBySessionIdAsync(sessionId); // Assert result.Should().NotBeNull(); result.SessionId.Should().Be(sessionId); } [Fact] public async Task GetBySessionIdAsync_ShouldReturnNull_WhenSessionDoesNotExist() { // Arrange CleanupDatabase(); var sessionId = "nonexistent-session"; // Act var result = await _repository.GetBySessionIdAsync(sessionId); // Assert result.Should().BeNull(); } [Fact] public async Task UpdateAsync_ShouldUpdateSession() { // Arrange CleanupDatabase(); var session = TestDataBuilder.Mocks.CreateChatSessionEntity(1, 12345); _dbContext.ChatSessions.Add(session); await _dbContext.SaveChangesAsync(); session.ChatTitle = "Updated Title"; // Act var result = await _repository.UpdateAsync(session); // Assert result.Should().NotBeNull(); result.ChatTitle.Should().Be("Updated Title"); } [Fact] public async Task DeleteAsync_ShouldReturnTrue_WhenSessionExists() { // Arrange CleanupDatabase(); var chatId = 12345L; var session = TestDataBuilder.Mocks.CreateChatSessionEntity(1, chatId); _dbContext.ChatSessions.Add(session); await _dbContext.SaveChangesAsync(); // Act var result = await _repository.DeleteAsync(chatId); // Assert result.Should().BeTrue(); var deletedSession = await _repository.GetByChatIdAsync(chatId); deletedSession.Should().BeNull(); } [Fact] public async Task DeleteAsync_ShouldReturnFalse_WhenSessionDoesNotExist() { // Arrange CleanupDatabase(); var chatId = 12345L; // Act var result = await _repository.DeleteAsync(chatId); // Assert result.Should().BeFalse(); } [Fact] public async Task GetActiveSessionsCountAsync_ShouldReturnCorrectCount() { // Arrange CleanupDatabase(); var session1 = TestDataBuilder.Mocks.CreateChatSessionEntity(1, 12345); var session2 = TestDataBuilder.Mocks.CreateChatSessionEntity(2, 12346); _dbContext.ChatSessions.AddRange(session1, session2); await _dbContext.SaveChangesAsync(); // Act var count = await _repository.GetActiveSessionsCountAsync(); // Assert count.Should().Be(2); } [Fact] public async Task CleanupOldSessionsAsync_ShouldRemoveOldSessions() { // Arrange CleanupDatabase(); // Verify database is empty var initialCount = await _repository.GetActiveSessionsCountAsync(); initialCount.Should().Be(0); var oldSession = TestDataBuilder.Mocks.CreateChatSessionEntity(1, 12345); oldSession.LastUpdatedAt = DateTime.UtcNow.AddDays(-2); // 2 days old var recentSession = TestDataBuilder.Mocks.CreateChatSessionEntity(2, 12346); recentSession.LastUpdatedAt = DateTime.UtcNow.AddMinutes(-30); // 30 minutes old _dbContext.ChatSessions.AddRange(oldSession, recentSession); await _dbContext.SaveChangesAsync(); // Act var removedCount = await _repository.CleanupOldSessionsAsync(1); // Remove sessions older than 1 hour // Assert removedCount.Should().Be(1); var remainingSessions = await _repository.GetActiveSessionsCountAsync(); remainingSessions.Should().Be(1); } }