using NSubstitute; using PnvPanel.Application.Common.Interfaces; using PnvPanel.Application.Support; using PnvPanel.Application.Support.ListMyTickets; using PnvPanel.Application.Tests.TestSupport; using PnvPanel.Domain.Support; using Xunit; namespace PnvPanel.Application.Tests.Support; public class ListMyTicketsQueryHandlerTests { private readonly IIdentityService _identityService = Substitute.For(); [Fact] public async Task Handle_ReturnsFirstMessageAsPreview_NotLastComment() { using var dbContext = InMemoryDbContextFactory.Create(); var userId = Guid.NewGuid(); var ticket = SupportTicket.CreateBugReport(userId); dbContext.SupportTickets.Add(ticket); var firstComment = TicketComment.Create(ticket.Id, userId, "исходное сообщение о баге"); dbContext.TicketComments.Add(firstComment); await dbContext.SaveChangesAsync(CancellationToken.None); // Гарантируем, что второй комментарий получит более поздний CreatedAt (UtcNow может // совпасть при быстром последовательном создании без явного clock-абстрагирования). await Task.Delay(5, CancellationToken.None); var replyComment = TicketComment.Create( ticket.Id, userId, "более поздний ответ администратора" ); dbContext.TicketComments.Add(replyComment); await dbContext.SaveChangesAsync(CancellationToken.None); _identityService .GetUserNamesAsync(Arg.Any>(), Arg.Any()) .Returns(new Dictionary { [userId] = "alice" }); var currentUser = FakeCurrentUser.Authenticated(userId, "alice"); var handler = new ListMyTicketsQueryHandler(dbContext, _identityService, currentUser); var result = await handler.Handle( new ListMyTicketsQuery(TypeFilter: null, StatusFilter: null, Page: 1, PageSize: 20), CancellationToken.None ); Assert.True(result.IsSuccess); var summary = Assert.Single(result.Value.Items); Assert.Equal("исходное сообщение о баге", summary.MessagePreview); } [Fact] public async Task Handle_TruncatesLongMessagePreview() { using var dbContext = InMemoryDbContextFactory.Create(); var userId = Guid.NewGuid(); var ticket = SupportTicket.CreateBugReport(userId); dbContext.SupportTickets.Add(ticket); var longBody = new string('x', 250); dbContext.TicketComments.Add(TicketComment.Create(ticket.Id, userId, longBody)); await dbContext.SaveChangesAsync(CancellationToken.None); _identityService .GetUserNamesAsync(Arg.Any>(), Arg.Any()) .Returns(new Dictionary { [userId] = "alice" }); var currentUser = FakeCurrentUser.Authenticated(userId, "alice"); var handler = new ListMyTicketsQueryHandler(dbContext, _identityService, currentUser); var result = await handler.Handle( new ListMyTicketsQuery(TypeFilter: null, StatusFilter: null, Page: 1, PageSize: 20), CancellationToken.None ); Assert.True(result.IsSuccess); var summary = Assert.Single(result.Value.Items); Assert.Equal(201, summary.MessagePreview!.Length); Assert.EndsWith("…", summary.MessagePreview); } }