2026-10-21 16:58:38 +08:00
import ElementPlus , { ElMessageBox } from 'element-plus'
import { defineComponent , h } from 'vue'
import { flushPromises , mount } from '@vue/test-utils'
import { beforeEach , expect , it , vi } from 'vitest'
import DispatchDocumentsDialog from './DispatchDocumentsDialog.vue'
import DeliveryDocumentsDialog from './DeliveryDocumentsDialog.vue'
import { detail } from '../dispatchTestFixtures'
import { getDispatch } from '../api/dispatches'
import { deliveryDocumentCategories , getDeliveryDocuments , saveDeliveryDocuments , type DeliveryDocuments } from '../api/deliveryDocuments'
const can = vi . hoisted (() => vi . fn (() => true ))
vi . mock ( '@/core/access/accessPreview' , () => ({ useAccessPreviewStore : () => ({ can }) }))
vi . mock ( '../api/dispatches' , () => ({ getDispatch : vi.fn () }))
vi . mock ( '../api/deliveryDocuments' , async original => ({ ... await original < typeof import ( '../api/deliveryDocuments' ) >(), getDeliveryDocuments : vi.fn (), saveDeliveryDocuments : vi.fn () }))
const dialogStub = defineComponent ({ props : [ 'modelValue' , 'showConfirm' ], emits : [ 'confirm' ], setup ( props , { slots , emit }) { return () => props . modelValue ? h ( 'section' , [ slots . default ? .(), props . showConfirm ? h ( 'button' , { class : 'save' , onClick : () => emit ( 'confirm' ) }, '保存资料' ) : null ]) : null } })
function documents ( no = 'DL-1' , customerId = '101' ) : DeliveryDocuments {
return { deliveryNo : no , customerId , version : 1 , bolNo : 'BOL-ORIGINAL' , uploadedCategoryCount : 1 , totalCategoryCount : 3 , allowedActions : [ 'MANAGE_DOCUMENTS' ], replayed : false , categories : deliveryDocumentCategories.map ( item => ({ category : item.category , status : item.category === 'RECEIPT' ? 'UPLOADED' : 'MISSING' , fileCount : item.category === 'RECEIPT' ? 1 : 0 , files : item.category === 'RECEIPT' ? [{ fileId : '99' , fileName : 'existing-pod.pdf' , contentType : 'application/pdf' , sizeBytes : 10 , uploadedAt : '2026-10-21T00:00:00' }] : [] })) }
}
2026-10-21 17:22:25 +08:00
function setup() { return mount ( DispatchDocumentsDialog , { props : { modelValue : true , dispatchNo : 'PC/1' }, global : { plugins : [ ElementPlus ], stubs : { AppDialog : dialogStub , DispatchVehicleDocuments : true , DispatchLoadingDocuments : true , DispatchEvidenceFiles : true } } }) }
2026-10-21 16:58:38 +08:00
beforeEach (() => {
vi . clearAllMocks (); can . mockReturnValue ( true )
const value = detail (); value . stage = 'DELIVERING'
value . documents . deliveries = [
{ deliveryNo : 'DL-1' , customerId : '101' , customerName : '客户甲' , groupKey : 'A' , outboundNo : 'OB-1' , destination : { key : 'FBA:A' , type : 'FBA' , warehouseId : null , warehouseCode : 'A' , warehouseName : null , address : null , postalCode : null , contactName : null , contactPhone : null }, status : 'DELIVERING' , packageCount : 1 , palletCount : 1 },
{ deliveryNo : 'DL-2' , customerId : '102' , customerName : '客户乙' , groupKey : 'B' , outboundNo : 'OB-2' , destination : { key : 'FBA:B' , type : 'FBA' , warehouseId : null , warehouseCode : 'B' , warehouseName : null , address : null , postalCode : null , contactName : null , contactPhone : null }, status : 'DELIVERING' , packageCount : 1 , palletCount : 1 },
]
vi . mocked ( getDispatch ). mockResolvedValue ( value )
vi . mocked ( getDeliveryDocuments ). mockImplementation ( async ( no , customer ) => documents ( no , customer ))
vi . mocked ( saveDeliveryDocuments ). mockResolvedValue ({ ... documents (), version : 2 })
})
2026-10-21 17:22:25 +08:00
it . each ([ 'LOADING' , 'AFTER_LOADING' ] as const )( 'opens loading documents in %s before delivery orders exist and without delivery-list permission' , async stage => {
vi . mocked ( getDispatch ). mockResolvedValue ( detail ({ stage }))
2026-10-21 17:08:59 +08:00
can . mockImplementation (( value? : string ) => value !== 'platform:overseas-warehouse:delivery:list' )
const wrapper = setup (); await flushPromises ()
expect ( wrapper . find ( 'dispatch-loading-documents-stub' ). exists ()). toBe ( true )
expect ( wrapper . findAll ( '[role="tab"]' ). find ( tab => tab . text () === '装车资料' ) ! . attributes ( 'aria-selected' )). toBe ( 'true' )
expect ( getDeliveryDocuments ). not . toHaveBeenCalled (); wrapper . unmount ()
})
2026-10-21 16:58:38 +08:00
it ( 'reads existing delivery files in one dialog and saves receipt without requiring loading or BOL files' , async () => {
const wrapper = setup (); await flushPromises ()
expect ( getDeliveryDocuments ). toHaveBeenCalledWith ( 'DL-1' , '101' )
expect ( wrapper . text ()). toContain ( 'existing-pod.pdf' )
expect ( wrapper . findAllComponents ( DeliveryDocumentsDialog )). toHaveLength ( 1 )
await wrapper . get ( '.save' ). trigger ( 'click' ); await flushPromises ()
expect ( saveDeliveryDocuments ). toHaveBeenCalledWith ( 'DL-1' , '101' , expect . objectContaining ({ bolNo : 'BOL-ORIGINAL' , documents : [{ category : 'LOADING_PHOTO' , fileIds : [] }, { category : 'BOL' , fileIds : [] }, { category : 'RECEIPT' , fileIds : [ '99' ] }] }))
expect ( wrapper . emitted ( 'saved' )). toHaveLength ( 1 )
expect ( wrapper . getComponent ( DeliveryDocumentsDialog ). props ( 'modelValue' )). toBe ( true )
wrapper . unmount ()
})
it ( 'switches customer scope exactly and keeps unsaved delivery edits when switching tabs' , async () => {
const wrapper = setup (); await flushPromises ()
await wrapper . findAll ( '[role="tab"]' ). find ( tab => tab . text () === '装车资料' ) ! . trigger ( 'click' )
2026-10-21 17:49:04 +08:00
expect ( wrapper . getComponent ( DeliveryDocumentsDialog ). props ( 'categories' )). toEqual ([ 'LOADING_PHOTO' , 'BOL' ])
2026-10-21 16:58:38 +08:00
await wrapper . getComponent ( DeliveryDocumentsDialog ). find ( 'input' ). setValue ( 'BOL-CHANGED' )
await wrapper . findAll ( '[role="tab"]' ). find ( tab => tab . text () === '油耗图片' ) ! . trigger ( 'click' )
expect ( getDeliveryDocuments ). toHaveBeenCalledTimes ( 1 )
const confirmation = vi . spyOn ( ElMessageBox , 'confirm' ). mockRejectedValue ( 'cancel' )
wrapper . getComponent ({ name : 'ElSelect' }). vm . $emit ( 'update:modelValue' , 'DL-2' ); await flushPromises ()
expect ( getDeliveryDocuments ). toHaveBeenCalledTimes ( 1 )
confirmation . mockResolvedValue ( 'confirm' as Awaited < ReturnType < typeof ElMessageBox.confirm >>)
wrapper . getComponent ({ name : 'ElSelect' }). vm . $emit ( 'update:modelValue' , 'DL-2' ); await flushPromises ()
expect ( getDeliveryDocuments ). toHaveBeenLastCalledWith ( 'DL-2' , '102' )
expect ( saveDeliveryDocuments ). not . toHaveBeenCalled ()
confirmation . mockRestore (); wrapper . unmount ()
})
it ( 'does not request delivery documents without delivery list permission' , async () => {
can . mockImplementation (( value? : string ) => value !== 'platform:overseas-warehouse:delivery:list' )
const wrapper = setup (); await flushPromises ()
expect ( getDeliveryDocuments ). not . toHaveBeenCalled ()
expect ( wrapper . text ()). toContain ( '当前账号无派送资料查看权限' )
wrapper . unmount ()
})