优化
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
import ElementPlus from 'element-plus'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { createPinia, setActivePinia } from 'pinia'
|
||||
import { DOMWrapper, enableAutoUnmount, flushPromises, mount, type VueWrapper } from '@vue/test-utils'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { useAccessPreviewStore } from '@/core/access/accessPreview'
|
||||
import { useAuthStore } from '@/core/auth/auth'
|
||||
import { ApiResponseError } from '@/shared/api/http'
|
||||
import AppDialog from '@/shared/components/AppDialog.vue'
|
||||
import {
|
||||
confirmWeightResult,
|
||||
correctWeightResult,
|
||||
@@ -92,11 +93,9 @@ function mountPanel(permissions = allWeightPermissions) {
|
||||
})
|
||||
}
|
||||
|
||||
async function openWeightDialog(wrapper: VueWrapper, reviewEvidence = true) {
|
||||
async function openWeightDialog(wrapper: VueWrapper) {
|
||||
await wrapper.get('button[aria-label="查看称重图片 1"]').trigger('click')
|
||||
await flushPromises()
|
||||
const evidence = document.body.querySelector<HTMLInputElement>('.ocr-review-check input[type="checkbox"]')
|
||||
if (reviewEvidence && evidence) await new DOMWrapper(evidence).setValue(true)
|
||||
}
|
||||
|
||||
function dialogWeightInput() {
|
||||
@@ -117,12 +116,6 @@ function dialogConfirmButton() {
|
||||
return new DOMWrapper(button)
|
||||
}
|
||||
|
||||
function dialogEvidenceCheckbox() {
|
||||
const input = document.body.querySelector<HTMLInputElement>('.ocr-review-check input[type="checkbox"]')
|
||||
if (!input) throw new Error('OCR evidence checkbox is missing')
|
||||
return new DOMWrapper(input)
|
||||
}
|
||||
|
||||
describe('WeightOcrPanel confirmation behavior', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
@@ -178,7 +171,9 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
expect(uploadWeightImage).toHaveBeenCalledWith('10001', '20001', file)
|
||||
expect(createWeightResult).toHaveBeenCalledWith('10001', '20001', expect.objectContaining({ palletId: '50001' }))
|
||||
expect(document.body.textContent).toContain('确认称重图片')
|
||||
expect(document.body.textContent).toContain('识别重量 12.500 KG')
|
||||
expect(document.body.textContent).toContain('当前托盘皮重')
|
||||
expect(document.body.textContent).toContain('OCR 识别毛重')
|
||||
expect(document.body.textContent).toContain('12.500 KG')
|
||||
expect(document.body.querySelector('input[aria-label="当前图片确认重量"]')).not.toBeNull()
|
||||
})
|
||||
|
||||
@@ -215,17 +210,21 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
expect(deleteWeightResult).toHaveBeenCalledWith('10001', '20001', '30001', 0)
|
||||
})
|
||||
|
||||
it('requires image review before confirming even a high-confidence OCR value', async () => {
|
||||
it('shows only the key weights and allows direct confirmation', async () => {
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
await openWeightDialog(wrapper, false)
|
||||
await openWeightDialog(wrapper)
|
||||
|
||||
expect(document.body.textContent).toContain('OCR 原文')
|
||||
expect(document.body.textContent).toContain('285.5')
|
||||
expect(document.body.textContent).toContain('98%')
|
||||
expect(document.body.textContent).toContain('OCR 可能误读数字或小数点')
|
||||
expect(dialogConfirmButton().attributes('disabled')).toBeDefined()
|
||||
await dialogEvidenceCheckbox().setValue(true)
|
||||
const dialogText = document.body.textContent || ''
|
||||
expect(dialogText).toContain('当前托盘皮重')
|
||||
expect(dialogText).toContain('12.000 KG')
|
||||
expect(dialogText).toContain('OCR 识别毛重')
|
||||
expect(dialogText).toContain('285.500 KG')
|
||||
expect(dialogText).toContain('确认含托盘毛重')
|
||||
for (const hiddenLabel of ['托盘编码', '托盘类型', '托盘容量', '识别状态', '置信度', '服务端毛重', '服务端净重', 'OCR 原文']) {
|
||||
expect(dialogText).not.toContain(hiddenLabel)
|
||||
}
|
||||
expect(dialogConfirmButton().attributes('disabled')).toBeUndefined()
|
||||
await dialogConfirmButton().trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
@@ -255,6 +254,18 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
expect(wrapper.text()).toContain('285.500 KG')
|
||||
})
|
||||
|
||||
it('closes the confirmation dialog immediately after a successful confirmation', async () => {
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
await openWeightDialog(wrapper)
|
||||
|
||||
expect(wrapper.getComponent(AppDialog).props('modelValue')).toBe(true)
|
||||
await dialogConfirmButton().trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(wrapper.getComponent(AppDialog).props('modelValue')).toBe(false)
|
||||
})
|
||||
|
||||
it('requires a pallet selection before opening the file picker', async () => {
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
@@ -292,22 +303,24 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
expect(getWeightPalletOptions).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('requires explicit image review before confirming a low-confidence OCR value', async () => {
|
||||
it('keeps a low-confidence OCR result focused on the editable weight', async () => {
|
||||
vi.mocked(getWeightWorkspace).mockResolvedValue({
|
||||
...workspace,
|
||||
weightResults: [{ ...pendingWeight, ocrRawText: '5360', ocrWeightValue: 5360, confidence: 0.51863 }],
|
||||
})
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
await openWeightDialog(wrapper, false)
|
||||
await openWeightDialog(wrapper)
|
||||
|
||||
expect(document.body.textContent).toContain('OCR 可能误读数字或小数点')
|
||||
expect(document.body.textContent).toContain('OCR 原文')
|
||||
expect(document.body.textContent).toContain('5360')
|
||||
expect(document.body.textContent).toContain('52%')
|
||||
expect(dialogConfirmButton().attributes('disabled')).toBeDefined()
|
||||
const dialogText = document.body.textContent || ''
|
||||
expect(dialogText).toContain('OCR 识别毛重')
|
||||
expect(dialogText).toContain('5360.000 KG')
|
||||
expect(dialogText).toContain('确认含托盘毛重')
|
||||
expect(dialogText).not.toContain('置信度')
|
||||
expect(dialogText).not.toContain('OCR 原文')
|
||||
expect(dialogText).not.toContain('OCR 可能误读数字或小数点')
|
||||
expect(dialogConfirmButton().attributes('disabled')).toBeUndefined()
|
||||
|
||||
await dialogEvidenceCheckbox().setValue(true)
|
||||
await dialogConfirmButton().trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
@@ -338,16 +351,16 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
await flushPromises()
|
||||
await openWeightDialog(wrapper)
|
||||
|
||||
await dialogWeightInput().setValue('10.125')
|
||||
await dialogWeightInput().setValue('30.125')
|
||||
await dialogUnit(1).trigger('click')
|
||||
await dialogConfirmButton().trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(confirmWeightResult).toHaveBeenCalledWith('10001', '20001', '30001', {
|
||||
version: 0,
|
||||
adjustedWeightValue: 10.125,
|
||||
adjustedWeightValue: 30.125,
|
||||
adjustedWeightUnit: 'LB',
|
||||
adjustmentReason: 'OCR 原值 285.500 KG,人工确认 10.125 LB',
|
||||
adjustmentReason: 'OCR 原值 285.500 KG,人工确认 30.125 LB',
|
||||
})
|
||||
expect(correctWeightResult).not.toHaveBeenCalled()
|
||||
})
|
||||
@@ -364,7 +377,8 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
expect(confirmWeightResult).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('accepts the smallest LB value that remains representable in kilograms', async () => {
|
||||
it('rejects a positive gross weight that does not exceed the pallet tare', async () => {
|
||||
const warning = vi.spyOn(ElMessage, 'warning')
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
await openWeightDialog(wrapper)
|
||||
@@ -374,12 +388,8 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
await dialogConfirmButton().trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(confirmWeightResult).toHaveBeenCalledWith('10001', '20001', '30001', {
|
||||
version: 0,
|
||||
adjustedWeightValue: 0.002,
|
||||
adjustedWeightUnit: 'LB',
|
||||
adjustmentReason: 'OCR 原值 285.500 KG,人工确认 0.002 LB',
|
||||
})
|
||||
expect(confirmWeightResult).not.toHaveBeenCalled()
|
||||
expect(warning).toHaveBeenCalledWith('称重毛重必须大于托盘皮重 12.000 KG')
|
||||
})
|
||||
|
||||
it('clamps a value outside the safe three-decimal JavaScript range', async () => {
|
||||
@@ -407,16 +417,16 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
await openWeightDialog(wrapper)
|
||||
const input = dialogWeightInput()
|
||||
|
||||
await input.setValue('1.2345')
|
||||
expect((input.element as HTMLInputElement).value).toBe('1.235')
|
||||
await input.setValue('13.2345')
|
||||
expect((input.element as HTMLInputElement).value).toBe('13.235')
|
||||
await dialogConfirmButton().trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(confirmWeightResult).toHaveBeenCalledWith('10001', '20001', '30001', {
|
||||
version: 0,
|
||||
adjustedWeightValue: 1.235,
|
||||
adjustedWeightValue: 13.235,
|
||||
adjustedWeightUnit: 'KG',
|
||||
adjustmentReason: 'OCR 原值 285.500 KG,人工确认 1.235 KG',
|
||||
adjustmentReason: 'OCR 原值 285.500 KG,人工确认 13.235 KG',
|
||||
})
|
||||
})
|
||||
|
||||
@@ -487,16 +497,15 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
await openWeightDialog(wrapper)
|
||||
|
||||
expect(dialogConfirmButton().attributes('disabled')).toBeDefined()
|
||||
await dialogWeightInput().setValue('1.500')
|
||||
await dialogEvidenceCheckbox().setValue(true)
|
||||
await dialogWeightInput().setValue('13.500')
|
||||
await dialogConfirmButton().trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(confirmWeightResult).toHaveBeenCalledWith('10001', '20001', '30001', {
|
||||
version: 0,
|
||||
adjustedWeightValue: 1.5,
|
||||
adjustedWeightValue: 13.5,
|
||||
adjustedWeightUnit: 'KG',
|
||||
adjustmentReason: 'OCR 原值 —,人工确认 1.500 KG',
|
||||
adjustmentReason: 'OCR 原值 —,人工确认 13.500 KG',
|
||||
})
|
||||
})
|
||||
|
||||
@@ -556,7 +565,10 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
})
|
||||
|
||||
it('keeps the edited draft available when confirmation fails', async () => {
|
||||
vi.mocked(confirmWeightResult).mockRejectedValueOnce(new ApiResponseError('数据版本已变化,请刷新后重试', 'A0409', 409))
|
||||
const errorMessage = vi.spyOn(ElMessage, 'error')
|
||||
vi.mocked(confirmWeightResult).mockRejectedValueOnce(
|
||||
new ApiResponseError('数据版本已变化,请刷新后重试', 'A0409', 409, undefined, 'request-1'),
|
||||
)
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
await openWeightDialog(wrapper)
|
||||
@@ -567,7 +579,13 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
await flushPromises()
|
||||
|
||||
expect((input.element as HTMLInputElement).value).toBe('286.125')
|
||||
expect(wrapper.text()).toContain('数据版本已变化,请刷新后重试')
|
||||
expect(wrapper.text()).not.toContain('操作未完成')
|
||||
expect(errorMessage).toHaveBeenCalledWith(expect.objectContaining({
|
||||
message: '数据版本已变化,请刷新后重试(请求 ID:request-1)',
|
||||
duration: 5_000,
|
||||
showClose: true,
|
||||
}))
|
||||
expect(wrapper.getComponent(AppDialog).props('modelValue')).toBe(true)
|
||||
expect(confirmWeightResult).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user