1
0
Files
nex/frontend/e2e/providers.spec.ts
lanyuanxiaoyao 5dd26d29a7 test: 修复单元测试并补充完善 E2E 测试用例
- 修复 5 个单元测试失败:ProviderForm 表单提交超时、ModelForm 初始值检查、
  StatsTable Select 交互、ProviderTable 删除确认超时
- 适配 Ant Design 6 的 DOM 结构变化和异步行为
- 补充 E2E 测试从 6 个扩展到 32 个,覆盖供应商 CRUD、模型管理、
  表单验证、错误处理、边界情况、用量统计筛选等完整用户流程
- 发现并处理 Ant Design 6 按钮文本渲染带空格的兼容性问题
2026-04-16 16:27:09 +08:00

137 lines
5.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { test, expect } from '@playwright/test';
// 辅助在对话框内定位输入框Ant Design 6 的 Modal + Form
function formInputs(page: import('@playwright/test').Page) {
const dialog = page.getByRole('dialog');
return {
id: dialog.getByRole('textbox', { name: /ID/ }),
name: dialog.getByRole('textbox', { name: /名称/ }),
apiKey: dialog.locator('input[type="password"]'),
baseUrl: dialog.getByRole('textbox', { name: /Base URL/ }),
// Ant Design 6 按钮文字带空格:"保 存"、"取 消"
saveBtn: dialog.locator('.ant-modal-footer').getByRole('button').last(),
cancelBtn: dialog.locator('.ant-modal-footer').getByRole('button').first(),
};
}
test.describe('供应商管理', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/providers');
await expect(page.getByRole('heading', { name: '供应商管理' })).toBeVisible();
});
test('应显示供应商管理页面', async ({ page }) => {
await expect(page.getByText('供应商列表')).toBeVisible();
});
test('应显示添加供应商按钮', async ({ page }) => {
await expect(page.getByRole('button', { name: '添加供应商' })).toBeVisible();
});
test('应通过顶部导航切换页面', async ({ page }) => {
await page.getByText('用量统计').click();
await expect(page.getByRole('heading', { name: '用量统计' })).toBeVisible();
await page.getByText('供应商管理').click();
await expect(page.getByRole('heading', { name: '供应商管理' })).toBeVisible();
});
test('应能打开添加供应商对话框', async ({ page }) => {
await page.getByRole('button', { name: '添加供应商' }).click();
const dialog = page.getByRole('dialog');
await expect(dialog).toBeVisible();
await expect(dialog.getByText('添加供应商')).toBeVisible();
await expect(formInputs(page).id).toBeVisible();
await expect(formInputs(page).name).toBeVisible();
await expect(formInputs(page).apiKey).toBeVisible();
await expect(formInputs(page).baseUrl).toBeVisible();
});
test('应验证供应商表单必填字段', async ({ page }) => {
await page.getByRole('button', { name: '添加供应商' }).click();
await expect(page.getByRole('dialog')).toBeVisible();
await formInputs(page).saveBtn.click();
await expect(page.getByText('请输入供应商 ID')).toBeVisible();
await expect(page.getByText('请输入名称')).toBeVisible();
await expect(page.getByText('请输入 API Key')).toBeVisible();
await expect(page.getByText('请输入 Base URL')).toBeVisible();
});
test('应验证URL格式', async ({ page }) => {
await page.getByRole('button', { name: '添加供应商' }).click();
await expect(page.getByRole('dialog')).toBeVisible();
const inputs = formInputs(page);
await inputs.id.fill('test-provider');
await inputs.name.fill('Test Provider');
await inputs.apiKey.fill('sk-test-key');
await inputs.baseUrl.fill('invalid-url');
await inputs.saveBtn.click();
await expect(page.getByText('请输入有效的 URL')).toBeVisible();
});
test('应能取消添加供应商', async ({ page }) => {
await page.getByRole('button', { name: '添加供应商' }).click();
await expect(page.getByRole('dialog')).toBeVisible();
await formInputs(page).id.fill('test-provider');
await formInputs(page).cancelBtn.click();
await expect(page.getByRole('dialog')).not.toBeVisible();
});
test('应显示供应商列表中的信息', async ({ page }) => {
await expect(page.locator('.ant-table')).toBeVisible();
const tableHeaders = page.locator('.ant-table-thead th');
const count = await tableHeaders.count();
expect(count).toBeGreaterThanOrEqual(3);
});
test('应能展开供应商查看模型列表', async ({ page }) => {
const expandBtns = page.locator('.ant-table-row-expand-icon');
const count = await expandBtns.count();
if (count > 0) {
await expandBtns.first().click();
await expect(page.locator('.ant-table-expanded-row').first()).toBeVisible();
} else {
test.skip();
}
});
test('应能打开编辑供应商对话框', async ({ page }) => {
const editBtns = page.locator('.ant-table-tbody button:has-text("编辑")');
const count = await editBtns.count();
if (count > 0) {
await editBtns.first().click();
const dialog = page.getByRole('dialog');
await expect(dialog).toBeVisible();
await expect(dialog.getByText('编辑供应商')).toBeVisible();
await expect(formInputs(page).id).toBeDisabled();
} else {
test.skip();
}
});
test('应显示删除确认对话框', async ({ page }) => {
const deleteBtns = page.locator('.ant-table-tbody button:has-text("删除")');
const count = await deleteBtns.count();
if (count > 0) {
await deleteBtns.first().click();
await expect(page.getByText('确定要删除这个供应商吗?')).toBeVisible();
// Popconfirm 按钮也带空格:"确 定"、"取 消"
await page.locator('.ant-popconfirm-buttons').getByRole('button').first().click();
} else {
test.skip();
}
});
});