using LightBDD.Framework; using LightBDD.Framework.Scenarios; using LightBDD.MsTest3; using PlanTempus.X.Services; using Shouldly; namespace PlanTempus.X.BDD.FeatureFixtures; [TestClass] [FeatureDescription(@"As a system administrator I want to ensure account security is maintained So users' data remains protected")] public partial class AccountSecuritySpecs : FeatureFixture { IUserService _userService; IEmailService _emailService; IOrganizationService _organizationService; IAuthService _authService; protected User _currentUser; protected DateTime? _lockoutEnd; protected bool _isLocked; protected bool _loginSuccessful; public async Task Given_user_exists(string email) { _currentUser = await _userService.GetUserByEmailAsync(email); if (_currentUser == null) { _currentUser = await _userService.CreateUserAsync(email, "Test User"); } } public async Task When_I_attempt_5_failed_logins_within_5_minutes() { for (var i = 0; i < 5; i++) { try { await _authService.AttemptLoginAsync(_currentUser.Email, "WrongPassword"); } catch { // Expected exception with wrong password } } } public async Task Then_the_account_should_be_locked() { _currentUser = _userService.GetUserByEmail(_currentUser.Email); _isLocked = _currentUser.IsLocked; _isLocked.ShouldBeTrue(); await Task.CompletedTask; } public async Task And_lockout_end_should_be_set() { _lockoutEnd = _currentUser.LockoutEnd; _lockoutEnd.ShouldNotBeNull(); _lockoutEnd.Value.ShouldBeGreaterThan(DateTime.UtcNow); await Task.CompletedTask; } public async Task And_subsequent_login_attempts_should_fail_until_lockout_end() { try { _loginSuccessful = await _authService.AttemptLoginAsync(_currentUser.Email, _currentUser.Password); } catch { _loginSuccessful = false; } _loginSuccessful.ShouldBeFalse(); } }