在 HPC Dashboard 的 Job Explorer 模块中,页面会展示多个 Job Card,每个卡片都有View Details等操作按钮。
如果直接定位按钮,可能匹配多个元素。因此,我采用了先定位 Job Card,再定位卡片内部按钮的方式。
1. 从 Job ID 定位所属卡片
首先,找到页面中第一个 Job ID:
constjobIdElement=page.getByText(/^Job ID:/).first();awaitexpect(jobIdElement).toBeVisible();constjobIdText=awaitjobIdElement.innerText();constjobId=jobIdText.replace(/^Job ID:\s*/,'').trim();接下来,通过 XPath 向上查找 Job Card:
constjobCard=jobIdElement.locator('xpath=ancestor::div[.//button[normalize-space()="View Details"]][1]');这里的关键是:
ancestor::div:查找当前元素的祖先div。.//button[...]:要求祖先容器内存在文本为View Details的按钮。normalize-space()可以避免这些空白差异影响定位:View Details[1]:选择满足条件的最近一个祖先div。
这样就能从 Job ID 找到对应的卡片容器,而不是在整个页面中操作按钮。
2. 封装 getFirstJob()
为了避免重复定位,我将这部分逻辑封装为公共方法:
asyncfunctiongetFirstJob(page:Page){constjobIdElement=page.getByText(/^Job ID:/).first();awaitexpect(jobIdElement).toBeVisible();constjobIdText=awaitjobIdElement.innerText();constjobId=jobIdText.replace(/^Job ID:\s*/,'').trim();constjobCard=jobIdElement.locator('xpath=ancestor::div[.//button[normalize-space()="View Details"]][1]');constjobName=(awaitjobCard.locator('h2, h3, h4').first().innerText()).trim();return{jobCard,jobName,jobId};}该方法返回三个值:jobCard、jobName和jobId,方便后续测试复用。
3. 在真实测试中使用 Locator Scoping
在 查看 Job 详情并导出 PDF测试中,我这样使用:
awaitopenJobsPage(page);const{jobCard,jobId}=awaitgetFirstJob(page);awaitjobCard.getByRole('button',{name:'View Details'}).click();awaitexpect(page.getByText(`Job ID:${jobId}`,{exact:true})).toBeVisible();这里的jobCard.getByRole()就是Locator Scoping(限定定位范围)。
它只在当前 Job Card 内查找View Details按钮,避免与其他卡片中的同名按钮混淆。
随后通过 Job ID 断言,验证打开的是对应 Job 的详情。
4. 小结
这次实践让我认识到,复杂页面的元素定位不能只关注单个按钮,还需要考虑它所属的业务容器。
先定位目标容器,再定位内部元素,是处理重复列表和卡片组件的一种实用方法。
目前getFirstJob()使用.first()获取首个 Job,后续如果需要测试指定 Job,可以进一步改成按 Job ID 精确查找。