You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
haoliang-net/frontend/e2e/admin-ui.spec.ts

248 lines
10 KiB
TypeScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* CNC管理后台 - Playwright浏览器UI测试
*
* 测试范围:设备管理、员工管理、采集地址三个模块的批量删除和启用/停用功能
* 使用Mock模式/mock前缀路由不依赖后端API
*
* 测试在真实浏览器中执行,验证:
* - 页面加载和表格数据渲染
* - 勾选行后批量操作按钮的显示
* - 批量删除操作(勾选→点击→确认弹窗→验证行数减少)
* - 批量停用操作(勾选已启用行→确认→验证状态变为停用)
* - 批量启用操作(勾选已停用行→确认→验证状态变为启用)
* - 单个删除操作(点击行内删除→确认→验证行数减少)
*/
import { test, expect, type Page } from '@playwright/test'
// 模拟登录TokenMock模式下路由守卫只检查token存在性
const MOCK_TOKEN = 'mock-test-token'
// 全局beforeEach在每个测试前预设token到localStorage避免路由守卫拦截
test.beforeEach(async ({ page }) => {
await page.addInitScript((token) => {
localStorage.setItem('token', token)
}, MOCK_TOKEN)
})
// 辅助函数重置指定模块的mock数据
async function resetMockData(page: Page, endpoint: string) {
await page.evaluate(async (url) => {
await fetch(url, { method: 'POST' })
}, endpoint)
}
// 辅助函数:导航到页面并等待表格渲染完成
async function gotoPage(page: Page, path: string) {
await page.goto(path, { waitUntil: 'networkidle' })
await page.waitForSelector('.el-table', { timeout: 15000 })
}
// 辅助函数勾选表格中指定行的checkbox
async function selectRowsByIndex(page: Page, indices: number[]) {
const checkboxes = page.locator('.el-table__body .el-checkbox')
for (const idx of indices) {
await checkboxes.nth(idx).waitFor({ state: 'visible' })
await checkboxes.nth(idx).click()
}
}
// 辅助函数处理Element Plus的ElMessageBox确认弹窗
async function confirmDialog(page: Page) {
const dialog = page.locator('.el-message-box')
await dialog.waitFor({ state: 'visible', timeout: 5000 })
await dialog.locator('.el-button--primary').click()
await dialog.waitFor({ state: 'hidden', timeout: 5000 })
}
// 辅助函数等待ElMessage消息提示并验证文本
async function expectMessage(page: Page, expectedText: string) {
const msg = page.locator('.el-message')
await msg.waitFor({ state: 'visible', timeout: 10000 })
await expect(msg).toContainText(expectedText)
}
// ============================================================
// 套件1设备管理机床页面测试
// ============================================================
test.describe('设备管理页面', () => {
test.beforeEach(async ({ page }) => {
await gotoPage(page, '/mock/machine')
await resetMockData(page, '/mock-api/test/reset-machines')
await page.reload({ waitUntil: 'networkidle' })
await page.waitForSelector('.el-table', { timeout: 15000 })
})
test('页面加载 - 表格显示5台机床', async ({ page }) => {
const rows = page.locator('.el-table__body-wrapper .el-table__row')
await expect(rows).toHaveCount(5)
const checkboxes = page.locator('.el-table__body .el-checkbox')
await expect(checkboxes).toHaveCount(5)
})
test('勾选行后 - 批量操作按钮显示', async ({ page }) => {
await expect(page.locator('button:has-text("批量删除")')).not.toBeVisible()
await selectRowsByIndex(page, [0])
await expect(page.locator('button:has-text("批量停用")')).toBeVisible()
await expect(page.locator('button:has-text("批量启用")')).toBeVisible()
await expect(page.locator('button:has-text("批量删除")')).toBeVisible()
await expect(page.locator('button:has-text("批量删除(1)")')).toBeVisible()
})
test('批量删除 - 勾选2行后删除表格行数减少', async ({ page }) => {
const rows = page.locator('.el-table__body-wrapper .el-table__row')
await expect(rows).toHaveCount(5)
await selectRowsByIndex(page, [0, 1])
await page.locator('button:has-text("批量删除")').click()
await confirmDialog(page)
await expectMessage(page, '批量删除成功')
await page.waitForTimeout(1000)
await expect(rows).toHaveCount(3)
})
test('批量停用 - 勾选已启用行后停用,状态标签变更', async ({ page }) => {
await selectRowsByIndex(page, [0])
await page.locator('button:has-text("批量停用")').click()
await confirmDialog(page)
await expectMessage(page, '操作成功')
await page.waitForTimeout(1000)
const statusTag = page.locator('.el-table__body-wrapper .el-table__row').first().locator('.el-tag:has-text("停用")')
await expect(statusTag).toBeVisible()
})
test('批量启用 - 勾选已停用行后启用,状态标签变更', async ({ page }) => {
// 第4行东-2.5isEnabled=0
await selectRowsByIndex(page, [3])
await page.locator('button:has-text("批量启用")').click()
await confirmDialog(page)
await expectMessage(page, '操作成功')
await page.waitForTimeout(1000)
const statusTag = page.locator('.el-table__body-wrapper .el-table__row').nth(3).locator('.el-tag:has-text("启用")')
await expect(statusTag).toBeVisible()
})
test('单个删除 - 点击行内删除按钮,确认后行消失', async ({ page }) => {
const rows = page.locator('.el-table__body-wrapper .el-table__row')
await expect(rows).toHaveCount(5)
await rows.first().locator('button:has-text("删除")').click()
await confirmDialog(page)
await expectMessage(page, '已删除')
await page.waitForTimeout(1000)
await expect(rows).toHaveCount(4)
})
})
// ============================================================
// 套件2员工管理页面测试
// ============================================================
test.describe('员工管理页面', () => {
test.beforeEach(async ({ page }) => {
await gotoPage(page, '/mock/worker')
await resetMockData(page, '/mock-api/test/reset-workers')
await page.reload({ waitUntil: 'networkidle' })
await page.waitForSelector('.el-table', { timeout: 15000 })
})
test('页面加载 - 表格显示3名员工', async ({ page }) => {
const rows = page.locator('.el-table__body-wrapper .el-table__row')
await expect(rows).toHaveCount(3)
})
test('勾选行后 - 批量操作按钮显示', async ({ page }) => {
await expect(page.locator('button:has-text("批量删除")')).not.toBeVisible()
await selectRowsByIndex(page, [0])
await expect(page.locator('button:has-text("批量启用")')).toBeVisible()
await expect(page.locator('button:has-text("批量停用")')).toBeVisible()
await expect(page.locator('button:has-text("批量删除")')).toBeVisible()
})
test('批量删除 - 勾选1行后删除表格行数减少', async ({ page }) => {
const rows = page.locator('.el-table__body-wrapper .el-table__row')
await expect(rows).toHaveCount(3)
await selectRowsByIndex(page, [2])
await page.locator('button:has-text("批量删除")').click()
await confirmDialog(page)
await expectMessage(page, '批量删除成功')
await page.waitForTimeout(1000)
await expect(rows).toHaveCount(2)
})
test('批量停用 - 勾选已启用员工后停用', async ({ page }) => {
await selectRowsByIndex(page, [0])
await page.locator('button:has-text("批量停用")').click()
await confirmDialog(page)
await expectMessage(page, '操作成功')
await page.waitForTimeout(1000)
const statusTag = page.locator('.el-table__body-wrapper .el-table__row').first().locator('.el-tag:has-text("停用")')
await expect(statusTag).toBeVisible()
})
test('批量启用 - 勾选已停用员工后启用', async ({ page }) => {
await selectRowsByIndex(page, [2])
await page.locator('button:has-text("批量启用")').click()
await confirmDialog(page)
await expectMessage(page, '操作成功')
await page.waitForTimeout(1000)
const statusTag = page.locator('.el-table__body-wrapper .el-table__row').nth(2).locator('.el-tag:has-text("启用")')
await expect(statusTag).toBeVisible()
})
})
// ============================================================
// 套件3采集地址页面测试
// ============================================================
test.describe('采集地址页面', () => {
test.beforeEach(async ({ page }) => {
await gotoPage(page, '/mock/collect-address')
await resetMockData(page, '/mock-api/test/reset-addresses')
await page.reload({ waitUntil: 'networkidle' })
await page.waitForSelector('.el-table', { timeout: 15000 })
})
test('页面加载 - 表格显示3条采集地址', async ({ page }) => {
const rows = page.locator('.el-table__body-wrapper .el-table__row')
await expect(rows).toHaveCount(3)
})
test('勾选行后 - 批量操作按钮显示', async ({ page }) => {
await expect(page.locator('button:has-text("批量删除")')).not.toBeVisible()
await selectRowsByIndex(page, [0])
await expect(page.locator('button:has-text("批量启用")')).toBeVisible()
await expect(page.locator('button:has-text("批量停用")')).toBeVisible()
await expect(page.locator('button:has-text("批量删除")')).toBeVisible()
})
test('批量删除 - 勾选1行后删除表格行数减少', async ({ page }) => {
const rows = page.locator('.el-table__body-wrapper .el-table__row')
await expect(rows).toHaveCount(3)
await selectRowsByIndex(page, [2])
await page.locator('button:has-text("批量删除")').click()
await confirmDialog(page)
await expectMessage(page, '批量删除成功')
await page.waitForTimeout(1000)
await expect(rows).toHaveCount(2)
})
test('批量停用 - 勾选已启用地址后停用', async ({ page }) => {
await selectRowsByIndex(page, [0])
await page.locator('button:has-text("批量停用")').click()
await confirmDialog(page)
await expectMessage(page, '操作成功')
await page.waitForTimeout(1000)
const statusTag = page.locator('.el-table__body-wrapper .el-table__row').first().locator('.el-tag:has-text("停用")')
await expect(statusTag).toBeVisible()
})
test('批量启用 - 勾选已停用地址后启用', async ({ page }) => {
await selectRowsByIndex(page, [2])
await page.locator('button:has-text("批量启用")').click()
await confirmDialog(page)
await expectMessage(page, '操作成功')
await page.waitForTimeout(1000)
const statusTag = page.locator('.el-table__body-wrapper .el-table__row').nth(2).locator('.el-tag:has-text("启用")')
await expect(statusTag).toBeVisible()
})
})