loginPage.ts 3.91 KB
import { Page, Locator, expect } from '@playwright/test';
import { BasePage } from './basePage';

/**
 * 登录页面选择器
 */
const selectors = {
  phoneLoginTab: 'text=手机号登录/注册',
  confirmButton: 'text=确定',
  phoneInput: 'uni-input:has-text("请输入手机号") input',
  getCodeButton: 'uni-button:has-text("获取验证码")',
  loginButton: 'uni-button:has-text("登录")',
  userInfo: (userName: string) => `text=${userName}`,
};

/**
 * 登录页面类
 * 处理用户登录相关的操作
 */
export class LoginPage extends BasePage {
  // 定位器
  readonly phoneLoginTab: Locator;
  readonly confirmButton: Locator;
  readonly phoneInput: Locator;
  readonly getCodeButton: Locator;
  readonly loginButton: Locator;

  constructor(page: Page) {
    super(page);
    
    this.phoneLoginTab = page.getByText('手机号登录/注册');
    this.confirmButton = page.getByText('确定');
    this.phoneInput = page.locator('uni-input').filter({ hasText: '请输入手机号' }).getByRole('textbox');
    this.getCodeButton = page.locator('uni-button').filter({ hasText: '获取验证码' });
    this.loginButton = page.locator('uni-button').filter({ hasText: '登录' });
  }

  /**
   * 导航到登录页面
   */
  async goto(): Promise<void> {
    await this.navigate('/pages/login/index');
  }

  /**
   * 点击手机号登录标签
   */
  async clickPhoneLoginTab(): Promise<void> {
    await this.phoneLoginTab.click();
  }

  /**
   * 点击确认按钮
   */
  async clickConfirm(): Promise<void> {
    await this.confirmButton.click();
  }

  /**
   * 输入手机号
   * @param phone 手机号
   */
  async enterPhone(phone: string): Promise<void> {
    await this.phoneInput.click();
    await this.phoneInput.fill(phone);
  }

  /**
   * 点击获取验证码按钮
   */
  async clickGetCode(): Promise<void> {
    await this.getCodeButton.click();
  }

  /**
   * 点击登录按钮
   */
  async clickLogin(): Promise<void> {
    await this.loginButton.click();
  }

  /**
   * 半自动登录(自动填手机号,手动输验证码)
   * @param phone 手机号
   * @param timeout 等待登录成功的超时时间(毫秒)
   */
  async loginWithPhone(phone: string, timeout: number = 120000): Promise<void> {
    await this.goto();
    await this.clickPhoneLoginTab();
    await this.clickConfirm();
    await this.enterPhone(phone);
    await this.clickGetCode();
    
    console.log('请手动输入验证码,然后点击登录按钮...');
    
    // 等待登录成功(检测用户名出现)
    await this.page.locator('uni-button').filter({ hasText: '登录' }).click();
  }

  /**
   * 等待登录成功
   * @param userName 期望显示的用户名
   * @param timeout 超时时间
   */
  async waitForLoginSuccess(userName: string, timeout: number = 120000): Promise<void> {
    await expect(this.page.getByText(userName)).toBeVisible({ timeout });
  }

  /**
   * 检查是否已登录(通过检测用户名是否存在)
   * @param userName 用户名
   */
  async isLoggedIn(userName: string): Promise<boolean> {
    try {
      await expect(this.page.getByText(userName)).toBeVisible({ timeout: 5000 });
      return true;
    } catch {
      return false;
    }
  }

  /**
   * 保存认证状态到文件
   * @param filePath 保存路径
   */
  async saveAuthState(filePath: string = 'auth.json'): Promise<void> {
    await this.page.context().storageState({ path: filePath });
    console.log(`认证状态已保存到 ${filePath}`);
  }

  /**
   * 完整的登录流程(半自动)
   * @param phone 手机号
   * @param userName 期望的用户名(用于验证登录成功)
   * @param authFilePath 认证文件保存路径
   */
  async performLogin(
    phone: string, 
    userName: string = '赵xt', 
    authFilePath: string = 'auth.json'
  ): Promise<void> {
    await this.loginWithPhone(phone);
    await this.waitForLoginSuccess(userName);
    await this.saveAuthState(authFilePath);
  }
}