优化
This commit is contained in:
@@ -1,13 +1,19 @@
|
||||
import ElementPlus from 'element-plus'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { createPinia, setActivePinia } from 'pinia'
|
||||
import { enableAutoUnmount, flushPromises, mount } from '@vue/test-utils'
|
||||
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 {
|
||||
confirmWeightResult,
|
||||
correctWeightResult,
|
||||
createWeightResult,
|
||||
deleteWeightResult,
|
||||
downloadWeightImage,
|
||||
downloadWeightThumbnail,
|
||||
getWeightWorkspace,
|
||||
uploadWeightImage,
|
||||
} from '../api/weightOcr'
|
||||
import type { WeightResultResource, WeightWorkspaceResource } from '../types'
|
||||
import WeightOcrPanel from './WeightOcrPanel.vue'
|
||||
@@ -18,7 +24,12 @@ vi.mock('../api/weightOcr', async () => {
|
||||
...actual,
|
||||
confirmWeightResult: vi.fn(),
|
||||
correctWeightResult: vi.fn(),
|
||||
createWeightResult: vi.fn(),
|
||||
deleteWeightResult: vi.fn(),
|
||||
downloadWeightImage: vi.fn(),
|
||||
downloadWeightThumbnail: vi.fn(),
|
||||
getWeightWorkspace: vi.fn(),
|
||||
uploadWeightImage: vi.fn(),
|
||||
}
|
||||
})
|
||||
|
||||
@@ -72,11 +83,40 @@ function mountPanel(permissions = allWeightPermissions) {
|
||||
})
|
||||
}
|
||||
|
||||
async function openWeightDialog(wrapper: VueWrapper) {
|
||||
await wrapper.get('button[aria-label="查看称重图片 1"]').trigger('click')
|
||||
await flushPromises()
|
||||
}
|
||||
|
||||
function dialogWeightInput() {
|
||||
const input = document.body.querySelector<HTMLInputElement>('input[aria-label="当前图片确认重量"]')
|
||||
if (!input) throw new Error('weight confirmation input is missing')
|
||||
return new DOMWrapper(input)
|
||||
}
|
||||
|
||||
function dialogUnit(index: number) {
|
||||
const option = document.body.querySelectorAll<HTMLElement>('.el-dialog .el-segmented__item').item(index)
|
||||
return new DOMWrapper(option)
|
||||
}
|
||||
|
||||
function dialogConfirmButton() {
|
||||
const button = [...document.body.querySelectorAll<HTMLButtonElement>('.el-dialog__footer button')]
|
||||
.find((candidate) => candidate.textContent?.trim() === '确认重量')
|
||||
if (!button) throw new Error('weight confirmation button is missing')
|
||||
return new DOMWrapper(button)
|
||||
}
|
||||
|
||||
describe('WeightOcrPanel confirmation behavior', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
document.body.innerHTML = ''
|
||||
vi.mocked(getWeightWorkspace).mockResolvedValue(workspace)
|
||||
vi.mocked(downloadWeightImage).mockResolvedValue(new Blob(['image'], { type: 'image/jpeg' }))
|
||||
vi.mocked(downloadWeightThumbnail).mockResolvedValue(new Blob(['thumb'], { type: 'image/jpeg' }))
|
||||
vi.stubGlobal('URL', {
|
||||
createObjectURL: vi.fn(() => 'blob:test-image'),
|
||||
revokeObjectURL: vi.fn(),
|
||||
})
|
||||
vi.mocked(confirmWeightResult).mockResolvedValue({
|
||||
...pendingWeight,
|
||||
recognitionStatus: 'CONFIRMED',
|
||||
@@ -85,11 +125,79 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('confirms an unchanged OCR value with one request', async () => {
|
||||
it('opens the editable confirmation dialog immediately after upload', async () => {
|
||||
vi.mocked(uploadWeightImage).mockResolvedValue({
|
||||
fileId: '40002',
|
||||
fileName: 'weight.jpg',
|
||||
contentType: 'image/jpeg',
|
||||
sizeBytes: 100,
|
||||
recognitionStatus: 'SUCCESS',
|
||||
weightValue: 12.5,
|
||||
weightUnit: 'KG',
|
||||
confidence: 0.98,
|
||||
error: null,
|
||||
})
|
||||
vi.mocked(createWeightResult).mockResolvedValue({
|
||||
...pendingWeight,
|
||||
id: '30002',
|
||||
fileId: '40002',
|
||||
ocrWeightValue: 12.5,
|
||||
})
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
const input = wrapper.get('input[type="file"]')
|
||||
const file = new File(['image'], 'weight.jpg', { type: 'image/jpeg' })
|
||||
Object.defineProperty(input.element, 'files', { configurable: true, value: [file] })
|
||||
|
||||
await input.trigger('change')
|
||||
await flushPromises()
|
||||
|
||||
expect(uploadWeightImage).toHaveBeenCalledWith('10001', '20001', file)
|
||||
expect(document.body.textContent).toContain('确认称重图片')
|
||||
expect(document.body.textContent).toContain('识别重量 12.500 KG')
|
||||
expect(document.body.querySelector('input[aria-label="当前图片确认重量"]')).not.toBeNull()
|
||||
})
|
||||
|
||||
it('renders thirty compact image cards without technical OCR details', async () => {
|
||||
vi.mocked(getWeightWorkspace).mockResolvedValue({
|
||||
...workspace,
|
||||
weightResults: Array.from({ length: 30 }, (_, index) => ({
|
||||
...pendingWeight,
|
||||
id: String(30001 + index),
|
||||
fileId: String(40001 + index),
|
||||
ocrRawText: `raw-${index}`,
|
||||
})),
|
||||
})
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
|
||||
await wrapper.get('.weight-row__editor .el-button--success').trigger('click')
|
||||
expect(wrapper.findAll('.weight-card')).toHaveLength(30)
|
||||
expect(wrapper.findAll('.weight-thumb')).toHaveLength(30)
|
||||
expect(wrapper.text()).not.toContain('置信度')
|
||||
expect(wrapper.text()).not.toContain('OCR 原文')
|
||||
expect(wrapper.text()).not.toContain('FILE_WEIGHT_OCR')
|
||||
expect(wrapper.text()).not.toContain('raw-0')
|
||||
})
|
||||
|
||||
it('deletes a pending image with its optimistic-lock version', async () => {
|
||||
vi.spyOn(ElMessageBox, 'confirm').mockResolvedValue(undefined as never)
|
||||
vi.mocked(deleteWeightResult).mockResolvedValue(undefined)
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
|
||||
await wrapper.get('button[aria-label="删除称重图片 1"]').trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(deleteWeightResult).toHaveBeenCalledWith('10001', '20001', '30001', 0)
|
||||
})
|
||||
|
||||
it('confirms an unchanged OCR value with one request', async () => {
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
await openWeightDialog(wrapper)
|
||||
|
||||
expect(document.body.textContent).not.toContain('识别重量 285.500 KG')
|
||||
await dialogConfirmButton().trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(confirmWeightResult).toHaveBeenCalledTimes(1)
|
||||
@@ -100,9 +208,10 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
it('sends the adjusted value and a specific audit reason in the same confirmation request', async () => {
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
await openWeightDialog(wrapper)
|
||||
|
||||
await wrapper.get('input[aria-label="称重图片序号 1 的确认重量"]').setValue('286.125')
|
||||
await wrapper.get('.weight-row__editor .el-button--success').trigger('click')
|
||||
await dialogWeightInput().setValue('286.125')
|
||||
await dialogConfirmButton().trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(confirmWeightResult).toHaveBeenCalledTimes(1)
|
||||
@@ -118,10 +227,11 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
it('sends an LB adjustment atomically after switching units', async () => {
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
await openWeightDialog(wrapper)
|
||||
|
||||
await wrapper.get('input[aria-label="称重图片序号 1 的确认重量"]').setValue('10.125')
|
||||
await wrapper.findAll('.el-segmented__item').at(1)?.trigger('click')
|
||||
await wrapper.get('.weight-row__editor .el-button--success').trigger('click')
|
||||
await dialogWeightInput().setValue('10.125')
|
||||
await dialogUnit(1).trigger('click')
|
||||
await dialogConfirmButton().trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(confirmWeightResult).toHaveBeenCalledWith('10001', '20001', '30001', {
|
||||
@@ -136,21 +246,23 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
it('rejects an LB value that would round to zero kilograms', async () => {
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
await openWeightDialog(wrapper)
|
||||
|
||||
await wrapper.get('input[aria-label="称重图片序号 1 的确认重量"]').setValue('0.001')
|
||||
await wrapper.findAll('.el-segmented__item').at(1)?.trigger('click')
|
||||
await dialogWeightInput().setValue('0.001')
|
||||
await dialogUnit(1).trigger('click')
|
||||
|
||||
expect(wrapper.get('.weight-row__editor .el-button--success').attributes('disabled')).toBeDefined()
|
||||
expect(dialogConfirmButton().attributes('disabled')).toBeDefined()
|
||||
expect(confirmWeightResult).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('accepts the smallest LB value that remains representable in kilograms', async () => {
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
await openWeightDialog(wrapper)
|
||||
|
||||
await wrapper.get('input[aria-label="称重图片序号 1 的确认重量"]').setValue('0.002')
|
||||
await wrapper.findAll('.el-segmented__item').at(1)?.trigger('click')
|
||||
await wrapper.get('.weight-row__editor .el-button--success').trigger('click')
|
||||
await dialogWeightInput().setValue('0.002')
|
||||
await dialogUnit(1).trigger('click')
|
||||
await dialogConfirmButton().trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(confirmWeightResult).toHaveBeenCalledWith('10001', '20001', '30001', {
|
||||
@@ -164,11 +276,12 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
it('clamps a value outside the safe three-decimal JavaScript range', async () => {
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
const input = wrapper.get('input[aria-label="称重图片序号 1 的确认重量"]')
|
||||
await openWeightDialog(wrapper)
|
||||
const input = dialogWeightInput()
|
||||
|
||||
await input.setValue('9000000000001')
|
||||
expect((input.element as HTMLInputElement).value).toBe('9000000000000.000')
|
||||
await wrapper.get('.weight-row__editor .el-button--success').trigger('click')
|
||||
await dialogConfirmButton().trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(confirmWeightResult).toHaveBeenCalledWith('10001', '20001', '30001', {
|
||||
@@ -182,11 +295,12 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
it('rounds an input with more than three decimals before confirmation', async () => {
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
const input = wrapper.get('input[aria-label="称重图片序号 1 的确认重量"]')
|
||||
await openWeightDialog(wrapper)
|
||||
const input = dialogWeightInput()
|
||||
|
||||
await input.setValue('1.2345')
|
||||
expect((input.element as HTMLInputElement).value).toBe('1.235')
|
||||
await wrapper.get('.weight-row__editor .el-button--success').trigger('click')
|
||||
await dialogConfirmButton().trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(confirmWeightResult).toHaveBeenCalledWith('10001', '20001', '30001', {
|
||||
@@ -210,8 +324,9 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
})
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
await openWeightDialog(wrapper)
|
||||
|
||||
await wrapper.get('.weight-row__editor .el-button--success').trigger('click')
|
||||
await dialogConfirmButton().trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(confirmWeightResult).toHaveBeenCalledWith('10001', '20001', '30001', { version: 1 })
|
||||
@@ -224,9 +339,10 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
'platform:firstleg:inbound:weight:confirm',
|
||||
])
|
||||
await flushPromises()
|
||||
await openWeightDialog(wrapper)
|
||||
|
||||
expect(wrapper.get('input[aria-label="称重图片序号 1 的确认重量"]').attributes('disabled')).toBeDefined()
|
||||
await wrapper.get('.weight-row__editor .el-button--success').trigger('click')
|
||||
expect(dialogWeightInput().attributes('disabled')).toBeDefined()
|
||||
await dialogConfirmButton().trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(confirmWeightResult).toHaveBeenCalledWith('10001', '20001', '30001', { version: 0 })
|
||||
@@ -238,8 +354,11 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
'platform:firstleg:inbound:weight:edit',
|
||||
])
|
||||
await flushPromises()
|
||||
await openWeightDialog(wrapper)
|
||||
|
||||
expect(wrapper.find('.weight-row__editor .el-button--success').exists()).toBe(false)
|
||||
const confirmButtons = [...document.body.querySelectorAll<HTMLButtonElement>('.el-dialog__footer button')]
|
||||
.filter((button) => button.textContent?.trim() === '确认重量')
|
||||
expect(confirmButtons).toHaveLength(0)
|
||||
expect(confirmWeightResult).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
@@ -256,10 +375,11 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
})
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
await openWeightDialog(wrapper)
|
||||
|
||||
expect(wrapper.get('.weight-row__editor .el-button--success').attributes('disabled')).toBeDefined()
|
||||
await wrapper.get('input[aria-label="称重图片序号 1 的确认重量"]').setValue('1.500')
|
||||
await wrapper.get('.weight-row__editor .el-button--success').trigger('click')
|
||||
expect(dialogConfirmButton().attributes('disabled')).toBeDefined()
|
||||
await dialogWeightInput().setValue('1.500')
|
||||
await dialogConfirmButton().trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(confirmWeightResult).toHaveBeenCalledWith('10001', '20001', '30001', {
|
||||
@@ -277,8 +397,9 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
})
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
await openWeightDialog(wrapper)
|
||||
|
||||
await wrapper.get('.weight-row__editor .el-button--success').trigger('click')
|
||||
await dialogConfirmButton().trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(confirmWeightResult).toHaveBeenCalledWith('10001', '20001', '30001', { version: 0 })
|
||||
@@ -291,8 +412,9 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
})
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
await openWeightDialog(wrapper)
|
||||
|
||||
await wrapper.get('.weight-row__editor .el-button--success').trigger('click')
|
||||
await dialogConfirmButton().trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(confirmWeightResult).toHaveBeenCalledWith('10001', '20001', '30001', {
|
||||
@@ -310,8 +432,9 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
})
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
await openWeightDialog(wrapper)
|
||||
|
||||
await wrapper.get('.weight-row__editor .el-button--success').trigger('click')
|
||||
await dialogConfirmButton().trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(confirmWeightResult).toHaveBeenCalledWith('10001', '20001', '30001', {
|
||||
@@ -326,10 +449,11 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
vi.mocked(confirmWeightResult).mockRejectedValueOnce(new Error('version conflict'))
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
const input = wrapper.get('input[aria-label="称重图片序号 1 的确认重量"]')
|
||||
await openWeightDialog(wrapper)
|
||||
const input = dialogWeightInput()
|
||||
|
||||
await input.setValue('286.125')
|
||||
await wrapper.get('.weight-row__editor .el-button--success').trigger('click')
|
||||
await dialogConfirmButton().trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect((input.element as HTMLInputElement).value).toBe('286.125')
|
||||
|
||||
Reference in New Issue
Block a user