| New file |
| | |
| | | import { expect, test, type Page } from '@playwright/test' |
| | | import { Ticket04Stack } from './support/ticket04-stack' |
| | | |
| | | const stack = new Ticket04Stack() |
| | | test.use({ actionTimeout: 20_000 }) |
| | | test.beforeAll(async () => { |
| | | await stack.start() |
| | | stack.executeIsolatedSql(` |
| | | INSERT INTO t_battery_group(group_id,group_name,model) VALUES(9201,'详情验收组','验收型号'); |
| | | INSERT INTO t_battery_group_field(field_id,field_name,field_type) VALUES(9201,'额定容量','text'),(9202,'电流','text'); |
| | | INSERT INTO t_test_type(test_type_id,test_type_name) VALUES(9201,'详情验收'); |
| | | INSERT INTO t_test(test_id,test_name,creator_id,principal_id,test_type_id,test_purpose,test_status,reception_status) |
| | | VALUES(9201,'详情测试甲',1,1,9201,'隔离验收','COMPLETED','ENDED'),(9202,'详情测试乙',1,1,9201,'隔离验收','COMPLETED','ENDED'),(9203,'无详情测试',1,1,9201,'隔离验收','COMPLETED','ENDED'); |
| | | INSERT INTO t_test_battery(test_battery_id,test_id,group_id,battery_no,collector_id) |
| | | VALUES(9201,9201,9201,'BAT-A',9201),(9202,9201,9201,'BAT-B',9202),(9203,9202,9201,'BAT-A',9203),(9204,9202,9201,'BAT-B',9204); |
| | | `) |
| | | }) |
| | | test.afterAll(async () => stack.stop()) |
| | | |
| | | async function login(page: Page) { |
| | | await page.goto('/login') |
| | | await page.locator('input[autocomplete="username"]').fill('admin') |
| | | await page.locator('input[autocomplete="current-password"]').fill('admin123') |
| | | await page.getByRole('button', { name: '登录', exact: true }).click() |
| | | await expect(page).toHaveURL(/\/dashboard$/) |
| | | } |
| | | |
| | | async function api(page: Page, id: number, data?: unknown) { |
| | | const token = await page.evaluate(() => localStorage.getItem('battery_detection_auth_token')) |
| | | const response = await page.request.fetch(`${stack.backendUrl}/system/test/${id}${data ? '/console-detail' : ''}`, { |
| | | method: data ? 'PUT' : 'GET', data, headers: { Authorization: `Bearer ${token}` }, |
| | | }) |
| | | const body = await response.json() |
| | | expect(body.code, body.msg).toBe(200) |
| | | return body.data |
| | | } |
| | | |
| | | const initial = { |
| | | experimentName: '原实验', batteryFields: ['额定容量', '电流'], specialFields: ['人工说明'], |
| | | fieldValues: { 额定容量: { 'BAT-A': '甲容量', 'BAT-B': '' }, 电流: { 'BAT-A': '甲电流', 'BAT-B': '乙电流' }, 人工说明: { 'BAT-A': '甲说明', 'BAT-B': '乙说明' } }, |
| | | } |
| | | const row = (page: Page, field: string) => page.locator('.field-table tbody tr').filter({ has: page.locator('td').filter({ hasText: new RegExp(`^${field}$`) }) }) |
| | | async function save(page: Page) { |
| | | const response = page.waitForResponse(r => r.url().endsWith('/console-detail') && r.request().method() === 'PUT') |
| | | await page.getByRole('button', { name: '保存详情', exact: true }).click() |
| | | return (await response).json() |
| | | } |
| | | |
| | | test('保存后页签返回、刷新及正式重读保持逐电池详情', async ({ page }) => { |
| | | await login(page) |
| | | await api(page, 9201, initial) |
| | | await page.goto('/test-list/9201/console?tab=step-chart') |
| | | await expect(page.locator('.detail-meta input')).toHaveValue('原实验') |
| | | await page.locator('.detail-meta input').fill('新实验甲') |
| | | await row(page, '人工说明').locator('input').nth(0).fill('新甲说明') |
| | | expect((await save(page)).code).toBe(200) |
| | | const saved = (await api(page, 9201)).consoleDetail |
| | | expect(saved.experimentName).toBe('新实验甲') |
| | | expect(saved.fieldValues['额定容量']['BAT-B']).toBe('') |
| | | expect(saved.fieldValues['人工说明']).toEqual({ 'BAT-A': '新甲说明', 'BAT-B': '乙说明' }) |
| | | await page.getByRole('button', { name: '实时监控', exact: true }).click() |
| | | await page.getByRole('button', { name: '工步图表', exact: true }).click() |
| | | await expect(page.locator('.detail-meta input')).toHaveValue('新实验甲') |
| | | await expect(row(page, '人工说明').locator('input').nth(0)).toHaveValue('新甲说明') |
| | | await page.reload() |
| | | await expect(page.locator('.detail-meta input')).toHaveValue('新实验甲') |
| | | await expect(row(page, '额定容量').locator('input').nth(1)).toHaveValue('') |
| | | }) |
| | | |
| | | test('取消模板字段再次保存只提交当前字段且保留其他电池值', async ({ page }) => { |
| | | await login(page) |
| | | await api(page, 9202, { ...initial, experimentName: '实验乙' }) |
| | | await page.goto('/test-list/9202/console?tab=step-chart') |
| | | await expect(page.locator('.detail-meta input')).toHaveValue('实验乙') |
| | | await page.getByRole('button', { name: '电池组字段模板', exact: true }).click() |
| | | await page.getByRole('dialog').getByText('电流', { exact: true }).click() |
| | | await page.getByRole('dialog').getByRole('button', { name: '应用模板', exact: true }).click() |
| | | expect((await save(page)).code).toBe(200) |
| | | const saved = (await api(page, 9202)).consoleDetail |
| | | expect(saved.batteryFields).toEqual(['额定容量']) |
| | | expect(saved.fieldValues).toEqual({ 额定容量: initial.fieldValues['额定容量'], 人工说明: initial.fieldValues['人工说明'] }) |
| | | await page.reload() |
| | | await expect(page.locator('.detail-meta input')).toHaveValue('实验乙') |
| | | await expect(row(page, '人工说明').locator('input').nth(1)).toHaveValue('乙说明') |
| | | await page.setViewportSize({ width: 1440, height: 1000 }) |
| | | await page.screenshot({ path: 'tests/e2e/.artifacts/console-detail-desktop.png', fullPage: true, animations: 'disabled' }) |
| | | await page.setViewportSize({ width: 390, height: 844 }) |
| | | await expect(page.getByRole('button', { name: '保存详情', exact: true })).toBeVisible() |
| | | await page.screenshot({ path: 'tests/e2e/.artifacts/console-detail-narrow.png', fullPage: true, animations: 'disabled' }) |
| | | }) |
| | | |
| | | test('无详情、读取失败与保存失败分别反馈且失败保留填写', async ({ page }) => { |
| | | await login(page) |
| | | expect((await api(page, 9203)).consoleDetail).toBeNull() |
| | | await page.goto('/test-list/9203/console?tab=step-chart') |
| | | await expect(page.getByText('暂无已保存的测试详情', { exact: true })).toBeVisible() |
| | | await page.route('**/dev-api/system/test/9203', route => route.fulfill({ json: { code: 500, msg: '详情读取失败验收' } })) |
| | | await page.reload() |
| | | await expect(page.getByText('详情读取失败验收', { exact: true }).first()).toBeVisible() |
| | | await expect(page.getByRole('button', { name: '保存详情', exact: true })).toHaveCount(0) |
| | | await page.unroute('**/dev-api/system/test/9203') |
| | | await api(page, 9202, initial) |
| | | await page.goto('/test-list/9202/console?tab=step-chart') |
| | | await expect(page.locator('.detail-meta input')).toHaveValue('原实验') |
| | | await page.locator('.detail-meta input').fill('失败时保留实验') |
| | | await row(page, '人工说明').locator('input').nth(1).fill('失败时保留乙说明') |
| | | await page.route('**/dev-api/system/test/9202/console-detail', route => route.fulfill({ json: { code: 500, msg: '详情保存失败验收' } }), { times: 1 }) |
| | | expect((await save(page)).code).toBe(500) |
| | | await expect(page.getByText('详情保存失败验收', { exact: true })).toBeVisible() |
| | | await expect(page.getByText('测试详情已保存', { exact: true })).toHaveCount(0) |
| | | await expect(page.locator('.detail-meta input')).toHaveValue('失败时保留实验') |
| | | await expect(row(page, '人工说明').locator('input').nth(1)).toHaveValue('失败时保留乙说明') |
| | | expect((await api(page, 9202)).consoleDetail).toEqual(initial) |
| | | }) |