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 MenuManagementPage extends BasePage { private formHelper: FormHelper; private tableHelper: TableHelper; private screenshotHelper: ScreenshotHelper; private readonly selectors = { menuTree: '.menu-tree', menuTable: '.menu-table', addMenuButton: 'button:has-text("新增")', editButton: 'button:has-text("编辑")', deleteButton: 'button:has-text("删除")', searchInput: 'input[placeholder*="搜索"]', searchButton: 'button:has-text("查询")', resetButton: 'button:has-text("重置")', modal: '.ant-modal', modalTitle: '.ant-modal-title', modalConfirmButton: '.ant-modal-confirm-btn', modalCancelButton: '.ant-modal-cancel-btn', successMessage: '.ant-message-success', errorMessage: '.ant-message-error', menuForm: '.menu-form', menuNameInput: 'input[name="menuName"]', menuTypeSelect: 'select[name="menuType"]', menuIconInput: 'input[name="icon"]', orderNumInput: 'input[name="orderNum"]', pathInput: 'input[name="path"]', componentInput: 'input[name="component"]', statusSelect: 'select[name="status"]', visibleSelect: 'select[name="visible"]', remarkInput: 'textarea[name="remark"]', treeNode: '.ant-tree-node', treeExpandButton: '.ant-tree-switcher' }; constructor(page: Page) { super(page); this.formHelper = new FormHelper(page); this.tableHelper = new TableHelper(page); this.screenshotHelper = new ScreenshotHelper(page); } async navigate(): Promise { testLogger.info('导航到菜单管理页面'); await super.navigate('/system/menu'); } async waitForLoad(): Promise { testLogger.info('等待菜单管理页面加载'); try { await this.page.waitForSelector(this.selectors.menuTree, { state: 'visible', timeout: this.timeout.default }); testLogger.info('菜单管理页面加载完成'); } catch (error) { testLogger.error('菜单管理页面加载超时', error as Error); await this.screenshotHelper.takeScreenshot('menu-management-load-error'); throw error; } } async clickAddMenu(): Promise { testLogger.info('点击新增菜单按钮'); try { await this.page.waitForSelector(this.selectors.addMenuButton, { state: 'visible', timeout: this.timeout.element }); await this.page.click(this.selectors.addMenuButton); 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-menu-error'); throw error; } } async clickEditMenu(menuName: string): Promise { testLogger.info(`点击编辑菜单按钮,菜单名称: ${menuName}`); try { const editButtons = this.page.locator(this.selectors.editButton); await editButtons.first().waitFor({ state: 'visible', timeout: this.timeout.element }); await editButtons.first().click(); await this.page.waitForSelector(this.selectors.modal, { state: 'visible', timeout: this.timeout.element }); testLogger.info('编辑菜单对话框已打开'); } catch (error) { testLogger.error(`点击编辑菜单按钮失败,菜单名称: ${menuName}`, error as Error); await this.screenshotHelper.takeScreenshot(`click-edit-menu-${menuName}-error`); throw error; } } async clickDeleteMenu(menuName: string): Promise { testLogger.info(`点击删除菜单按钮,菜单名称: ${menuName}`); try { const deleteButtons = this.page.locator(this.selectors.deleteButton); await deleteButtons.first().waitFor({ state: 'visible', timeout: this.timeout.element }); await deleteButtons.first().click(); testLogger.info('删除确认对话框已打开'); } catch (error) { testLogger.error(`点击删除菜单按钮失败,菜单名称: ${menuName}`, error as Error); await this.screenshotHelper.takeScreenshot(`click-delete-menu-${menuName}-error`); throw error; } } async confirmDelete(): Promise { 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 searchMenu(keyword: string): Promise { 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-menu-error'); throw error; } } async expandTreeNode(nodeIndex: number): Promise { testLogger.info(`展开树节点,索引: ${nodeIndex}`); try { const expandButtons = this.page.locator(this.selectors.treeExpandButton); await expandButtons.nth(nodeIndex).waitFor({ state: 'visible', timeout: this.timeout.element }); await expandButtons.nth(nodeIndex).click(); testLogger.info(`树节点已展开,索引: ${nodeIndex}`); } catch (error) { testLogger.error(`展开树节点失败,索引: ${nodeIndex}`, error as Error); await this.screenshotHelper.takeScreenshot(`expand-tree-node-${nodeIndex}-error`); throw error; } } async getSuccessMessage(): Promise { 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 { 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 getMenuCount(): Promise { testLogger.debug('获取菜单数量'); try { const count = await this.tableHelper.getRowCount(this.selectors.menuTable); testLogger.debug(`菜单数量: ${count}`); return count; } catch (error) { testLogger.error('获取菜单数量失败', error as Error); return 0; } } async getTreeNodeCount(): Promise { testLogger.debug('获取树节点数量'); try { const treeNodes = this.page.locator(this.selectors.treeNode); const count = await treeNodes.count(); testLogger.debug(`树节点数量: ${count}`); return count; } catch (error) { testLogger.error('获取树节点数量失败', error as Error); return 0; } } }