first commit
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using SequenceAuth.Lib;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace SequenceAuth.Lib.Tests;
|
||||
|
||||
public class SequenceManagerTests
|
||||
{
|
||||
private readonly Mock<ISequenceStore> _mockStore;
|
||||
private readonly SequenceManager _manager;
|
||||
|
||||
public SequenceManagerTests()
|
||||
{
|
||||
_mockStore = new Mock<ISequenceStore>();
|
||||
_manager = new SequenceManager(_mockStore.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ValidateAndRotateAsync_ValidToken_ReturnsSuccessAndGeneratesNewToken()
|
||||
{
|
||||
// Arrange
|
||||
var token = "valid-token";
|
||||
var nextToken = "pre-generated-next-token";
|
||||
var sequenceData = new SequenceData("user123", 100, SequenceState.Active, nextToken);
|
||||
|
||||
_mockStore.Setup(s => s.GetSequenceAsync(token))
|
||||
.ReturnsAsync(Option<SequenceData>.Some(sequenceData));
|
||||
|
||||
_mockStore.Setup(s => s.SaveSequenceAsync(It.IsAny<string>(), It.IsAny<SequenceData>()))
|
||||
.ReturnsAsync(StoreOutcome.Success);
|
||||
|
||||
// Act
|
||||
var result = await _manager.ValidateAndRotateAsync(token);
|
||||
|
||||
// Assert
|
||||
result.Outcome.Should().Be(ValidationOutcome.Success);
|
||||
result.NextSequence.State.Should().Be(OptionState.Some);
|
||||
result.NextSequence.Value.Should().Be(nextToken);
|
||||
|
||||
// Ensure the old sequence was marked as Rotated
|
||||
_mockStore.Verify(s => s.SaveSequenceAsync(token, It.Is<SequenceData>(d =>
|
||||
d.State == SequenceState.Rotated)), Times.Once);
|
||||
|
||||
// Ensure the new sequence was saved
|
||||
_mockStore.Verify(s => s.SaveSequenceAsync(nextToken, It.Is<SequenceData>(d =>
|
||||
d.State == SequenceState.Active)), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ValidateAndRotateAsync_RotatedToken_ReturnsCompromisedAndDestroysSession()
|
||||
{
|
||||
// Arrange
|
||||
var token = "compromised-token";
|
||||
var sequenceData = new SequenceData("user123", 100, SequenceState.Rotated, "some-next-token");
|
||||
|
||||
_mockStore.Setup(s => s.GetSequenceAsync(token))
|
||||
.ReturnsAsync(Option<SequenceData>.Some(sequenceData));
|
||||
|
||||
// Act
|
||||
var result = await _manager.ValidateAndRotateAsync(token);
|
||||
|
||||
// Assert
|
||||
result.Outcome.Should().Be(ValidationOutcome.CompromisedSequenceDetected);
|
||||
result.NextSequence.State.Should().Be(OptionState.None);
|
||||
|
||||
// Ensure InvalidateUserSessionsAsync was called for the user
|
||||
_mockStore.Verify(s => s.InvalidateUserSessionsAsync("user123"), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ValidateAndRotateAsync_MissingToken_ReturnsNotFound()
|
||||
{
|
||||
// Arrange
|
||||
var token = "invalid-token";
|
||||
|
||||
_mockStore.Setup(s => s.GetSequenceAsync(token))
|
||||
.ReturnsAsync(Option<SequenceData>.None());
|
||||
|
||||
// Act
|
||||
var result = await _manager.ValidateAndRotateAsync(token);
|
||||
|
||||
// Assert
|
||||
result.Outcome.Should().Be(ValidationOutcome.SequenceNotFound);
|
||||
result.NextSequence.State.Should().Be(OptionState.None);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user