import { Page, Locator } from '@playwright/test'; export class LoginPage { readonly page: Page; readonly usernameInput: Locator; readonly passwordInput: Locator; readonly loginButton: Locator; readonly errorMessage: Locator; readonly logoutButton: Locator; constructor(page: Page) { this.page = page; this.usernameInput = page.locator('input[placeholder="请输入用户名"]'); this.passwordInput = page.locator('input[placeholder="请输入密码"]'); this.loginButton = page.locator('button:has-text("登录")'); this.errorMessage = page.locator('.el-message--error .el-message__content'); this.logoutButton = page.getByRole('button', { name: '退出登录' }); } async goto() { await this.page.goto('/login'); await this.page.waitForLoadState('networkidle'); } async login(username: string, password: string, maxRetries: number = 3) { let lastError: Error | null = null; for (let attempt = 1; attempt <= maxRetries; attempt++) { console.log(`Login attempt ${attempt}/${maxRetries}`); try { await this.usernameInput.fill(username); await this.passwordInput.fill(password); console.log('Filled username and password'); await this.loginButton.click(); console.log('Clicked login button'); await this.page.waitForURL(/\/(dashboard|\/)$/, { timeout: 30000 }); console.log('Successfully navigated to dashboard or home'); await this.page.waitForLoadState('networkidle'); console.log('Network idle achieved'); await this.page.waitForTimeout(2000); console.log('Login completed successfully'); return; } catch (error) { lastError = error as Error; console.log(`Login attempt ${attempt} failed:`, error); const currentUrl = this.page.url(); console.log('Current URL:', currentUrl); const errorMessage = await this.getErrorMessage(); if (errorMessage) { console.log('Login error message:', errorMessage); } const token = await this.page.evaluate(() => localStorage.getItem('token')); console.log('Token in localStorage:', token ? 'exists' : 'not found'); if (attempt < maxRetries) { console.log(`Waiting 2 seconds before retry...`); await this.page.waitForTimeout(2000); await this.goto(); console.log('Navigated back to login page for retry'); } } } console.log(`All ${maxRetries} login attempts failed`); throw lastError || new Error('Login failed after all retries'); } async getErrorMessage(): Promise { try { await this.page.waitForSelector('.el-message--error', { timeout: 10000 }); await this.page.waitForTimeout(500); const messageElement = await this.page.locator('.el-message--error .el-message__content').first(); const text = await messageElement.textContent(); return text; } catch { try { await this.page.waitForSelector('.el-message', { timeout: 5000 }); await this.page.waitForTimeout(500); const messageElement = await this.page.locator('.el-message .el-message__content').first(); const text = await messageElement.textContent(); return text; } catch { return null; } } } async logout() { const avatar = this.page.locator('.el-avatar'); await avatar.click(); await this.page.waitForTimeout(1000); const logoutButton = this.page.locator('.el-dropdown-menu').getByText('退出登录'); await logoutButton.click(); await this.page.waitForURL('**/login', { timeout: 10000 }); } async isLoggedIn(): Promise { return this.page.url().includes('/dashboard') || this.page.url() === this.page.url().split('?')[0].split('#')[0]; } }