4、页面导航与菜单解析:菜单树结构分析、动态菜单加载处理、导航到规则管理页面
在IDP自助门户的自动化验证方案中,页面导航与菜单解析是脚本与UI交互的第一步。自动化测试脚本需要准确理解门户的菜单树结构,处理动态加载的菜单项,并最终可靠地导航到“准入控制规则管理”页面。本章将深入分析菜单树的DOM结构、动态加载机制以及自动化定位策略。
4.1 菜单树结构分析
IDP自助门户的左侧导航菜单采用多级树形结构,通常由 <ul> / <li> 嵌套列表实现,每个菜单项包含图标、文本标签和展开/折叠箭头。菜单树的核心层级关系如下表所示:
| 层级 | DOM 元素特征 | CSS 选择器示例 | 说明 |
|---|---|---|---|
| 一级菜单 | <li class="nav-item level-1"> |
.nav-item.level-1 |
顶级导航入口,如“安全策略”、“审计日志” |
| 二级菜单 | <li class="nav-item level-2"> |
.nav-item.level-2 |
一级菜单下的子分类,如“准入控制”、“流量过滤” |
| 三级菜单 | <li class="nav-item level-3"> |
.nav-item.level-3 |
具体功能页面入口,如“规则管理”、“黑白名单” |
| 展开/折叠触发器 | <span class="toggle-icon"> |
.toggle-icon |
点击后展开或收起子菜单列表 |
| 菜单文本标签 | <span class="menu-label"> |
.menu-label |
菜单项显示的文字内容 |
自动化定位建议: 优先使用菜单文本标签(
.menu-label)结合层级关系进行定位,避免依赖可能变化的图标类名或索引位置。例如,定位“规则管理”可使用 //span[@class='menu-label' and text()='规则管理']。
4.2 动态菜单加载处理
现代IDP门户的菜单通常采用异步加载(AJAX)方式,页面初始化时只渲染一级菜单,子菜单在用户点击展开后才从后端获取并动态插入DOM。这种机制给自动化测试带来两个核心挑战:
- 元素可见性延迟: 子菜单的DOM节点在点击展开前不存在,脚本需要等待异步请求完成。
- 加载状态判断: 展开动画或加载指示器(如旋转图标)可能干扰点击操作。
自动化处理策略:
- 显式等待(Explicit Wait): 使用
WebDriverWait配合expected_conditions.presence_of_element_located或visibility_of_element_located,等待目标菜单项出现在DOM中。 - 展开父级菜单: 在定位子菜单前,先确保其所有父级菜单已处于展开状态。可通过点击父级菜单的
.toggle-icon触发展开。 - 等待加载完成: 观察加载指示器(如
class="loading-spinner")的消失,或等待菜单容器内出现特定子节点。
以下是一个典型的动态菜单加载流程代码示例:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def expand_menu_and_navigate(driver, menu_path):
"""
展开菜单路径并导航到目标页面
:param driver: WebDriver 实例
:param menu_path: 菜单文本列表,如 ["安全策略", "准入控制", "规则管理"]
"""
for index, menu_text in enumerate(menu_path):
# 构造当前层级的菜单项定位器
if index == 0:
# 一级菜单直接可见
menu_item = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, f"//span[@class='menu-label' and text()='{menu_text}']"))
)
else:
# 子菜单需要等待父级展开后出现
menu_item = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.XPATH, f"//span[@class='menu-label' and text()='{menu_text}']"))
)
# 如果是最后一个菜单项,直接点击导航
if index == len(menu_path) - 1:
menu_item.click()
print(f"已导航到: {menu_text}")
else:
# 非最后一项,点击展开子菜单
# 查找父级 li 元素中的展开图标
parent_li = menu_item.find_element(By.XPATH, "./ancestor::li[contains(@class, 'nav-item')]")
toggle_icon = parent_li.find_element(By.CLASS_NAME, "toggle-icon")
toggle_icon.click()
print(f"已展开菜单: {menu_text}")
# 等待子菜单加载完成
WebDriverWait(driver, 5).until(
EC.presence_of_element_located((By.XPATH, f"//li[contains(@class, 'level-{index+2}')]"))
)
4.3 导航到规则管理页面
“规则管理”页面是准入控制规则自动化验证的核心操作界面。导航到该页面的标准路径为:安全策略 → 准入控制 → 规则管理。自动化脚本需要确保每一步都正确执行,并验证页面加载完成。
导航成功后的页面验证要点:
| 验证项 | 预期结果 | 自动化检查方式 |
|---|---|---|
| 页面标题 | 包含“规则管理”或“Rule Management” | driver.title 或页面内 <h1> 标签文本 |
| URL路径 | 包含 /policy/access-control/rules 等特征路径 |
driver.current_url 正则匹配 |
| 页面关键元素 | 规则列表表格、新增规则按钮、搜索框可见 | EC.visibility_of_element_located 检查 |
| 面包屑导航 | 显示“安全策略 > 准入控制 > 规则管理” | 定位面包屑容器,验证文本顺序 |
常见陷阱: 部分IDP门户在导航到规则管理页面时,会弹出“加载中”遮罩层或短暂的重定向。脚本在点击菜单后,应等待页面完全加载(如等待
document.readyState === 'complete' 或特定元素出现),再执行后续操作,避免因页面未就绪导致元素定位失败。
4.4 菜单解析最佳实践总结
综合以上分析,在自动化验证方案中处理页面导航与菜单解析时,应遵循以下原则:
- 结构化定位: 基于菜单文本和层级关系构建XPath,避免使用路径或索引。
- 显式等待优先: 对每个动态加载的菜单项使用
WebDriverWait,设置合理的超时时间(通常5-10秒)。 - 逐层展开: 从一级菜单开始,逐级展开并等待子菜单加载,最后点击目标菜单项。
- 页面验证: 导航后立即验证页面标题、URL或关键元素,确保导航成功。
- 异常处理: 捕获
TimeoutException和ElementClickInterceptedException,并加入重试机制。
扩展思考: 如果IDP门户使用了前端框架(如React、Vue)的虚拟DOM,菜单的DOM结构可能在每次展开时重新渲染。此时,建议在每次点击操作后重新获取元素引用,避免使用过时的
WebElement 对象。