Files

137 lines
4.5 KiB
C#
Raw Permalink Normal View History

using SIGCM2.Domain.Entities;
namespace SIGCM2.Application.Tests.Domain;
public class RefreshTokenTests
{
// --- IssueForNewFamily ---
[Fact]
public void IssueForNewFamily_SetsNewFamilyIdAndExpiresAt()
{
var now = DateTime.UtcNow;
var ttl = TimeSpan.FromDays(7);
var token = RefreshToken.IssueForNewFamily(
usuarioId: 1,
tokenHash: "hash_abc",
now: now,
ttl: ttl,
createdByIp: "127.0.0.1",
userAgent: "Mozilla/5.0");
Assert.Equal(1, token.UsuarioId);
Assert.Equal("hash_abc", token.TokenHash);
Assert.NotEqual(Guid.Empty, token.FamilyId);
Assert.Equal(now, token.IssuedAt);
Assert.Equal(now + ttl, token.ExpiresAt);
Assert.Equal("127.0.0.1", token.CreatedByIp);
Assert.Equal("Mozilla/5.0", token.UserAgent);
Assert.Null(token.RevokedAt);
Assert.Null(token.ReplacedById);
}
[Fact]
public void IssueForNewFamily_TwoCallsProduceDifferentFamilyIds()
{
var now = DateTime.UtcNow;
var ttl = TimeSpan.FromDays(7);
var t1 = RefreshToken.IssueForNewFamily(1, "hash1", now, ttl, "127.0.0.1", null);
var t2 = RefreshToken.IssueForNewFamily(1, "hash2", now, ttl, "127.0.0.1", null);
Assert.NotEqual(t1.FamilyId, t2.FamilyId);
}
// --- IssueRotation ---
[Fact]
public void IssueRotation_InheritsFamilyIdAndExpiresAt()
{
var now = DateTime.UtcNow;
var original = RefreshToken.IssueForNewFamily(
1, "hash_original", now.AddHours(-2), TimeSpan.FromDays(7), "10.0.0.1", "UA1");
var rotationTime = now;
var rotated = RefreshToken.IssueRotation(
previous: original,
newTokenHash: "hash_new",
now: rotationTime,
createdByIp: "10.0.0.2",
userAgent: "UA2");
Assert.Equal(original.FamilyId, rotated.FamilyId); // same family
Assert.Equal(original.ExpiresAt, rotated.ExpiresAt); // ABSOLUTE — inherited
Assert.Equal(original.UsuarioId, rotated.UsuarioId);
Assert.Equal("hash_new", rotated.TokenHash);
Assert.Equal(rotationTime, rotated.IssuedAt);
Assert.Equal("10.0.0.2", rotated.CreatedByIp);
Assert.Equal("UA2", rotated.UserAgent);
Assert.Null(rotated.RevokedAt);
Assert.Null(rotated.ReplacedById);
}
// --- IsActive ---
[Fact]
public void IsActive_False_WhenRevoked()
{
var now = DateTime.UtcNow;
var token = RefreshToken.IssueForNewFamily(1, "h", now, TimeSpan.FromDays(7), "1.1.1.1", null);
token.MarkAsPersistedRevocation(now.AddSeconds(-1), replacedById: null);
Assert.False(token.IsActive(now));
Assert.True(token.IsRevoked);
}
[Fact]
public void IsActive_False_WhenExpired()
{
var now = DateTime.UtcNow;
// issued 8 days ago, ttl 7 days → expired yesterday
var token = RefreshToken.IssueForNewFamily(1, "h", now.AddDays(-8), TimeSpan.FromDays(7), "1.1.1.1", null);
Assert.False(token.IsActive(now));
Assert.True(token.IsExpired(now));
Assert.False(token.IsRevoked);
}
[Fact]
public void IsActive_True_WhenFreshAndNotRevoked()
{
var now = DateTime.UtcNow;
var token = RefreshToken.IssueForNewFamily(1, "h", now, TimeSpan.FromDays(7), "1.1.1.1", null);
Assert.True(token.IsActive(now.AddMinutes(1)));
Assert.False(token.IsRevoked);
Assert.False(token.IsExpired(now.AddMinutes(1)));
}
[Fact]
public void IsExpired_True_AtExpiresAt()
{
var now = DateTime.UtcNow;
var token = RefreshToken.IssueForNewFamily(1, "h", now, TimeSpan.FromDays(7), "1.1.1.1", null);
// exactly at ExpiresAt it is expired (>= boundary)
Assert.True(token.IsExpired(token.ExpiresAt));
// one second before: not expired
Assert.False(token.IsExpired(token.ExpiresAt.AddSeconds(-1)));
}
// --- MarkAsPersistedRevocation ---
[Fact]
public void MarkAsPersistedRevocation_SetsRevokedAtAndReplacedById()
{
var now = DateTime.UtcNow;
var token = RefreshToken.IssueForNewFamily(1, "h", now, TimeSpan.FromDays(7), "1.1.1.1", null);
token.MarkAsPersistedRevocation(now.AddSeconds(30), replacedById: 42);
Assert.Equal(now.AddSeconds(30), token.RevokedAt);
Assert.Equal(42, token.ReplacedById);
Assert.True(token.IsRevoked);
}
}