- 重构 AppLayout 为可折叠侧边栏导航布局 - 实现统计仪表盘:统计摘要卡片 + 请求趋势图表 - Provider 页面使用 Card 包裹优化视觉层次 - 主题切换按钮移至侧边栏底部,支持折叠态 - Header 适配暗色主题,添加分隔线优化视觉过渡 - 添加全局样式重置(SCSS) - 完善组件测试和 E2E 测试覆盖 - 同步 OpenSpec 规范到主 specs
137 lines
5.2 KiB
TypeScript
137 lines
5.2 KiB
TypeScript
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.locator('.ant-layout-sider').getByText('用量统计').click();
|
||
await expect(page.getByRole('heading', { name: '用量统计' })).toBeVisible();
|
||
|
||
await page.locator('.ant-layout-sider').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();
|
||
}
|
||
});
|
||
});
|