import { test, expect } from '@playwright/test' let uid = Date.now() function nextId() { return `pw_${++uid}` } function formInputs(page: import('@playwright/test').Page) { const dialog = page.locator('.t-dialog:visible') return { id: dialog.locator('input[placeholder="例如: openai"]'), name: dialog.locator('input[placeholder="例如: OpenAI"]'), apiKey: dialog.locator('input[type="password"]'), baseUrl: dialog.locator('input[placeholder="例如: https://api.openai.com/v1"]'), saveBtn: dialog.locator('.t-dialog__footer').getByRole('button', { name: '保存' }), cancelBtn: dialog.locator('.t-dialog__footer').getByRole('button', { name: '取消' }), } } test.describe('供应商管理', () => { test.beforeEach(async ({ page }) => { await page.goto('/providers') await expect(page.getByRole('heading', { name: '供应商管理' })).toBeVisible() }) test('应能创建供应商并验证出现在表格中', async ({ page }) => { const testId = nextId() await page.getByRole('button', { name: '添加供应商' }).click() await expect(page.locator('.t-dialog:visible')).toBeVisible() const inputs = formInputs(page) await inputs.id.fill(testId) await inputs.name.fill('Test Provider') await inputs.apiKey.fill('sk_test_key_12345') await inputs.baseUrl.fill('https://api.openai.com/v1') await inputs.saveBtn.click() await expect(page.locator('.t-dialog:visible')).not.toBeVisible({ timeout: 5000 }) await expect(page.locator('.t-table__body td').getByText(testId)).toBeVisible() await expect(page.locator('.t-table__body td').getByText('Test Provider')).toBeVisible() }) test('应能编辑供应商并验证更新生效', async ({ page }) => { const testId = nextId() await page.getByRole('button', { name: '添加供应商' }).click() await expect(page.locator('.t-dialog:visible')).toBeVisible() const inputs = formInputs(page) await inputs.id.fill(testId) await inputs.name.fill('Before Edit') await inputs.apiKey.fill('sk_key') await inputs.baseUrl.fill('https://api.example.com/v1') await inputs.saveBtn.click() await expect(page.locator('.t-dialog:visible')).not.toBeVisible({ timeout: 5000 }) await page.locator('.t-table__body button:has-text("编辑")').first().click() await expect(page.locator('.t-dialog:visible')).toBeVisible() const editInputs = formInputs(page) await editInputs.name.clear() await editInputs.name.fill('After Edit') await editInputs.saveBtn.click() await expect(page.locator('.t-dialog:visible')).not.toBeVisible({ timeout: 5000 }) await expect(page.locator('.t-table__body td').getByText('After Edit')).toBeVisible() }) test('应能删除供应商并验证消失', async ({ page }) => { const testId = nextId() await page.getByRole('button', { name: '添加供应商' }).click() await expect(page.locator('.t-dialog:visible')).toBeVisible() const inputs = formInputs(page) await inputs.id.fill(testId) await inputs.name.fill('To Delete') await inputs.apiKey.fill('sk_key') await inputs.baseUrl.fill('https://api.example.com/v1') await inputs.saveBtn.click() await expect(page.locator('.t-dialog:visible')).not.toBeVisible({ timeout: 5000 }) await page.locator('.t-table__body button:has-text("删除")').first().click() await expect(page.getByText('确定要删除这个供应商吗?')).toBeVisible() await page.locator('.t-popconfirm').getByRole('button', { name: '确定' }).click() await expect(page.getByText('确定要删除这个供应商吗?')).not.toBeVisible({ timeout: 3000 }) await expect(page.locator('.t-table__body td').getByText(testId)).not.toBeVisible({ timeout: 5000 }) }) test('应正确脱敏显示 API Key', async ({ page }) => { const testId = nextId() await page.getByRole('button', { name: '添加供应商' }).click() await expect(page.locator('.t-dialog:visible')).toBeVisible() const inputs = formInputs(page) await inputs.id.fill(testId) await inputs.name.fill('Mask Test') await inputs.apiKey.fill('sk_abcdefghijklmnopqrstuvwxyz') await inputs.baseUrl.fill('https://api.example.com/v1') await inputs.saveBtn.click() await expect(page.locator('.t-dialog:visible')).not.toBeVisible({ timeout: 5000 }) await expect(page.locator('.t-table__body')).toContainText('***stuv') }) })