using ManagerService.Controllers; using ManagerService.Data; using ManagerService.DTOs; using ManagerService.Services; using ManagerService.Tests.Infrastructure; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging.Abstractions; using Moq; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Xunit; namespace ManagerService.Tests.Controllers { public class AiControllerTests { private static readonly AiChatResponse FakeResponse = new AiChatResponse { Reply = "OK" }; private AiController BuildController(MyInfoMateDbContext db, Mock? mockService = null) { mockService ??= new Mock(); mockService .Setup(s => s.ChatAsync(It.IsAny())) .ReturnsAsync(FakeResponse); return new AiController(mockService.Object, db, NullLogger.Instance); } private static AiChatRequest MakeRequest(string instanceId, AppType appType = AppType.Tablet) => new AiChatRequest { InstanceId = instanceId, AppType = appType, Message = "Bonjour" }; // ── FORBID CASES ───────────────────────────────────────────────────── [Fact] public async Task Chat_InstanceNotFound_ReturnsForbid() { using var db = DbContextFactory.Create(); var result = await BuildController(db).Chat(MakeRequest("unknown")); Assert.IsType(result); } [Fact] public async Task Chat_InstanceAssistantDisabled_ReturnsForbid() { using var db = DbContextFactory.Create(); db.Instances.Add(new Instance { Id = "i1", Name = "Musée", IsAssistant = false, DateCreation = DateTime.UtcNow }); db.ApplicationInstances.Add(new ApplicationInstance { Id = "ai1", InstanceId = "i1", AppType = AppType.Tablet, IsAssistant = true, Languages = new List() }); db.SaveChanges(); var result = await BuildController(db).Chat(MakeRequest("i1")); Assert.IsType(result); } [Fact] public async Task Chat_AppInstanceAssistantDisabled_ReturnsForbid() { using var db = DbContextFactory.Create(); db.Instances.Add(new Instance { Id = "i1", Name = "Musée", IsAssistant = true, DateCreation = DateTime.UtcNow }); db.ApplicationInstances.Add(new ApplicationInstance { Id = "ai1", InstanceId = "i1", AppType = AppType.Tablet, IsAssistant = false, Languages = new List() }); db.SaveChanges(); var result = await BuildController(db).Chat(MakeRequest("i1")); Assert.IsType(result); } [Fact] public async Task Chat_NoAppInstance_ReturnsForbid() { using var db = DbContextFactory.Create(); db.Instances.Add(new Instance { Id = "i1", Name = "Musée", IsAssistant = true, DateCreation = DateTime.UtcNow }); db.SaveChanges(); var result = await BuildController(db).Chat(MakeRequest("i1")); Assert.IsType(result); } // ── QUOTA COUNTER ──────────────────────────────────────────────────── [Fact] public async Task Chat_FirstRequestOfMonth_ResetsCounterAndSets1() { using var db = DbContextFactory.Create(); db.Instances.Add(new Instance { Id = "i1", Name = "Musée", IsAssistant = true, DateCreation = DateTime.UtcNow, AiRequestsThisMonth = 99, AiUsageMonthKey = "2020-01" }); db.ApplicationInstances.Add(new ApplicationInstance { Id = "ai1", InstanceId = "i1", AppType = AppType.Tablet, IsAssistant = true, Languages = new List() }); db.SaveChanges(); await BuildController(db).Chat(MakeRequest("i1")); var inst = db.Instances.First(); Assert.Equal(1, inst.AiRequestsThisMonth); Assert.Equal(DateTime.UtcNow.ToString("yyyy-MM"), inst.AiUsageMonthKey); } [Fact] public async Task Chat_SameMonth_IncrementsCounter() { using var db = DbContextFactory.Create(); var monthKey = DateTime.UtcNow.ToString("yyyy-MM"); db.Instances.Add(new Instance { Id = "i1", Name = "Musée", IsAssistant = true, DateCreation = DateTime.UtcNow, AiRequestsThisMonth = 3, AiUsageMonthKey = monthKey }); db.ApplicationInstances.Add(new ApplicationInstance { Id = "ai1", InstanceId = "i1", AppType = AppType.Tablet, IsAssistant = true, Languages = new List() }); db.SaveChanges(); await BuildController(db).Chat(MakeRequest("i1")); Assert.Equal(4, db.Instances.First().AiRequestsThisMonth); } // ── NOMINAL ────────────────────────────────────────────────────────── [Fact] public async Task Chat_Success_CallsAssistantServiceAndReturns200() { using var db = DbContextFactory.Create(); var mockService = new Mock(); mockService.Setup(s => s.ChatAsync(It.IsAny())).ReturnsAsync(FakeResponse); db.Instances.Add(new Instance { Id = "i1", Name = "Musée", IsAssistant = true, DateCreation = DateTime.UtcNow, AiUsageMonthKey = DateTime.UtcNow.ToString("yyyy-MM") }); db.ApplicationInstances.Add(new ApplicationInstance { Id = "ai1", InstanceId = "i1", AppType = AppType.Tablet, IsAssistant = true, Languages = new List() }); db.SaveChanges(); var result = await BuildController(db, mockService).Chat(MakeRequest("i1")); var ok = Assert.IsType(result); Assert.Equal(FakeResponse, ok.Value); mockService.Verify(s => s.ChatAsync(It.IsAny()), Times.Once); } } }