2026-10-19 17:56:31 +08:00
import ElementPlus from 'element-plus'
import { flushPromises , mount } from '@vue/test-utils'
import { beforeEach , expect , it , vi } from 'vitest'
import DispatchResourceFields from './DispatchResourceFields.vue'
import { resources } from '../dispatchTestFixtures'
2026-10-21 23:20:10 +08:00
import { listDrivers , listVehicles , type VehicleDetail } from '@/modules/overseas-master-data'
2026-10-19 17:56:31 +08:00
const can = vi . hoisted (() => vi . fn (() => true ))
vi . mock ( '@/core/access/accessPreview' , () => ({ useAccessPreviewStore : () => ({ can }) }))
vi . mock ( '@/modules/overseas-master-data' , () => ({ listDrivers : vi.fn (), listVehicles : vi.fn (), overseasMasterDataPermissions : { vehicleList : 'vehicle:list' , driverList : 'driver:list' } }))
beforeEach (() => { vi . clearAllMocks (); can . mockReturnValue ( true ) })
2026-10-21 23:20:10 +08:00
it . each ([[ '本趟承运公司' , '555-0123' ], [ null , null ]])( 'shows continuous master snapshot fields read-only and uses a dash for missing facts (%s)' , async ( carrierName , phone ) => {
const value = resources (); value . vehicle . mode = 'MASTER' ; value . vehicle . vehicleId = 'vehicle-1' ; value . vehicle . carrierName = carrierName ; value . driver . mode = 'MASTER' ; value . driver . driverId = 'driver-1' ; value . driver . phone = phone
const wrapper = mount ( DispatchResourceFields , { props : { vehicle : value.vehicle , driver : value.driver , disabled : false , continuous : true }, global : { plugins : [ ElementPlus ] } }); await flushPromises ()
const field = ( label : string ) => wrapper . findAllComponents ({ name : 'ElFormItem' }). find ( item => item . props ( 'label' ) === label ) ! . getComponent ({ name : 'ElInput' })
expect ( field ( '拖车公司名称' ). props ( 'modelValue' )). toBe ( carrierName || '—' ); expect ( field ( '拖车公司名称' ). props ( 'readonly' )). toBe ( true )
expect ( field ( '联系电话' ). props ( 'modelValue' )). toBe ( phone || '—' ); expect ( field ( '联系电话' ). props ( 'readonly' )). toBe ( true )
expect ( listVehicles ). not . toHaveBeenCalled (); expect ( listDrivers ). not . toHaveBeenCalled ()
expect ( wrapper . emitted ( 'update:vehicle' )). toBeUndefined (); expect ( wrapper . emitted ( 'update:driver' )). toBeUndefined (); wrapper . unmount ()
})
it ( 'keeps master company and phone fields out of the existing non-continuous creation form' , async () => {
const value = resources (); value . vehicle . mode = 'MASTER' ; value . driver . mode = 'MASTER'
const wrapper = mount ( DispatchResourceFields , { props : { vehicle : value.vehicle , driver : value.driver , disabled : false }, global : { plugins : [ ElementPlus ] } }); await flushPromises ()
const labels = wrapper . findAllComponents ({ name : 'ElFormItem' }). map ( item => item . props ( 'label' ))
expect ( labels ). not . toContain ( '拖车公司名称' ); expect ( labels ). not . toContain ( '联系电话' ); wrapper . unmount ()
})
it ( 'shows the newly selected authorized vehicle company without copying it into the master command' , async () => {
const candidate : VehicleDetail = { id : 'vehicle-2' , plateNumber : 'CA-200' , model : '厢式货车' , driverOrDispatchCompany : '新承运公司' , phone : null , maxPalletSpaces : 20 , maxLoadKg : 18000 , maxVolumeCbm : 60 , fuelConsumptionPer100Km : 0 , mileageKm : 0 , region : 'OVERSEAS' , ownership : 'OWNED' , status : 'IN_SERVICE' , remark : null , recordVersion : 1 , updatedBy : 'operator' , updatedAt : '2026-10-21T10:00:00Z' }
vi . mocked ( listVehicles ). mockResolvedValueOnce ({ records : [ candidate ], page : 1 , size : 100 , total : 1 , pages : 1 })
const value = resources (); value . vehicle . mode = 'MASTER' ; value . vehicle . vehicleId = 'vehicle-1'
const wrapper = mount ( DispatchResourceFields , { props : { vehicle : value.vehicle , driver : value.driver , disabled : false , continuous : true }, global : { plugins : [ ElementPlus ] } })
const state = wrapper . vm as unknown as { searchVehicles () : Promise < void >; selectVehicle ( id : string ) : void }
await state . searchVehicles (); state . selectVehicle ( 'vehicle-2' )
const selected = wrapper . emitted ( 'update:vehicle' ) ! . at ( - 1 ) ! [ 0 ] as typeof value . vehicle
expect ( selected ). toMatchObject ({ vehicleId : 'vehicle-2' , carrierName : null })
await wrapper . setProps ({ vehicle : selected })
const company = wrapper . findAllComponents ({ name : 'ElFormItem' }). find ( item => item . props ( 'label' ) === '拖车公司名称' ) ! . getComponent ({ name : 'ElInput' })
expect ( company . props ( 'modelValue' )). toBe ( '新承运公司' ); expect ( company . props ( 'readonly' )). toBe ( true ); wrapper . unmount ()
})
2026-10-20 10:11:31 +08:00
it . each ([ false , true ])( 'renders known business labels without internal IDs (continuous=%s)' , async continuous => {
2026-10-19 17:56:31 +08:00
const value = resources (); value . vehicle . mode = 'MASTER' ; value . vehicle . vehicleId = '900719925474099301' ; value . driver . mode = 'MASTER' ; value . driver . driverId = '900719925474099302'
2026-10-20 10:11:31 +08:00
const wrapper = mount ( DispatchResourceFields , { props : { vehicle : value.vehicle , driver : value.driver , disabled : false , continuous }, global : { plugins : [ ElementPlus ] } }); await flushPromises ()
2026-10-19 17:56:31 +08:00
expect ( wrapper . text ()). toContain ( 'CA-100' ); expect ( wrapper . text ()). toContain ( '司机甲' ); expect ( wrapper . text ()). not . toContain ( '90071992547409930' ); wrapper . unmount ()
})
2026-10-20 10:11:31 +08:00
it . each ([ false , true ])( 'resets only the switched resource and keeps choices independent (continuous=%s)' , async continuous => {
2026-10-19 17:56:31 +08:00
const value = resources (); value . vehicle . mode = 'MASTER' ; value . vehicle . vehicleId = 'vehicle-1'
2026-10-20 10:11:31 +08:00
const wrapper = mount ( DispatchResourceFields , { props : { vehicle : value.vehicle , driver : value.driver , disabled : false , continuous }, global : { plugins : [ ElementPlus ] } })
2026-10-19 17:56:31 +08:00
const state = wrapper . vm as unknown as { changeDriver () : void }; state . changeDriver (); await flushPromises ()
expect ( wrapper . emitted ( 'update:driver' ) ! [ 0 ] ! [ 0 ]). toMatchObject ({ mode : 'EXTERNAL' , driverId : null , name : null , evidence : { fileIds : [], licenseNo : null } })
expect ( wrapper . emitted ( 'update:vehicle' )). toBeUndefined (); expect ( value . vehicle . vehicleId ). toBe ( 'vehicle-1' ); wrapper . unmount ()
})
2026-10-20 10:11:31 +08:00
it . each ([ false , true ])( 'requires each directory permission before reading candidates (continuous=%s)' , async continuous => {
2026-10-19 17:56:31 +08:00
can . mockReturnValue ( false ); const value = resources ()
2026-10-20 10:11:31 +08:00
const wrapper = mount ( DispatchResourceFields , { props : { vehicle : value.vehicle , driver : value.driver , disabled : false , continuous }, global : { plugins : [ ElementPlus ] } })
2026-10-19 17:56:31 +08:00
const state = wrapper . vm as unknown as { searchVehicles () : Promise < void >; searchDrivers () : Promise < void > }; await state . searchVehicles (); await state . searchDrivers ()
expect ( listVehicles ). not . toHaveBeenCalled (); expect ( listDrivers ). not . toHaveBeenCalled (); expect ( wrapper . text ()). toContain ( '缺少司机档案读取权限' ); wrapper . unmount ()
})