yeg
2026-09-09 bbe4715e003e991d058dcfe757849cfbdc798900
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import assert from 'node:assert/strict'
import { readFile } from 'node:fs/promises'
import { chromium, expect } from '@playwright/test'
 
// #19 的只读修订摘要回放;页面加载真实构建产物,API 使用替身,不启动服务或写数据库。
const capturedChanges = [
  { identity: 'realtime:53519', before: { energy: 16.3385, current: -8.1659, voltage: 0.8999, capacity: 13.6507, temperature: 25.5, negativePotential: -0.105, positivePotential: 1.505 }, after: { temperature: '25.5001' } },
  { identity: 'realtime:53518', before: { energy: 16.3034, current: -8.1674, voltage: 0.9095, capacity: 13.6119, temperature: 25.4, negativePotential: -0.104, positivePotential: 1.504 }, after: { negativePotential: '-0.1041' } },
]
const origin = 'http://revision-detail.test'
const browser = await chromium.launch({ channel: 'chrome', headless: true })
try {
  const page = await browser.newPage({ viewport: { width: 1440, height: 1000 } })
  const errors = []
  page.on('pageerror', error => errors.push(error.message))
  await page.addInitScript(() => localStorage.setItem('battery_detection_auth_token', 'browser-test'))
  let operationType = 'EDIT'
  let changes = process.env.MINIMAL_REPRO ? [{ identity: 'realtime:53519', before: { temperature: 25.5 }, after: { temperature: '25.5001' } }] : capturedChanges
  await page.route(`${origin}/**`, async route => {
    const path = new URL(route.request().url()).pathname
    if (path.startsWith('/assets/')) return route.fulfill({ body: await readFile(`dist${path}`), contentType: path.endsWith('.css') ? 'text/css' : 'text/javascript' })
    if (path.endsWith('/system/data-revision/19')) return route.fulfill({ json: { code: 200, data: {
      actionId: 19, testId: 4, testName: '修订回放测试', dataType: 'REALTIME', operationType,
      affectedRecordCount: changes.length,
      identitySummary: operationType === 'EDIT' ? JSON.stringify(changes.map(row => row.identity)) : null,
      changesSummary: operationType === 'EDIT' ? JSON.stringify(changes) : null,
      scopeSummary: '修改测量值', reason: '核对修订显示', operatorName: '测试操作员', createdAtUtc: 1788924699166,
    } } })
    if (path.endsWith('/getInfo')) return route.fulfill({ json: { code: 200, user: { userName: 'test' }, roles: ['admin'] } })
    if (path.includes('/system/')) return route.fulfill({ json: { code: 200, data: [], rows: [] } })
    return route.fulfill({ body: await readFile('dist/index.html'), contentType: 'text/html' })
  })
  await page.goto(`${origin}/data-revision/19`)
  await expect(page.locator('.identity-list')).toContainText('realtime:53519')
  await expect(page.locator('.change-list')).toContainText('温度(℃)')
  await expect(page.locator('.change-list')).toContainText('25.5000')
  await expect(page.locator('.change-list')).toContainText('25.5001')
  if (!process.env.MINIMAL_REPRO) {
    await expect(page.locator('.change-list')).toContainText('负电位(V)')
    await expect(page.locator('.change-list')).toContainText('-0.1040')
    await expect(page.locator('.change-list')).toContainText('-0.1041')
    await expect(page.locator('.change-list dt')).toHaveCount(2)
    await expect(page.locator('.change-list')).not.toContainText('本次导入')
    changes = [{ identity: 'realtime:1', before: { positivePotential: null, current: -8.1651, capacity: 0, temperature: 25 }, after: { positivePotential: '0', current: '-8', capacity: null, temperature: 25 } }]
    await page.reload()
    await expect(page.locator('.change-list')).toContainText('正电位(V)')
    await expect(page.locator('.change-list')).toContainText('-8165.1000')
    await expect(page.locator('.change-list')).toContainText('-8000.0000')
    await expect(page.locator('.change-list')).toContainText('0.0000')
    await expect(page.locator('.change-list dt')).toHaveCount(3)
    await page.setViewportSize({ width: 390, height: 844 })
    await expect(page.locator('.app-main')).toHaveCSS('margin-left', '0px')
    await expect.poll(() => page.evaluate(() => document.documentElement.scrollWidth > innerWidth)).toBe(false)
    for (const operation of ['IMPORT', 'DELETE']) {
      operationType = operation
      changes = Array.from({ length: 8000 }, (_, index) => ({ identity: `realtime:${index}`, voltage: 1.5 }))
      await page.reload()
      await expect(page.locator('.operation-tag')).toHaveText(operation === 'IMPORT' ? '导入' : '删除')
      await expect(page.getByText('字段变化摘要', { exact: true })).toHaveCount(0)
      await expect(page.getByText('记录编号', { exact: true })).toHaveCount(0)
      await expect(page.locator('.identity-list')).toHaveCount(0)
      await expect(page.locator('.change-list')).toHaveCount(0)
      await expect(page.locator('.summary-section')).toContainText('8000 条')
    }
  }
  assert.deepEqual(errors, [])
  console.log('通过:编辑字段前后值、毫单位、零与空值正确;导入和删除不展示字段变化。')
} finally { await browser.close() }