using NSubstitute; using PnvPanel.Application.Activation; using PnvPanel.Application.Admin.Activation; using PnvPanel.Application.Auth; using PnvPanel.Application.Common.Interfaces; using PnvPanel.Application.Common.Models; using PnvPanel.Application.Tests.TestSupport; using PnvPanel.Domain.Activation; using Xunit; namespace PnvPanel.Application.Tests.Activation; public class ApproveActivationCommandHandlerTests { private readonly IIdentityService _identityService = Substitute.For(); private readonly IRealtimeNotifier _notifier = Substitute.For(); private readonly ITelegramNotifier _telegramNotifier = Substitute.For(); private readonly ICurrentUser _currentUser = Substitute.For(); [Fact] public async Task Handle_WhenPending_ApprovesActivatesUserAndNotifies() { using var dbContext = InMemoryDbContextFactory.Create(); var adminId = Guid.NewGuid(); var request = ActivationRequest.Create(Guid.NewGuid(), "please"); dbContext.ActivationRequests.Add(request); await dbContext.SaveChangesAsync(CancellationToken.None); _currentUser.UserId.Returns(adminId); _identityService .ActivateUserAsync(request.UserId, adminId, Arg.Any()) .Returns(Result.Success()); var handler = new ApproveActivationCommandHandler( dbContext, _identityService, _notifier, _telegramNotifier, _currentUser ); var result = await handler.Handle( new ApproveActivationCommand(request.Id), CancellationToken.None ); Assert.True(result.IsSuccess); Assert.Equal(ActivationStatus.Approved, request.Status); await _notifier .Received(1) .NotifyUserActivatedAsync(request.UserId, Arg.Any()); } [Fact] public async Task Handle_WhenRequestNotFound_ReturnsNotFound() { using var dbContext = InMemoryDbContextFactory.Create(); _currentUser.UserId.Returns(Guid.NewGuid()); var handler = new ApproveActivationCommandHandler( dbContext, _identityService, _notifier, _telegramNotifier, _currentUser ); var result = await handler.Handle( new ApproveActivationCommand(Guid.NewGuid()), CancellationToken.None ); Assert.False(result.IsSuccess); Assert.Equal(ActivationErrors.NotFound, result.Error); } [Fact] public async Task Handle_WhenAlreadyDecided_ReturnsConflict() { using var dbContext = InMemoryDbContextFactory.Create(); var request = ActivationRequest.Create(Guid.NewGuid(), null); request.Approve(Guid.NewGuid()); dbContext.ActivationRequests.Add(request); await dbContext.SaveChangesAsync(CancellationToken.None); _currentUser.UserId.Returns(Guid.NewGuid()); var handler = new ApproveActivationCommandHandler( dbContext, _identityService, _notifier, _telegramNotifier, _currentUser ); var result = await handler.Handle( new ApproveActivationCommand(request.Id), CancellationToken.None ); Assert.False(result.IsSuccess); Assert.Equal(ActivationErrors.AlreadyDecided, result.Error); } [Fact] public async Task Handle_WhenActivateUserFails_PropagatesFailureWithoutNotifying() { using var dbContext = InMemoryDbContextFactory.Create(); var adminId = Guid.NewGuid(); var request = ActivationRequest.Create(Guid.NewGuid(), null); dbContext.ActivationRequests.Add(request); await dbContext.SaveChangesAsync(CancellationToken.None); _currentUser.UserId.Returns(adminId); var failure = Error.NotFound("User.NotFound", "Пользователь не найден."); _identityService .ActivateUserAsync(request.UserId, adminId, Arg.Any()) .Returns(Result.Failure(failure)); var handler = new ApproveActivationCommandHandler( dbContext, _identityService, _notifier, _telegramNotifier, _currentUser ); var result = await handler.Handle( new ApproveActivationCommand(request.Id), CancellationToken.None ); Assert.False(result.IsSuccess); Assert.Equal(failure, result.Error); await _notifier .DidNotReceive() .NotifyUserActivatedAsync(Arg.Any(), Arg.Any()); } }