2026-10-10 08:05:21 +08:00
|
|
|
import ElementPlus from 'element-plus'
|
|
|
|
|
import { flushPromises, mount } from '@vue/test-utils'
|
|
|
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
|
import AppointmentCargoPanel from './AppointmentCargoPanel.vue'
|
2026-10-10 08:42:03 +08:00
|
|
|
import AppointmentContainerPanel from './AppointmentContainerPanel.vue'
|
2026-10-10 08:05:21 +08:00
|
|
|
import AppointmentFollowupDialog from './AppointmentFollowupDialog.vue'
|
2026-10-10 08:42:03 +08:00
|
|
|
import { getFollowups, listPlanningCargo, resolvePlanningSource, listPlanningContainers, resolvePlanningContainer, type PlanningCargo, type PlanningSource } from './planningApi'
|
2026-10-10 08:05:21 +08:00
|
|
|
|
2026-10-10 08:42:03 +08:00
|
|
|
vi.mock('./planningApi', () => ({ listPlanningCargo: vi.fn(), resolvePlanningSource: vi.fn(), getFollowups: vi.fn(), saveFollowup: vi.fn(), listPlanningContainers: vi.fn(), resolvePlanningContainer: vi.fn() }))
|
2026-10-10 08:05:21 +08:00
|
|
|
vi.mock('vue-router', () => ({ useRouter: () => ({ push: vi.fn() }) }))
|
|
|
|
|
vi.mock('@/core/access/accessPreview', () => ({ useAccessPreviewStore: () => ({ can: () => true }) }))
|
|
|
|
|
const source: PlanningSource = { sourceKey: 'ORDER:1', customerId: 'A', orderId: '1', inboundCode: 'IN-A', bookingNo: null, containerNo: 'CONTAINER-A', originWarehouseId: '100', originWarehouseName: '美国仓', destinationKey: 'FBA:ONT8', destinationWarehouseCode: 'ONT8', packages: 20, sourceVersion: 'ORDER:1', canFollowup: true, blockReasons: [] }
|
|
|
|
|
const cargo: PlanningCargo = { sourceKey: source.sourceKey, customerId: 'A', customerName: '客户甲', orderId: '1', inboundCode: 'IN-A', containerBookingId: '2', containerNo: 'CONTAINER-A', originWarehouseId: '100', originWarehouseCode: 'US', originWarehouseName: '美国仓', destinationWarehouseCode: 'ONT8', packages: 20, receivedPackages: null, shippedPackages: null, sourcePalletCount: null, volumeCbm: null, estimatedArrivalAt: null, estimatedWarehouseAt: null, orderVersion: 1, standardNode: 'DEPARTED', shippingVersion: null, shippingObservedAt: null, shippingProvider: null, hasInboundPlan: false, hasActiveAppointment: false, detained: false, mixedDestinations: false }
|
|
|
|
|
const coverage = { status: 'UNASSIGNED', appointments: [], missingFields: [], changeReviewRequired: false }
|
|
|
|
|
|
|
|
|
|
describe('appointment tables use actual shared table slots', () => {
|
|
|
|
|
beforeEach(() => vi.resetAllMocks())
|
2026-10-10 08:42:03 +08:00
|
|
|
it('renders one shared container and resolves each receiving warehouse without per-row requests', async () => {
|
|
|
|
|
vi.mocked(listPlanningContainers).mockResolvedValue({ total: 1, records: [{ containerBookingId: 'C1', containerNo: 'CONTAINER-A', orderCount: 20, customerCount: 12, packages: null, unknownPackageOrders: 1, earliestArrivalAt: null, latestArrivalAt: null, standardNode: 'DEPARTED', sourceVersion: null, incompleteScope: false, warehouses: [{ warehouseId: '100', warehouseName: '洛杉矶仓', orderCount: 20, customerCount: 12 }] }] })
|
|
|
|
|
vi.mocked(resolvePlanningContainer).mockResolvedValue({ containerBookingId: 'C1', containerNo: 'CONTAINER-A', warehouseId: '100', warehouseName: '洛杉矶仓', canFollowup: true, blockReasons: [] })
|
|
|
|
|
const wrapper = mount(AppointmentContainerPanel, { global: { plugins: [ElementPlus], stubs: { AppointmentFollowupDialog: true } } })
|
|
|
|
|
await flushPromises()
|
|
|
|
|
expect(listPlanningContainers).toHaveBeenCalledTimes(1)
|
|
|
|
|
expect(resolvePlanningContainer).not.toHaveBeenCalled()
|
|
|
|
|
const rows = wrapper.findAll('.el-table__body-wrapper .el-table__row')
|
|
|
|
|
expect(rows).toHaveLength(1)
|
|
|
|
|
expect(rows[0]!.text()).toContain('待核实')
|
|
|
|
|
expect(rows[0]!.text()).toContain('洛杉矶仓')
|
|
|
|
|
await rows[0]!.findAll('button').find(button => button.text() === '接仓跟进')!.trigger('click')
|
|
|
|
|
await flushPromises()
|
|
|
|
|
expect(resolvePlanningContainer).toHaveBeenCalledExactlyOnceWith('C1', '100')
|
|
|
|
|
expect(wrapper.findComponent(AppointmentFollowupDialog).props('container')?.warehouseId).toBe('100')
|
|
|
|
|
wrapper.unmount()
|
|
|
|
|
})
|
2026-10-10 08:05:21 +08:00
|
|
|
it('renders working source actions and readable progress through DataTable and RowActions', async () => {
|
|
|
|
|
vi.mocked(listPlanningCargo).mockResolvedValue({ records: [cargo], page: 1, size: 20, total: 1, pages: 1 })
|
|
|
|
|
vi.mocked(resolvePlanningSource).mockResolvedValue({ source, coverage })
|
|
|
|
|
const wrapper = mount(AppointmentCargoPanel, { global: { plugins: [ElementPlus], stubs: { AppointmentFollowupDialog: true } } })
|
|
|
|
|
await flushPromises()
|
|
|
|
|
const row = wrapper.get('.el-table__body-wrapper .el-table__row')
|
|
|
|
|
expect(row.text()).toContain('IN-A')
|
|
|
|
|
expect(row.text()).toContain('尚未建入仓计划')
|
|
|
|
|
const followup = row.findAll('button').find(button => button.text() === '跟进')
|
|
|
|
|
expect(followup).toBeDefined()
|
|
|
|
|
expect(row.findAll('button').some(button => button.text() === '查看来源')).toBe(true)
|
|
|
|
|
await followup!.trigger('click')
|
|
|
|
|
await flushPromises()
|
|
|
|
|
expect(resolvePlanningSource).toHaveBeenCalledExactlyOnceWith({ sourceKey: 'ORDER:1', customerId: 'A', destinationKey: 'FBA:ONT8' })
|
|
|
|
|
expect(wrapper.findComponent(AppointmentFollowupDialog).exists()).toBe(true)
|
|
|
|
|
wrapper.unmount()
|
|
|
|
|
})
|
|
|
|
|
it('renders followup stage names instead of blank table cells', async () => {
|
|
|
|
|
vi.mocked(getFollowups).mockResolvedValue({ history: { records: [{ stage: 'FBA_RECEIVING', version: 1, contactedParty: null, result: '等待回复', nextAction: null, followupDate: null, operatorName: '运营', createdAt: '2026-10-09T12:00:00Z' }], total: 1, page: 1, size: 10, pages: 1 }, versions: { DRAYAGE_CONTACT: 0, TERMINAL_APPOINTMENT: 0, WAREHOUSE_RECEIVING: 0, FBA_RECEIVING: 1 } })
|
|
|
|
|
const wrapper = mount(AppointmentFollowupDialog, { props: { source, coverage, canWrite: false }, global: { plugins: [ElementPlus], stubs: { AppDialog: { template: '<section><slot /></section>' } } } })
|
|
|
|
|
await flushPromises()
|
|
|
|
|
const row = wrapper.get('.el-table__body-wrapper .el-table__row')
|
|
|
|
|
expect(row.text()).toContain('FBA收货跟进')
|
|
|
|
|
expect(row.text()).toContain('等待回复')
|
|
|
|
|
wrapper.unmount()
|
|
|
|
|
})
|
|
|
|
|
})
|