using NSubstitute; using SIGCM2.Application.Abstractions.Persistence; using SIGCM2.Application.Audit; using SIGCM2.Application.Auth.Logout; namespace SIGCM2.Application.Tests.Auth.Logout; public class LogoutCommandHandlerTests { private readonly IRefreshTokenRepository _refreshRepo = Substitute.For(); private readonly ISecurityEventLogger _security = Substitute.For(); private readonly LogoutCommandHandler _handler; public LogoutCommandHandlerTests() { _handler = new LogoutCommandHandler(_refreshRepo, _security); } [Fact] public async Task Handle_RevokesAllActiveForUser() { _refreshRepo.RevokeAllActiveForUserAsync(42, Arg.Any()).Returns(3); var result = await _handler.Handle(new LogoutCommand(42)); Assert.True(result.Success); Assert.False(string.IsNullOrWhiteSpace(result.Mensaje)); await _refreshRepo.Received(1).RevokeAllActiveForUserAsync(42, Arg.Any()); } [Fact] public async Task Handle_NoActiveTokens_StillReturnsSuccess() { // 0 rows affected = idempotent logout _refreshRepo.RevokeAllActiveForUserAsync(Arg.Any(), Arg.Any()).Returns(0); var result = await _handler.Handle(new LogoutCommand(99)); Assert.True(result.Success); } }