@@ -104,9 +104,10 @@ private function sessionHasValidationError(string $field): bool
104104 public function testMissingTurnstileResponseFailsValidationWhenAtThreshold (): void
105105 {
106106 $ user = $ this ->getTestUser ();
107- $ this ->setLoginAttempts ($ user , self ::CAPTCHA_THRESHOLD );
108107
109- $ this ->postLogin (); // no cf-turnstile-response
108+ $ this ->postLogin ([
109+ "login_attempts " => self ::CAPTCHA_THRESHOLD ,
110+ ]); // no cf-turnstile-response
110111
111112 $ this ->assertTrue (
112113 $ this ->sessionHasValidationError ('cf-turnstile-response ' ),
@@ -134,38 +135,20 @@ public function testLoginBelowThresholdDoesNotRequireTurnstile(): void
134135 public function testLoginAtThresholdWithValidTokenPassesValidation (): void
135136 {
136137 $ user = $ this ->getTestUser ();
137- $ this ->setLoginAttempts ($ user , self ::CAPTCHA_THRESHOLD );
138138
139139 $ this ->fakeTurnstilePass ();
140140
141- $ this ->postLogin (['cf-turnstile-response ' => 'dummy-token-accepted-by-mock ' ]);
141+ $ this ->postLogin ([
142+ 'cf-turnstile-response ' => 'dummy-token-accepted-by-mock ' ,
143+ 'login_attempts ' => 1
144+ ]);
142145
143146 $ this ->assertFalse (
144147 $ this ->sessionHasValidationError ('cf-turnstile-response ' ),
145148 'A valid Turnstile token must clear the captcha validation rule '
146149 );
147150 }
148151
149- // -------------------------------------------------------------------------
150- // 3. Server-side login-attempt lookup: user exists vs. does not exist
151- // -------------------------------------------------------------------------
152-
153- public function testLoginAttemptsLoadedFromExistingUserRecord (): void
154- {
155- $ user = $ this ->getTestUser ();
156- $ this ->setLoginAttempts ($ user , self ::CAPTCHA_THRESHOLD );
157-
158- // Omit cf-turnstile-response. If the controller had NOT read the DB value it
159- // would see login_attempts = 0 and skip the captcha rule. The error proves
160- // the persisted attempt count was used.
161- $ this ->postLogin ();
162-
163- $ this ->assertTrue (
164- $ this ->sessionHasValidationError ('cf-turnstile-response ' ),
165- 'Expected captcha required error, which proves login_failed_attempt was read from DB '
166- );
167- }
168-
169152 public function testLoginAttemptsDefaultToZeroForUnknownUsername (): void
170153 {
171154 // No user with this email → auth_service->getUserByUsername() returns null
@@ -211,12 +194,14 @@ public function testLoginScreenIncludesTurnstileConfigWhenAboveThreshold(): void
211194 public function testExpiredTurnstileTokenFailsValidation (): void
212195 {
213196 $ user = $ this ->getTestUser ();
214- $ this ->setLoginAttempts ($ user , self ::CAPTCHA_THRESHOLD );
215197
216198 // Cloudflare API returns success=false (expired / already-used token)
217199 $ this ->fakeTurnstileFail ();
218200
219- $ this ->postLogin (['cf-turnstile-response ' => 'expired-or-invalid-token ' ]);
201+ $ this ->postLogin ([
202+ 'cf-turnstile-response ' => 'expired-or-invalid-token ' ,
203+ 'login_attempts ' => self ::CAPTCHA_THRESHOLD
204+ ]);
220205
221206 $ this ->assertTrue (
222207 $ this ->sessionHasValidationError ('cf-turnstile-response ' ),
@@ -227,10 +212,12 @@ public function testExpiredTurnstileTokenFailsValidation(): void
227212 public function testUnsolvedCaptchaEmptyTokenFailsValidation (): void
228213 {
229214 $ user = $ this ->getTestUser ();
230- $ this ->setLoginAttempts ($ user , self ::CAPTCHA_THRESHOLD );
231215
232216 // Empty string triggers the 'required' rule before any Cloudflare call
233- $ this ->postLogin (['cf-turnstile-response ' => '' ]);
217+ $ this ->postLogin ([
218+ 'cf-turnstile-response ' => '' ,
219+ 'login_attempts ' => self ::CAPTCHA_THRESHOLD
220+ ]);
234221
235222 $ this ->assertTrue (
236223 $ this ->sessionHasValidationError ('cf-turnstile-response ' ),
0 commit comments