api()->loginWeb(DatabaseSeeder::ADMIN_USERNAME, DatabaseSeeder::PASSWORD); $this->assertApiOk($res); $this->assertNotEmpty($res['data']['token']); $this->assertSame('admin', $res['data']['role']); } public function testInvalidCredentials(): void { $res = $this->api()->loginWeb(DatabaseSeeder::ADMIN_USERNAME, 'wrong'); $this->assertApiError($res, 'INVALID_CREDENTIALS', 401); } public function testCoachBlockedOnWebClient(): void { $res = $this->api()->loginWeb(DatabaseSeeder::COACH_USERNAME, DatabaseSeeder::PASSWORD); $this->assertApiError($res, 'FORBIDDEN', 403); } public function testRateLimitAfterFailures(): void { require_once dirname(__DIR__, 2) . '/lib/settings.php'; [$pdo, $tmpDb, $lockFp] = qdb_open(true); qdb_settings_save_on_pdo($pdo, qdb_settings_validate_and_merge([ 'login_max_attempts' => 2, 'login_window_seconds' => 600, 'login_lockout_seconds' => 600, ], qdb_settings_get_on_pdo($pdo))); qdb_save($tmpDb, $lockFp); $this->api()->loginWeb('rate_user', 'bad1'); $this->api()->loginWeb('rate_user', 'bad2'); $res = $this->api()->loginWeb('rate_user', 'bad3'); $this->assertApiError($res, 'RATE_LIMITED', 429); } public function testMissingFields(): void { $res = $this->api()->request('POST', 'auth/login', ['username' => '']); $this->assertApiError($res, 'MISSING_FIELDS', 400); } }