using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using BLAIzor.Data; using BLAIzor.Models; using BLAIzor.Services; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Moq; using Xunit; namespace SeemGen.Tests; public class ContentEditorServiceTests { [Fact] public async Task SaveAndSyncContentItemAsync_UpdatesFieldsAndRechunks_WhenContentChanged() { // Arrange var contentItemId = 1; var oldContent = "Old content"; var newContent = "New content for chunking"; var collectionName = "test_collection"; var contentGroup = new ContentGroup { Id = 1, Name = "Group", SiteInfoId = 1, Items = new List() }; var existingChunks = new List { new ContentChunk { Id = 1, ContentItemId = contentItemId, QdrantPointId = Guid.NewGuid().ToString(), ChunkIndex = 0, CreatedAt = DateTime.UtcNow } }; var existingItem = new ContentItem { Id = contentItemId, Title = "Old Title", Description = "Old Desc", Content = oldContent, Language = "en", Tags = "tag1", IsPublished = true, LastUpdated = DateTime.UtcNow, ContentGroup = contentGroup, Chunks = existingChunks }; contentGroup.Items.Add(existingItem); var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString()) .Options; var dbContext = new ApplicationDbContext(options); dbContext.ContentItems.Add(existingItem); dbContext.ContentChunks.AddRange(existingChunks); dbContext.SaveChanges(); var serviceScopeFactoryMock = new Mock(); var scopeMock = new Mock(); var providerMock = new Mock(); providerMock.Setup(x => x.GetService(typeof(ApplicationDbContext))).Returns(dbContext); scopeMock.Setup(x => x.ServiceProvider).Returns(providerMock.Object); serviceScopeFactoryMock.Setup(x => x.CreateScope()).Returns(scopeMock.Object); var qdrantServiceMock = new Mock(null); qdrantServiceMock.Setup(x => x.DeletePointsAsync(It.IsAny(), collectionName)).Returns(Task.CompletedTask); qdrantServiceMock.Setup(x => x.QDrantInsertManyAsync(It.IsAny>(), collectionName)).Returns(Task.CompletedTask); var openAIEmbeddingServiceMock = new Mock(); openAIEmbeddingServiceMock.Setup(x => x.GenerateEmbeddingAsync(It.IsAny())).ReturnsAsync(new float[] { 0.1f, 0.2f }); var localEmbeddingServiceMock = new Mock(); localEmbeddingServiceMock.Setup(x => x.GenerateEmbeddingAsync(It.IsAny())).ReturnsAsync(new float[] { 0.1f, 0.2f }); var openAIApiServiceMock = new Mock(MockBehavior.Loose, null, null); var htmlSnippetProcessorMock = new Mock(qdrantServiceMock.Object, openAIEmbeddingServiceMock.Object, localEmbeddingServiceMock.Object, null); var scopedContentServiceMock = new Mock(dbContext, serviceScopeFactoryMock.Object); var configMock = new Mock(); configMock.Setup(x => x.GetSection("AiSettings").GetValue("EmbeddingService")).Returns("openai"); var service = new ContentEditorService( openAIApiServiceMock.Object, qdrantServiceMock.Object, openAIEmbeddingServiceMock.Object, localEmbeddingServiceMock.Object, htmlSnippetProcessorMock.Object, serviceScopeFactoryMock.Object, scopedContentServiceMock.Object, configMock.Object ); var dto = new ContentItem { Id = contentItemId, Title = "New Title", Description = "New Desc", Content = newContent, Language = "fr", Tags = "tag2", IsPublished = false, LastUpdated = DateTime.UtcNow }; // Act var result = await service.SaveAndSyncContentItemAsync(dto, collectionName, false); // Assert Assert.Equal(dto.Title, result.Title); Assert.Equal(dto.Description, result.Description); Assert.Equal(dto.Content, result.Content); Assert.Equal(dto.Language, result.Language); Assert.Equal(dto.Tags, result.Tags); Assert.Equal(dto.IsPublished, result.IsPublished); Assert.True(result.Version > 0); Assert.NotEmpty(dbContext.ContentChunks.Where(c => c.ContentItemId == contentItemId)); qdrantServiceMock.Verify(x => x.DeletePointsAsync(It.IsAny(), collectionName), Times.Once); qdrantServiceMock.Verify(x => x.QDrantInsertManyAsync(It.IsAny>(), collectionName), Times.Once); } }