yeg
2026-09-09 b226aa0db7fbecb8fff92476537adc0ca3e16a4f
tests/test-console-data-import.test.mjs
@@ -3,6 +3,37 @@
import XLSX from 'xlsx'
import { parseConsoleImport, consoleImportColumns } from '../src/utils/consoleDataImport.ts'
import * as importUtils from '../src/utils/consoleDataImport.ts'
import { formatTestDuration, parseTestDuration } from '../src/utils/testDataDuration.ts'
test('时长保留毫秒、累计小时和空值,非法时长不变成有效值', () => {
  assert.equal(formatTestDuration(90062.125), '25:01:02.125')
  assert.equal(parseTestDuration('25:01:02.125'), 90062.125)
  assert.equal(formatTestDuration(0), '0:00:00.000')
  assert.equal(formatTestDuration(null), '-')
  assert.equal(parseTestDuration('-'), null)
  for (const value of ['-1', '0:60:00.000', '2023-05-08 12:00:00', 'abc']) assert.ok(Number.isNaN(parseTestDuration(value)))
})
test('工步单页模板借同电池 record 时间,系统编号不充当来源编号', () => {
  const workbook = importUtils.createConsoleImportWorkbook('STEP')
  assert.deepEqual(workbook.SheetNames, ['工步', 'record'])
  assert.deepEqual(XLSX.utils.sheet_to_json(workbook.Sheets['工步'], { header: 1 })[0], [
    '记录编号', '电池', '循环序号', '工步序号', '工步名称', '工步时间(h:min:s.ms)', '容量(mAh)', '能量(mWh)',
    '起始电压(V)', '终止电压(V)', '充电中值电压(V)', '放电中值电压(V)',
  ])
  XLSX.utils.sheet_add_aoa(workbook.Sheets['工步'], [['step:999', 'BAT-1', 1, 1, '恒流放电', '1:02:32.125']], { origin: 'A2' })
  const records = [{ batteryNo: 'BAT-1', recordedAt: '2023-05-08 11:42:11' }, { batteryNo: 'BAT-2', recordedAt: '2023-05-08 12:42:11' }]
  XLSX.utils.sheet_add_aoa(workbook.Sheets.record, records.map(row => Object.keys(consoleImportColumns.REALTIME).map(key => ({ ...row, cycleNo: 1, stepNo: 1 })[key] ?? '')), { origin: 'A2' })
  const imported = parseConsoleImport(workbook, 'STEP', ['BAT-1', 'BAT-2'])
  assert.equal(imported.length, 1)
  assert.deepEqual(imported[0].errors, [])
  assert.equal(imported[0].data.recordNo, 'step:1:1')
  assert.equal(imported[0].data.recordedAt, 1683517331000)
  assert.equal(imported[0].data.stepDuration, 3752.125)
  workbook.Sheets.record.A2 = { t: 's', v: '' }
  workbook.Sheets.record.B2 = { t: 's', v: 'BAT-2' }
  assert.match(parseConsoleImport(workbook, 'STEP', ['BAT-1', 'BAT-2'])[0].errors.join(), /绝对.*无效/)
})
test('一键模板包含三个标准 Sheet,并逐 Sheet 预览与报告缺失表', () => {
  const workbook = importUtils.createConsoleImportWorkbook()
@@ -41,6 +72,8 @@
  assert.equal(rows[0].data.cycleNo, 1)
  assert.equal(rows[0].data.stepNo, 1)
  assert.equal(rows[0].data.recordedAt, 1683517331000)
  assert.equal(rows[0].data.relativeTimeSeconds, 0)
  assert.equal(rows[1].data.relativeTimeSeconds, 3752)
  assert.equal(rows[0].data.deviceTimeRaw, '2023-05-08 11:42:11')
  assert.equal(rows[0].data.current, -8.1651)
  assert.equal(rows[1].data.capacity, 8.5122)
@@ -48,6 +81,15 @@
  for (const field of ['temperature', 'positivePotential', 'negativePotential']) {
    assert.equal(rows[0].data[field], null)
  }
})
test('汇总时间匹配组中存在非法绝对时间时拒绝,不选择更早有效行代替', () => {
  const workbook = partyWorkbook()
  XLSX.utils.book_append_sheet(workbook, XLSX.utils.aoa_to_sheet([
    Object.values(consoleImportColumns.CYCLE), ['', 'BAT-1', 1, 0, 0, 0, 0, 0],
  ]), '循环')
  workbook.Sheets.record.J3 = { t: 's', v: '错误时间' }
  assert.match(parseConsoleImport(workbook, 'CYCLE', ['BAT-1'])[0].errors.join(), /绝对.*无效/)
})
test('采集器三项测量只读取 Excel 已有值,缺列或空格不生成数值', () => {
@@ -82,7 +124,7 @@
})
test('多电池文件要求明确归属,保留空白行后的实际错误位置', () => {
  assert.match(parseConsoleImport(partyWorkbook(), 'REALTIME', ['BAT-1', 'BAT-2'])[0].errors.join(), /电池号.*不能为空/)
  assert.match(parseConsoleImport(partyWorkbook(), 'REALTIME', ['BAT-1', 'BAT-2'])[0].errors.join(), /电池.*不能为空/)
  assert.equal(parseConsoleImport(partyWorkbook(), 'REALTIME', ['BAT-1', 'BAT-2'], 'BAT-2')[0].data.batteryNo, 'BAT-2')
  const workbook = partyWorkbook()
  XLSX.utils.sheet_add_aoa(workbook.Sheets.record, [[1, 1, '恒流放电', 19, '0:01:00.000', '不是数值', 0, 0, 0, '2023-05-08 11:44:11']], { origin: 'A20' })