Files
admin-web/src/modules/overseas-warehouse/pages/InventoryCustomerName.behavior.test.ts
T
2026-10-20 14:00:49 +08:00

113 lines
7.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import ElementPlus from 'element-plus'
import { createPinia } from 'pinia'
import { enableAutoUnmount, flushPromises, mount } from '@vue/test-utils'
import { afterAll, afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { getInventoryPieceProjection, getInventorySummary, listInventoryBalances, listInventoryLedger, listInventoryPositions } from '../api/inventory'
import InventoryDetailView from './InventoryDetailView.vue'
import InventoryView from './InventoryView.vue'
const routing = vi.hoisted(() => ({ push: vi.fn(), route: { params: {} as Record<string, string>, query: {} as Record<string, string> } }))
vi.mock('vue-router', () => ({ useRoute: () => routing.route, useRouter: () => ({ push: routing.push }) }))
vi.mock('@/core/access/accessPreview', () => ({ useAccessPreviewStore: () => ({ can: () => false }) }))
vi.mock('../api/pallets', () => ({ listReceivingOverseasWarehouses: vi.fn() }))
vi.mock('../api/inventory', () => ({
listInventoryBalances: vi.fn(), getInventorySummary: vi.fn(),
listInventoryPositions: vi.fn(), listInventoryLedger: vi.fn(),
getInventoryPieceProjection: vi.fn(),
}))
class ResizeObserverStub implements ResizeObserver { observe() {} unobserve() {} disconnect() {} }
function memoryStorage(): Storage {
const values = new Map<string, string>()
return {
get length() { return values.size }, clear: () => values.clear(), getItem: (key) => values.get(key) ?? null,
key: (index) => [...values.keys()][index] ?? null, removeItem: (key) => values.delete(key), setItem: (key, value) => values.set(key, value),
}
}
const customerId = '2092618717861048321'
const balance = {
id: '2092873463568596994', customerId, customerName: '华远贸易', overseasWarehouseId: '200',
overseasWarehouseName: '洛杉矶仓', inboundOrderId: '300', inboundOrderNo: 'LIP-1', inboundCode: 'IN-1',
destinationWarehouseName: 'ONT8目的仓',
skuCode: 'SKU-1', productNameZh: '验收商品', totalPackages: 10, availablePackages: 10,
holdPackages: 0, allocatedPackages: 0, pickedPackages: 0, inTransitPackages: 0,
receivingPackages: 0, procurementPackages: 0, updatedAt: '2026-08-28T10:00:00',
}
enableAutoUnmount(afterEach)
afterAll(() => vi.unstubAllGlobals())
describe('inventory customer-name snapshots', () => {
beforeEach(() => {
vi.stubGlobal('ResizeObserver', ResizeObserverStub)
vi.stubGlobal('localStorage', memoryStorage())
routing.push.mockReset(); routing.route.params = {}; routing.route.query = {}
vi.mocked(listInventoryBalances).mockReset().mockResolvedValue({ records: [balance], page: 1, size: 10, total: 1, pages: 1 })
vi.mocked(getInventorySummary).mockReset().mockResolvedValue({ inboundOrderCount: 1, palletCount: 1, totalPackages: 10, availablePackages: 10, holdPackages: 0, allocatedPackages: 0, pickedPackages: 0, inTransitPackages: 0, receivingPackages: 0, procurementPackages: 0 })
vi.mocked(listInventoryPositions).mockReset().mockResolvedValue([])
vi.mocked(getInventoryPieceProjection).mockReset().mockResolvedValue({ availablePieceCount: null, knownAvailablePieceCount: 0, unknownCartonCount: 10, availableCartonCount: 10, availablePalletCount: 1, groups: [] })
vi.mocked(listInventoryLedger).mockReset().mockResolvedValue({ records: [], page: 1, size: 200, total: 0, pages: 0 })
})
it('renders the formal server customerName in the inventory list', async () => {
const wrapper = mount(InventoryView, { attachTo: document.body, global: { plugins: [createPinia(), ElementPlus] } })
await flushPromises()
expect(wrapper.text()).toContain('华远贸易')
expect(wrapper.text()).toContain('洛杉矶仓')
expect(wrapper.text()).not.toContain('ONT8目的仓')
expect(wrapper.text()).not.toContain(customerId)
})
it('renders the same server snapshot in inventory detail', async () => {
routing.route.params = { inventoryId: balance.id }
routing.route.query = { overseasWarehouseId: balance.overseasWarehouseId, inboundOrderNo: balance.inboundOrderNo, inboundCode: balance.inboundCode, skuCode: balance.skuCode }
const wrapper = mount(InventoryDetailView, { attachTo: document.body, global: { plugins: [createPinia(), ElementPlus] } })
await flushPromises()
expect(wrapper.text()).toContain('华远贸易')
expect(wrapper.text()).toContain('洛杉矶仓')
expect(wrapper.find('.density-detail-title').text()).toBe(`${balance.inboundOrderNo} / ${balance.inboundCode} / ${balance.skuCode}`)
expect(wrapper.text()).toContain('美本土散板')
expect(wrapper.text()).not.toContain('美本土散版')
expect(wrapper.text()).not.toContain('ONT8目的仓')
expect(wrapper.text()).not.toContain(customerId)
expect(wrapper.text()).not.toContain(balance.id)
})
it('keeps the formal customer and carton list when piece projection fails', async () => {
vi.mocked(getInventoryPieceProjection).mockRejectedValueOnce(new Error('projection unavailable'))
const wrapper = mount(InventoryView, { attachTo: document.body, global: { plugins: [createPinia(), ElementPlus] } })
await flushPromises()
expect(wrapper.text()).toContain('华远贸易')
expect(wrapper.text()).toContain('可用件数及箱内SKU加载失败')
expect(wrapper.text()).not.toContain('库存数据加载失败')
})
it('renders every mixed-carton SKU and real piece count alongside carton totals', async () => {
vi.mocked(getInventoryPieceProjection).mockResolvedValueOnce({ availablePieceCount: '12', knownAvailablePieceCount: '12', unknownCartonCount: '0', availableCartonCount: '2', availablePalletCount: '1', groups: [{ customerId, warehouseId: '200', destinationCode: null, anchorSkuCode: 'SKU-1', availablePieceCount: '12', knownAvailablePieceCount: '12', unknownCartonCount: '0', availableCartonCount: '2', availablePalletCount: '1', skuContents: [{ skuCode: 'SKU-1', quantity: '5' }, { skuCode: 'SKU-SECOND', quantity: '7' }], cartons: [] }] })
const wrapper = mount(InventoryView, { attachTo: document.body, global: { plugins: [createPinia(), ElementPlus] } })
await flushPromises()
expect(wrapper.text()).toContain('华远贸易')
expect(wrapper.text()).toContain('SKU-1 × 5 件;SKU-SECOND × 7 件')
expect(wrapper.text()).toContain('可用 12 件 / 2 箱 / 1 托')
})
it('combines the available references and then shows an explicit empty business reference without exposing the inventory id', async () => {
vi.mocked(listInventoryBalances).mockResolvedValueOnce({ records: [{ ...balance, inboundOrderNo: '', skuCode: '' }], page: 1, size: 10, total: 1, pages: 1 })
routing.route.params = { inventoryId: balance.id }
routing.route.query = { inboundCode: balance.inboundCode }
const inboundCodeWrapper = mount(InventoryDetailView, { attachTo: document.body, global: { plugins: [createPinia(), ElementPlus] } })
await flushPromises()
expect(inboundCodeWrapper.find('.density-detail-title').text()).toBe(`${balance.inboundCode}`)
expect(inboundCodeWrapper.text()).not.toContain(balance.id)
inboundCodeWrapper.unmount()
vi.mocked(listInventoryBalances).mockResolvedValueOnce({ records: [{ ...balance, inboundOrderNo: '', inboundCode: '', skuCode: '' }], page: 1, size: 10, total: 1, pages: 1 })
routing.route.query = {}
const emptyWrapper = mount(InventoryDetailView, { attachTo: document.body, global: { plugins: [createPinia(), ElementPlus] } })
await flushPromises()
expect(emptyWrapper.find('.density-detail-title').text()).toBe('—')
expect(emptyWrapper.text()).not.toContain(balance.id)
})
})