using NSubstitute; using PnvPanel.Application.Billing; using PnvPanel.Application.Common.Interfaces; using PnvPanel.Application.Support; using PnvPanel.Application.Support.CreateExtensionRequest; using PnvPanel.Application.Tests.TestSupport; using PnvPanel.Domain.Support; using Xunit; namespace PnvPanel.Application.Tests.Support; public class CreateExtensionRequestTicketCommandHandlerTests { private readonly IIdentityService _identityService = Substitute.For(); private readonly IRealtimeNotifier _notifier = Substitute.For(); private readonly ITelegramNotifier _telegramNotifier = Substitute.For(); private static CurrentUserProfile Profile(Guid userId, bool billingEnabled) => new( userId, "alice", Guid.NewGuid(), "premium", IsActivated: true, IsBlocked: false, ConfigQuota: 5, PlanId: null, MaxIpLimit: 3, SubscriptionToken: "sub-token", BillingEnabled: billingEnabled, BillingPaidUntil: null, BillingSuspended: false ); [Fact] public async Task Handle_WhenBillingEnabled_CreatesTicketAndNotifiesAdmins() { using var dbContext = InMemoryDbContextFactory.Create(); var userId = Guid.NewGuid(); _identityService .GetProfileAsync(userId, Arg.Any()) .Returns(Profile(userId, billingEnabled: true)); var handler = new CreateExtensionRequestTicketCommandHandler( dbContext, _identityService, _notifier, _telegramNotifier, FakeCurrentUser.Authenticated(userId, "alice") ); var result = await handler.Handle( new CreateExtensionRequestTicketCommand(14, "нужно продлить"), CancellationToken.None ); Assert.True(result.IsSuccess); Assert.Equal(TicketType.ExtensionRequest, result.Value.Type); Assert.Equal(14, result.Value.RequestedDays); await _telegramNotifier .Received(1) .NotifyAdminsExtensionRequestCreatedAsync( Arg.Any(), "alice", 14, "нужно продлить", Arg.Any() ); } [Fact] public async Task Handle_WhenBillingNotEnabled_ReturnsNotEnabled() { using var dbContext = InMemoryDbContextFactory.Create(); var userId = Guid.NewGuid(); _identityService .GetProfileAsync(userId, Arg.Any()) .Returns(Profile(userId, billingEnabled: false)); var handler = new CreateExtensionRequestTicketCommandHandler( dbContext, _identityService, _notifier, _telegramNotifier, FakeCurrentUser.Authenticated(userId) ); var result = await handler.Handle( new CreateExtensionRequestTicketCommand(14, "нужно продлить"), CancellationToken.None ); Assert.False(result.IsSuccess); Assert.Equal(BillingErrors.NotEnabled, result.Error); } [Fact] public async Task Handle_WhenPendingExtensionRequestExists_ReturnsConflict() { using var dbContext = InMemoryDbContextFactory.Create(); var userId = Guid.NewGuid(); dbContext.SupportTickets.Add(SupportTicket.CreateExtensionRequest(userId, 7)); await dbContext.SaveChangesAsync(CancellationToken.None); _identityService .GetProfileAsync(userId, Arg.Any()) .Returns(Profile(userId, billingEnabled: true)); var handler = new CreateExtensionRequestTicketCommandHandler( dbContext, _identityService, _notifier, _telegramNotifier, FakeCurrentUser.Authenticated(userId) ); var result = await handler.Handle( new CreateExtensionRequestTicketCommand(3, "ещё заявка"), CancellationToken.None ); Assert.False(result.IsSuccess); Assert.Equal(SupportErrors.ExtensionRequestAlreadyPending, result.Error); } }