Files
张翔 08ea5fbe98 feat(admin): 添加用户管理相关文件
添加用户管理视图、API和状态管理文件
2026-03-28 14:37:29 +08:00

251 lines
8.1 KiB
TypeScript

import { Page } from '@playwright/test';
import { BasePage } from './base-page';
import { FormHelper } from '../helpers/form-helper';
import { TableHelper } from '../helpers/table-helper';
import { ScreenshotHelper } from '../helpers/screenshot-helper';
import { testLogger } from '../core/test-logger';
export class UserManagementPage extends BasePage {
private formHelper: FormHelper;
private tableHelper: TableHelper;
private screenshotHelper: ScreenshotHelper;
private readonly selectors = {
userTable: '[data-testid="user-table"]',
addUserButton: '[data-testid="add-user-button"]',
editButton: 'button:has-text("编辑")',
deleteButton: 'button:has-text("删除")',
searchInput: '[data-testid="username-search-input"]',
emailSearchInput: '[data-testid="email-search-input"]',
statusSelect: '[data-testid="status-select"]',
searchButton: '[data-testid="search-button"]',
resetButton: '[data-testid="reset-button"]',
modal: '.ant-modal',
modalTitle: '.ant-modal-title',
modalConfirmButton: '.ant-modal .ant-btn-primary',
modalCancelButton: '.ant-modal .ant-btn-default',
successMessage: '.ant-message-success',
errorMessage: '.ant-message-error',
pagination: '.ant-pagination',
userForm: '.user-form',
usernameInput: 'input[name="username"]',
passwordInput: 'input[name="password"]',
emailInput: 'input[name="email"]',
phoneInput: 'input[name="phone"]',
realNameInput: 'input[name="realName"]',
statusSelect: 'select[name="status"]',
roleSelect: 'select[name="roleIds"]'
};
constructor(page: Page) {
super(page);
this.formHelper = new FormHelper(page);
this.tableHelper = new TableHelper(page);
this.screenshotHelper = new ScreenshotHelper(page);
}
async navigate(): Promise<void> {
testLogger.info('导航到用户管理页面');
await super.navigate('/system/user');
}
async waitForLoad(): Promise<void> {
testLogger.info('等待用户管理页面加载');
try {
await this.page.waitForSelector(this.selectors.userTable, {
state: 'visible',
timeout: this.timeout.default
});
testLogger.info('用户管理页面加载完成');
} catch (error) {
testLogger.error('用户管理页面加载超时', error as Error);
await this.screenshotHelper.takeScreenshot('user-management-load-error');
throw error;
}
}
async clickAddUser(): Promise<void> {
testLogger.info('点击新增用户按钮');
try {
await this.page.waitForSelector(this.selectors.addUserButton, {
state: 'visible',
timeout: this.timeout.element
});
await this.page.click(this.selectors.addUserButton);
await this.page.waitForSelector(this.selectors.modal, {
state: 'visible',
timeout: this.timeout.element
});
testLogger.info('新增用户对话框已打开');
} catch (error) {
testLogger.error('点击新增用户按钮失败', error as Error);
await this.screenshotHelper.takeScreenshot('click-add-user-error');
throw error;
}
}
async clickEditUser(rowIndex: number): Promise<void> {
testLogger.info(`点击编辑用户按钮,行索引: ${rowIndex}`);
try {
const editButtons = this.page.locator(this.selectors.editButton);
await editButtons.nth(rowIndex).waitFor({ state: 'visible', timeout: this.timeout.element });
await editButtons.nth(rowIndex).click();
await this.page.waitForSelector(this.selectors.modal, {
state: 'visible',
timeout: this.timeout.element
});
testLogger.info('编辑用户对话框已打开');
} catch (error) {
testLogger.error(`点击编辑用户按钮失败,行索引: ${rowIndex}`, error as Error);
await this.screenshotHelper.takeScreenshot(`click-edit-user-${rowIndex}-error`);
throw error;
}
}
async clickDeleteUser(rowIndex: number): Promise<void> {
testLogger.info(`点击删除用户按钮,行索引: ${rowIndex}`);
try {
const deleteButtons = this.page.locator(this.selectors.deleteButton);
await deleteButtons.nth(rowIndex).waitFor({ state: 'visible', timeout: this.timeout.element });
await deleteButtons.nth(rowIndex).click();
testLogger.info('删除确认对话框已打开');
} catch (error) {
testLogger.error(`点击删除用户按钮失败,行索引: ${rowIndex}`, error as Error);
await this.screenshotHelper.takeScreenshot(`click-delete-user-${rowIndex}-error`);
throw error;
}
}
async confirmDelete(): Promise<void> {
testLogger.info('确认删除用户');
try {
await this.page.waitForSelector(this.selectors.modalConfirmButton, {
state: 'visible',
timeout: this.timeout.element
});
await this.page.click(this.selectors.modalConfirmButton);
await this.page.waitForSelector(this.selectors.modal, {
state: 'hidden',
timeout: this.timeout.element
});
testLogger.info('用户删除确认成功');
} catch (error) {
testLogger.error('确认删除用户失败', error as Error);
await this.screenshotHelper.takeScreenshot('confirm-delete-error');
throw error;
}
}
async searchUser(keyword: string): Promise<void> {
testLogger.info(`搜索用户,关键词: ${keyword}`);
try {
await this.page.waitForSelector(this.selectors.searchInput, {
state: 'visible',
timeout: this.timeout.element
});
await this.page.fill(this.selectors.searchInput, keyword);
await this.page.click(this.selectors.searchButton);
await this.page.waitForLoadState('networkidle', {
timeout: this.timeout.network
});
testLogger.info('用户搜索完成');
} catch (error) {
testLogger.error(`搜索用户失败,关键词: ${keyword}`, error as Error);
await this.screenshotHelper.takeScreenshot('search-user-error');
throw error;
}
}
async resetSearch(): Promise<void> {
testLogger.info('重置搜索条件');
try {
await this.page.waitForSelector(this.selectors.resetButton, {
state: 'visible',
timeout: this.timeout.element
});
await this.page.click(this.selectors.resetButton);
await this.page.waitForLoadState('networkidle', {
timeout: this.timeout.network
});
testLogger.info('搜索条件已重置');
} catch (error) {
testLogger.error('重置搜索条件失败', error as Error);
await this.screenshotHelper.takeScreenshot('reset-search-error');
throw error;
}
}
async getSuccessMessage(): Promise<string> {
testLogger.debug('获取成功消息');
try {
const successElement = this.page.locator(this.selectors.successMessage);
await successElement.waitFor({ state: 'visible', timeout: this.timeout.element });
const message = await successElement.textContent();
testLogger.debug(`成功消息: ${message}`);
return message || '';
} catch (error) {
testLogger.error('获取成功消息失败', error as Error);
return '';
}
}
async getErrorMessage(): Promise<string> {
testLogger.debug('获取错误消息');
try {
const errorElement = this.page.locator(this.selectors.errorMessage);
await errorElement.waitFor({ state: 'visible', timeout: this.timeout.element });
const message = await errorElement.textContent();
testLogger.debug(`错误消息: ${message}`);
return message || '';
} catch (error) {
testLogger.error('获取错误消息失败', error as Error);
return '';
}
}
async getUserCount(): Promise<number> {
testLogger.debug('获取用户数量');
try {
const count = await this.tableHelper.getRowCount(this.selectors.userTable);
testLogger.debug(`用户数量: ${count}`);
return count;
} catch (error) {
testLogger.error('获取用户数量失败', error as Error);
return 0;
}
}
}