import { test, expect, type Page } from '@playwright/test' // 测试账号配置 const TEST_USERNAME = process.env.TEST_USERNAME || 'admin' const TEST_PASSWORD = process.env.TEST_PASSWORD || '123456' // 生成唯一的测试机器ID const generateMachineId = () => `TEST_${Date.now()}` // data-id 选择器辅助函数 const byDataId = (id: string) => `[data-id="${id}"]` test.describe('机器管理 CRUD 测试', () => { // 登录辅助函数 async function login(page: Page) { await page.goto('/login') await page.evaluate(() => { localStorage.clear() document.cookie.split(';').forEach((c) => { document.cookie = c.replace(/^ +/, '').replace(/=.*/, `=;expires=${new Date().toUTCString()};path=/`) }) }) await page.reload() await page.getByPlaceholder('用户名').fill(TEST_USERNAME) await page.getByPlaceholder('密码').fill(TEST_PASSWORD) await page.getByRole('button', { name: '登录' }).click() await expect(page).not.toHaveURL(/\/login/, { timeout: 15000 }) } test('机器管理页面正确显示', async ({ page }) => { await login(page) await page.goto('/machine') // 验证页面元素 await expect(page.locator(byDataId('btn-add-machine'))).toBeVisible() await expect(page.locator(byDataId('btn-search'))).toBeVisible() await expect(page.locator(byDataId('btn-reset'))).toBeVisible() await expect(page.locator(byDataId('machine-table'))).toBeVisible() // 验证表头 - 使用 thead 来区分表单标签和表头 await expect(page.locator('thead').getByText('机器ID')).toBeVisible() await expect(page.locator('thead').getByText('名称')).toBeVisible() await expect(page.locator('thead').getByText('位置')).toBeVisible() }) test('查询和重置功能', async ({ page }) => { await login(page) await page.goto('/machine') // 等待表格加载 await expect(page.locator(byDataId('machine-table'))).toBeVisible() // 点击查询按钮 await page.locator(byDataId('btn-search')).click() await page.waitForTimeout(500) // 表格应该仍然可见 await expect(page.locator(byDataId('machine-table'))).toBeVisible() // 点击重置按钮 await page.locator(byDataId('btn-reset')).click() await page.waitForTimeout(500) // 表格应该仍然可见 await expect(page.locator(byDataId('machine-table'))).toBeVisible() }) test('新增机器完整流程', async ({ page }) => { await login(page) await page.goto('/machine') const machineId = generateMachineId() const machineName = `测试机器_${Date.now()}` // 点击新增按钮 await page.locator(byDataId('btn-add-machine')).click() // 验证弹窗打开 const dialog = page.locator(byDataId('dialog-machine')) await expect(dialog).toBeVisible() await expect(page.locator('.el-dialog__title')).toContainText('新增机器') // 填写表单 - 使用 dialog 作为容器来定位输入框 await dialog.locator(byDataId('input-machine-id')).fill(machineId) await dialog.locator(byDataId('input-name')).fill(machineName) await dialog.locator(byDataId('input-location')).fill('测试位置') await dialog.locator(byDataId('input-description')).fill('E2E测试创建的机器') // 等待提交按钮可用后点击 const submitBtn = page.locator(byDataId('btn-submit')) await expect(submitBtn).toBeEnabled() await submitBtn.click() // 等待成功消息或弹窗关闭(API成功或失败都会关闭弹窗) const successPromise = page .locator('.el-message--success') .waitFor({ timeout: 10000 }) .catch(() => null) const dialogClosePromise = expect(dialog).not.toBeVisible({ timeout: 10000 }) await Promise.race([successPromise, dialogClosePromise]) // 如果弹窗关闭了,说明操作已完成 await expect(dialog).not.toBeVisible({ timeout: 5000 }) }) test('编辑机器功能', async ({ page }) => { await login(page) await page.goto('/machine') // 等待表格加载 await expect(page.locator(byDataId('machine-table'))).toBeVisible() await page.waitForTimeout(1000) // 点击第一行的名称链接 const firstNameLink = page.locator('[data-id^="link-edit-"]').first() // 等待数据加载,确保有可编辑的数据 await expect(firstNameLink).toBeVisible({ timeout: 10000 }) await firstNameLink.click() // 验证弹窗打开 const dialog = page.locator(byDataId('dialog-machine')) await expect(dialog).toBeVisible() await expect(page.locator('.el-dialog__title')).toContainText('编辑机器') // 修改名称 - 使用 data-id 定位输入框 const nameInput = dialog.locator(byDataId('input-name')) await nameInput.clear() await nameInput.fill(`编辑测试_${Date.now()}`) // 等待提交按钮可用后点击 const submitBtn = page.locator(byDataId('btn-submit')) await expect(submitBtn).toBeEnabled() await submitBtn.click() // 验证弹窗关闭 await expect(dialog).not.toBeVisible({ timeout: 15000 }) }) test('删除机器功能', async ({ page }) => { await login(page) await page.goto('/machine') // 等待表格加载 await expect(page.locator(byDataId('machine-table'))).toBeVisible() await page.waitForTimeout(1000) // 找到第一个删除按钮并点击 const deleteBtn = page.locator('[data-id^="btn-delete-"]').first() // 确保有数据可以删除 await expect(deleteBtn).toBeVisible({ timeout: 10000 }) await deleteBtn.click() // 确认删除对话框出现 await expect(page.locator('.el-message-box')).toBeVisible() await page.locator('.el-message-box').getByRole('button', { name: '确定' }).click() // 等待确认对话框关闭(删除操作已执行) await expect(page.locator('.el-message-box')).not.toBeVisible({ timeout: 10000 }) // 验证表格仍然可见(删除后页面正常) await expect(page.locator(byDataId('machine-table'))).toBeVisible() }) test('新增机器表单验证', async ({ page }) => { await login(page) await page.goto('/machine') // 点击新增按钮 await page.locator(byDataId('btn-add-machine')).click() await expect(page.locator(byDataId('dialog-machine'))).toBeVisible() // 直接点击确定,不填写任何内容 await page.locator(byDataId('btn-submit')).click() // 验证显示验证错误 - 使用 dialog 容器来定位错误消息 const dialog = page.locator(byDataId('dialog-machine')) await expect(dialog.getByText('请输入机器ID')).toBeVisible() await expect(dialog.getByText('请输入名称')).toBeVisible() }) test('取消新增机器', async ({ page }) => { await login(page) await page.goto('/machine') // 点击新增按钮 await page.locator(byDataId('btn-add-machine')).click() const dialog = page.locator(byDataId('dialog-machine')) await expect(dialog).toBeVisible() // 填写部分内容 await dialog.locator(byDataId('input-machine-id')).fill('TEST_CANCEL') // 点击取消 await page.locator(byDataId('btn-cancel')).click() // 验证弹窗关闭 await expect(dialog).not.toBeVisible() }) test('从侧边栏导航到机器管理', async ({ page }) => { await login(page) // 点击侧边栏机器管理菜单项 await page.getByText('机器管理').first().click() // 验证跳转到机器管理页面 await expect(page).toHaveURL(/\/machine/) await expect(page.locator(byDataId('btn-add-machine'))).toBeVisible() }) })