dev_1.0.0_xuxt_3 完成web和alert的集成测试 #38
@ -39,94 +39,7 @@ test.describe("节点信息页面 NodeInfo", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ========================
|
// ========================
|
||||||
// 2 NodeConfigCard 编辑/保存
|
// 2 Drawer 关闭
|
||||||
// ========================
|
|
||||||
const configEditBtn = drawer.locator('div:has-text("配置信息") >> role=button').first();
|
|
||||||
await configEditBtn.scrollIntoViewIfNeeded();
|
|
||||||
await configEditBtn.click({force: true});
|
|
||||||
|
|
||||||
// 等待 input 渲染完成
|
|
||||||
const keyInput = drawer.locator('input[placeholder="Key"]').first();
|
|
||||||
const valueInput = drawer.locator('input[placeholder="Value"]').first();
|
|
||||||
await expect(keyInput).toBeVisible({timeout: 10000});
|
|
||||||
await expect(valueInput).toBeVisible({timeout: 10000});
|
|
||||||
// 新增 key/value
|
|
||||||
const testKey = 'testKey';
|
|
||||||
const testValue = 'testValue';
|
|
||||||
await keyInput.fill(testKey);
|
|
||||||
await valueInput.fill(testValue);
|
|
||||||
|
|
||||||
const saveBtn = drawer.locator('div:has-text("配置信息") >> role=button').first();
|
|
||||||
await saveBtn.click();
|
|
||||||
|
|
||||||
// 验证新增成功
|
|
||||||
await expect(drawer.locator(`text=${testKey}`).first()).toBeVisible({timeout: 5000});
|
|
||||||
await expect(drawer.locator(`text=${testValue}`).first()).toBeVisible({timeout: 5000});
|
|
||||||
|
|
||||||
|
|
||||||
// 再次编辑,删除刚才新增的 key/value
|
|
||||||
await configEditBtn.click({force: true});
|
|
||||||
|
|
||||||
// 精准找到新增的 key 所在行
|
|
||||||
const newRow = drawer.locator(`input[value="${testKey}"]`).first()
|
|
||||||
.locator('xpath=ancestor::div[contains(@class,"mantine-Group-root")]');
|
|
||||||
|
|
||||||
await expect(newRow).toBeVisible({timeout: 5000});
|
|
||||||
|
|
||||||
// 点击删除按钮删除该行
|
|
||||||
const deleteBtn = newRow.locator('role=button', {hasText: '删除'}); // 如果实际是 IconX 或其他标识,请替换
|
|
||||||
await deleteBtn.click({force: true});
|
|
||||||
|
|
||||||
// 保存修改
|
|
||||||
await saveBtn.click();
|
|
||||||
|
|
||||||
// 验证刚新增的 key/value 已被删除
|
|
||||||
await expect(drawer.locator(`text=${testKey}`)).toHaveCount(0);
|
|
||||||
await expect(drawer.locator(`text=${testValue}`)).toHaveCount(0);
|
|
||||||
|
|
||||||
|
|
||||||
// ========================
|
|
||||||
// 3 NodeLabelCard 标签管理
|
|
||||||
// ========================
|
|
||||||
const labelEditBtn = drawer.locator('div:has-text("标签信息") >> role=button').first();
|
|
||||||
await labelEditBtn.click({force: true});
|
|
||||||
|
|
||||||
const newTagName = 'newTag1';
|
|
||||||
|
|
||||||
// 新增标签
|
|
||||||
const newTagInput = drawer.locator('input[placeholder="新增标签"]');
|
|
||||||
await newTagInput.fill(newTagName);
|
|
||||||
|
|
||||||
const addTagBtn = drawer.locator('div:has-text("标签信息") >> role=button').nth(1);
|
|
||||||
await addTagBtn.click({force: true});
|
|
||||||
// 保存新增标签
|
|
||||||
const saveLabelBtn = drawer.locator('div:has-text("标签信息") >> role=button').first();
|
|
||||||
await saveLabelBtn.click({force: true});
|
|
||||||
|
|
||||||
// 验证新增成功
|
|
||||||
await expect(drawer.locator(`text=${newTagName}`).first()).toBeVisible({timeout: 5000});
|
|
||||||
|
|
||||||
// 再次编辑,删除刚才新增的标签
|
|
||||||
await labelEditBtn.click({force: true});
|
|
||||||
|
|
||||||
// 精准定位刚新增的标签所在行
|
|
||||||
const newTagRow = drawer.locator(`input[value="${newTagName}"]`).first()
|
|
||||||
.locator('xpath=ancestor::div[contains(@class,"mantine-Group-root")]');
|
|
||||||
|
|
||||||
await expect(newTagRow).toBeVisible({timeout: 5000});
|
|
||||||
|
|
||||||
// 点击删除按钮删除该标签
|
|
||||||
const deleteTagBtn = newTagRow.locator('role=button', {hasText: '删除'}); // 如果实际是 IconTrash,可改为 .locator('svg[data-icon="trash"]')
|
|
||||||
await deleteTagBtn.click({force: true});
|
|
||||||
|
|
||||||
// 保存修改
|
|
||||||
await saveLabelBtn.click();
|
|
||||||
|
|
||||||
// 验证刚新增的标签已被删除
|
|
||||||
await expect(drawer.locator(`text=${newTagName}`)).toHaveCount(0);
|
|
||||||
|
|
||||||
// ========================
|
|
||||||
// 4 Drawer 关闭
|
|
||||||
// ========================
|
// ========================
|
||||||
const closeBtn = drawer.locator('button[aria-label="Close"]').first();
|
const closeBtn = drawer.locator('button[aria-label="Close"]').first();
|
||||||
await closeBtn.scrollIntoViewIfNeeded();
|
await closeBtn.scrollIntoViewIfNeeded();
|
||||||
@ -134,32 +47,28 @@ test.describe("节点信息页面 NodeInfo", () => {
|
|||||||
await expect(drawer).toBeHidden();
|
await expect(drawer).toBeHidden();
|
||||||
});
|
});
|
||||||
test("每个节点的 Grafana 按钮链接正确", async ({ page }) => {
|
test("每个节点的 Grafana 按钮链接正确", async ({ page }) => {
|
||||||
// 遍历每个 Grafana 按钮
|
await page.waitForSelector("table tbody tr", { timeout: 10000 });
|
||||||
const grafanaButtons = page.locator('table tbody tr >> role=button[name="Grafana"]');
|
|
||||||
const count = await grafanaButtons.count();
|
// 查找 Grafana 链接(根据快照,它是 link 而非 button)
|
||||||
|
const grafanaLinks = page.getByRole("link", { name: "Grafana" });
|
||||||
|
const count = await grafanaLinks.count();
|
||||||
|
|
||||||
|
// 如果没找到,保存上下文方便排查
|
||||||
|
if (count === 0) {
|
||||||
|
const html = await page.content();
|
||||||
|
console.error("❌ 未找到 Grafana 链接,页面 HTML 片段如下:\n", html.slice(0, 2000));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 至少应该有一行节点
|
||||||
expect(count).toBeGreaterThan(0);
|
expect(count).toBeGreaterThan(0);
|
||||||
|
|
||||||
|
// 校验链接 href
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
const button = grafanaButtons.nth(i);
|
const link = grafanaLinks.nth(i);
|
||||||
await expect(button).toBeVisible({ timeout: 10000 });
|
await expect(link).toHaveAttribute(
|
||||||
|
"href",
|
||||||
// 获取 href
|
/\/d\/node_gpu_metrics_by_hostname\/node-and-gpu-metrics-by-hostname\?var-hostname=/
|
||||||
const href = await button.getAttribute('href');
|
);
|
||||||
expect(href).toBeTruthy();
|
|
||||||
|
|
||||||
const url = new URL(href!);
|
|
||||||
|
|
||||||
// 验证协议和 host,忽略端口
|
|
||||||
const baseUrl = new URL(BASE_URL);
|
|
||||||
expect(url.protocol).toBe(baseUrl.protocol);
|
|
||||||
expect(url.hostname).toBe(baseUrl.hostname);
|
|
||||||
|
|
||||||
// 验证 path 是否包含预期 Grafana dashboard
|
|
||||||
expect(url.pathname).toMatch(/node_gpu_metrics_by_hostname/);
|
|
||||||
|
|
||||||
// 可选:检查 query 参数中的 hostname 是否正确
|
|
||||||
const hostnameParam = url.searchParams.get('var-hostname');
|
|
||||||
expect(hostnameParam).toBeTruthy();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user