loginPage.ts
4.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
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 期望的用户名(用于验证登录成功,可选,默认从环境变量 TEST_USER_NAME 获取)
* @param authFilePath 认证文件保存路径
*/
async performLogin(
phone: string,
userName?: string,
authFilePath: string = 'auth.json'
): Promise<void> {
const finalUserName = userName ?? process.env.TEST_USER_NAME;
if (!finalUserName) {
throw new Error('userName 参数未提供且 TEST_USER_NAME 环境变量未设置,请设置其中之一后再运行');
}
await this.loginWithPhone(phone);
await this.waitForLoginSuccess(finalUserName);
await this.saveAuthState(authFilePath);
}
}