using Xunit; using KArtSell.Modules.IdentityAccess.ManageIdentityAndRoles.Domain; namespace KArtSell.IdentityAccess.UnitTests.ManageIdentityAndRoles; /// /// AEG-VS-01-03: Domain policy tests for Identity state machine /// Pure domain logic (no infrastructure dependencies) /// public class IdentityStateTests { [Fact] public void CanTransitionFromUndefinedToActive() { var state = IdentityState.CreateUndefined(); var nextState = state.Register(); Assert.Equal(IdentityState.Active, nextState.Value); } [Fact] public void CanTransitionFromActiveToRequiresMfaSetup() { var state = IdentityState.CreateActive(); var nextState = state.RequestMfaSetup(); Assert.Equal(IdentityState.RequiresMfaSetup, nextState.Value); } [Fact] public void CanTransitionFromRequiresMfaSetupToMfaConfigured() { var state = IdentityState.Parse(IdentityState.RequiresMfaSetup); var nextState = state.CompleteMfaSetup(); Assert.Equal(IdentityState.MfaConfigured, nextState.Value); } [Fact] public void CanSuspendAndResumeMfa() { var state = IdentityState.Parse(IdentityState.MfaConfigured); var suspended = state.SuspendMfaTemporarily(); var resumed = suspended.ResumeMfa(); Assert.Equal(IdentityState.MfaSuspended, suspended.Value); Assert.Equal(IdentityState.MfaConfigured, resumed.Value); } [Fact] public void CanDeactivateFromMultipleStates() { var states = new[] { IdentityState.CreateActive(), IdentityState.Parse(IdentityState.RequiresMfaSetup), IdentityState.Parse(IdentityState.MfaConfigured), IdentityState.Parse(IdentityState.MfaSuspended) }; foreach (var state in states) { var deactivated = state.Deactivate(); Assert.Equal("INACTIVE", deactivated.Value); } } [Fact] public void CanRevokeFromInactive() { var state = IdentityState.CreateInactive(); var revoked = state.Revoke(); Assert.Equal(IdentityState.Revoked, revoked.Value); } [Fact] public void InvalidTransitionThrowsException() { var state = IdentityState.CreateUndefined(); Assert.Throws(() => state.RequestMfaSetup()); Assert.Throws(() => state.Deactivate()); } [Fact] public void CanQueryStateProperties() { var active = IdentityState.CreateActive(); Assert.True(active.IsActive()); Assert.False(active.IsInactive()); var mfaRequired = IdentityState.Parse(IdentityState.RequiresMfaSetup); Assert.True(mfaRequired.IsMfaRequired()); var revoked = IdentityState.Parse(IdentityState.Revoked); Assert.True(revoked.IsRevoked()); } [Fact] public void CanCheckCapabilities() { var undefined = IdentityState.CreateUndefined(); Assert.True(undefined.CanRegister()); var active = IdentityState.CreateActive(); Assert.True(active.CanReceiveRoles()); Assert.False(active.CanRegister()); var revoked = IdentityState.Parse(IdentityState.Revoked); Assert.False(revoked.CanReceiveRoles()); } [Theory] [InlineData(IdentityState.Undefined)] [InlineData(IdentityState.Active)] [InlineData(IdentityState.RequiresMfaSetup)] [InlineData(IdentityState.MfaConfigured)] [InlineData(IdentityState.MfaSuspended)] [InlineData(IdentityState.Inactive)] [InlineData(IdentityState.Revoked)] public void CanParseAllValidStates(string stateValue) { var state = IdentityState.Parse(stateValue); Assert.Equal(stateValue, state.Value); } [Fact] public void InvalidStateThrowsException() { Assert.Throws(() => IdentityState.Parse("INVALID_STATE")); } [Fact] public void StateIsValueObject() { var state1 = IdentityState.CreateActive(); var state2 = IdentityState.Parse(IdentityState.Active); Assert.Equal(state1, state2); } }