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 { IAccountService _accountService; IEmailService _emailService; IOrganizationService _organizationService; IAuthService _authService; protected Account _currentAccount; protected DateTime? _lockoutEnd; protected bool _isLocked; protected bool _loginSuccessful; public async Task Given_account_exists(string email) { _currentAccount = await _accountService.GetAccountByEmailAsync(email); if (_currentAccount == null) { _currentAccount = await _accountService.CreateAccountAsync(email, "TestPassword123!"); } } public async Task When_I_attempt_5_failed_logins_within_5_minutes() { for (var i = 0; i < 5; i++) { try { await _authService.AttemptLoginAsync(_currentAccount.Email, "WrongPassword"); } catch { // Expected exception with wrong password } } } public async Task Then_the_account_should_be_locked() { _currentAccount = _accountService.GetAccountByEmail(_currentAccount.Email); _isLocked = _currentAccount.IsLocked; _isLocked.ShouldBeTrue(); await Task.CompletedTask; } public async Task And_lockout_end_should_be_set() { _lockoutEnd = _currentAccount.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(_currentAccount.Email, _currentAccount.Password); } catch { _loginSuccessful = false; } _loginSuccessful.ShouldBeFalse(); } }