优化
This commit is contained in:
@@ -2,25 +2,32 @@ import ElementPlus from 'element-plus'
|
||||
import { createPinia, setActivePinia } from 'pinia'
|
||||
import { enableAutoUnmount, flushPromises, mount } from '@vue/test-utils'
|
||||
import { afterAll, afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import DataTable from '@/shared/components/DataTable.vue'
|
||||
import QueryToolbar from '@/shared/components/QueryToolbar.vue'
|
||||
import {
|
||||
createFbaWarehouse,
|
||||
createPlatformWarehouse,
|
||||
getPlatformWarehouse,
|
||||
importWarehouses,
|
||||
listPlatformWarehouses,
|
||||
updatePlatformWarehouse,
|
||||
type PlatformWarehouseDetailResource,
|
||||
type PlatformWarehouseResource,
|
||||
type PlatformWarehouseSummaryResource,
|
||||
type WarehouseImportResult,
|
||||
} from '@/modules/warehouses/api/platformWarehouses'
|
||||
import { useAccessPreviewStore } from '@/core/access/accessPreview'
|
||||
import { useAuthStore } from '@/core/auth/auth'
|
||||
import QueryToolbar from '@/shared/components/QueryToolbar.vue'
|
||||
import WarehousesView from './WarehousesView.vue'
|
||||
|
||||
vi.mock('@/modules/warehouses/api/platformWarehouses', () => ({
|
||||
listPlatformWarehouses: vi.fn(),
|
||||
getPlatformWarehouse: vi.fn(),
|
||||
createPlatformWarehouse: vi.fn(),
|
||||
createFbaWarehouse: vi.fn(),
|
||||
updatePlatformWarehouse: vi.fn(),
|
||||
changePlatformWarehouseStatus: vi.fn(),
|
||||
downloadWarehouseImportTemplate: vi.fn(),
|
||||
importWarehouses: vi.fn(),
|
||||
}))
|
||||
|
||||
class ResizeObserverStub implements ResizeObserver {
|
||||
@@ -41,43 +48,109 @@ function createMemoryStorage(initial: Record<string, string> = {}): Storage {
|
||||
}
|
||||
}
|
||||
|
||||
const warehouse: PlatformWarehouseResource = {
|
||||
const domesticAddress = {
|
||||
id: '19002',
|
||||
tenantId: 0,
|
||||
warehouseId: '19001',
|
||||
addressType: 'OPERATING',
|
||||
countryCode: 'CN',
|
||||
stateProvince: '浙江省',
|
||||
city: '义乌市',
|
||||
district: '北苑街道',
|
||||
postalCode: '322000',
|
||||
addressLine1: '真实物流园 1 号库',
|
||||
addressLine2: 'A 栋',
|
||||
latitude: '29.3',
|
||||
longitude: '120.0',
|
||||
}
|
||||
|
||||
const domesticWarehouse: PlatformWarehouseSummaryResource = {
|
||||
id: '19001',
|
||||
tenantId: 10001,
|
||||
warehouseCode: 'CN-TEST-01',
|
||||
warehouseName: '测试环境收货仓',
|
||||
tenantId: 0,
|
||||
warehouseCode: 'CN-YW-01',
|
||||
warehouseName: '义乌收货仓',
|
||||
warehouseType: 'DOMESTIC',
|
||||
countryCode: 'CN',
|
||||
timezone: 'Asia/Shanghai',
|
||||
contactName: '真实联系人',
|
||||
timezone: 'UTC+8',
|
||||
contactName: '仓库客服',
|
||||
contactPhone: '0579-12345678',
|
||||
contactEmail: 'warehouse@example.com',
|
||||
status: 'ACTIVE',
|
||||
remark: '测试环境数据',
|
||||
updatedAt: '2026-07-31T10:20:00',
|
||||
addressSummary: '浙江省义乌市北苑街道 1 号库',
|
||||
primaryAddress: domesticAddress,
|
||||
}
|
||||
|
||||
const fbaAddress = {
|
||||
id: '19012',
|
||||
tenantId: 0,
|
||||
warehouseId: '19011',
|
||||
addressType: 'OPERATING',
|
||||
countryCode: 'US',
|
||||
stateProvince: 'OH',
|
||||
city: 'Canton',
|
||||
district: null,
|
||||
postalCode: '44705',
|
||||
addressLine1: '4747 Rebar Ave NE',
|
||||
addressLine2: null,
|
||||
latitude: null,
|
||||
longitude: null,
|
||||
}
|
||||
|
||||
const fbaWarehouse: PlatformWarehouseSummaryResource = {
|
||||
id: '19011',
|
||||
tenantId: 0,
|
||||
warehouseCode: 'AKR1',
|
||||
warehouseName: 'AKR1',
|
||||
warehouseType: 'FBA',
|
||||
countryCode: 'US',
|
||||
timezone: 'UTC-5',
|
||||
contactName: null,
|
||||
contactPhone: null,
|
||||
contactEmail: null,
|
||||
status: 'ACTIVE',
|
||||
remark: null,
|
||||
updatedAt: '2026-07-31T10:20:00',
|
||||
addressSummary: 'OH · Canton',
|
||||
primaryAddress: fbaAddress,
|
||||
}
|
||||
|
||||
const fbaDetail: PlatformWarehouseDetailResource = {
|
||||
warehouse: fbaWarehouse,
|
||||
addresses: [fbaAddress],
|
||||
capabilities: [],
|
||||
}
|
||||
|
||||
const detail: PlatformWarehouseDetailResource = {
|
||||
warehouse,
|
||||
addresses: [{
|
||||
id: '19002', tenantId: 10001, warehouseId: '19001', addressType: 'OPERATING', countryCode: 'CN',
|
||||
stateProvince: '浙江省', city: '义乌市', district: '北苑街道', postalCode: '322000',
|
||||
addressLine1: '真实物流园 1 号库', addressLine2: 'A 栋', latitude: '29.3', longitude: '120.0',
|
||||
}],
|
||||
warehouse: domesticWarehouse,
|
||||
addresses: [domesticAddress],
|
||||
capabilities: [
|
||||
{ id: '19003', tenantId: 10001, warehouseId: '19001', capabilityCode: 'RECEIVING', capabilityName: '收货服务', enabled: true, cutoffTime: '17:00:00', description: '周一至周六 08:30-18:00' },
|
||||
{ id: '19004', tenantId: 10001, warehouseId: '19001', capabilityCode: 'STORAGE', capabilityName: '仓储', enabled: true, cutoffTime: null, description: '托盘仓储' },
|
||||
{ id: '19003', tenantId: 0, warehouseId: '19001', capabilityCode: 'RECEIVING', capabilityName: '收货服务', enabled: true, cutoffTime: '17:00:00', description: '周一至周六 08:30-18:00' },
|
||||
{ id: '19004', tenantId: 0, warehouseId: '19001', capabilityCode: 'STORAGE', capabilityName: '仓储', enabled: true, cutoffTime: null, description: '托盘仓储' },
|
||||
],
|
||||
}
|
||||
|
||||
async function mountView() {
|
||||
const importPreview: WarehouseImportResult = {
|
||||
fileName: 'warehouses.xlsx',
|
||||
totalRows: 4,
|
||||
validRows: 3,
|
||||
createCount: 2,
|
||||
updateCount: 1,
|
||||
unchangedCount: 0,
|
||||
errorCount: 1,
|
||||
committed: false,
|
||||
errors: [{ row: 4, field: '仓库编码', code: 'DUPLICATE_CODE', message: '文件内编码重复' }],
|
||||
}
|
||||
|
||||
async function mountView(permissions = ['platform:warehouse:list', 'platform:warehouse:create', 'platform:warehouse:edit', 'platform:warehouse:status']) {
|
||||
vi.stubGlobal('localStorage', createMemoryStorage())
|
||||
vi.stubGlobal('sessionStorage', createMemoryStorage())
|
||||
const pinia = createPinia()
|
||||
setActivePinia(pinia)
|
||||
const auth = useAuthStore()
|
||||
auth.token = 'token'
|
||||
auth.permissions = ['platform:warehouse:list', 'platform:warehouse:create', 'platform:warehouse:edit', 'platform:warehouse:status']
|
||||
auth.permissions = permissions
|
||||
useAccessPreviewStore().initializeAfterLogin()
|
||||
const wrapper = mount(WarehousesView, {
|
||||
attachTo: document.body,
|
||||
@@ -87,72 +160,80 @@ async function mountView() {
|
||||
return wrapper
|
||||
}
|
||||
|
||||
function setField(selector: string, value: string) {
|
||||
const field = document.querySelector<HTMLInputElement | HTMLTextAreaElement>(selector)
|
||||
expect(field).not.toBeNull()
|
||||
field!.value = value
|
||||
field!.dispatchEvent(new Event('input', { bubbles: true }))
|
||||
}
|
||||
|
||||
enableAutoUnmount(afterEach)
|
||||
afterAll(() => vi.unstubAllGlobals())
|
||||
|
||||
describe('WarehousesView real API integration', () => {
|
||||
describe('WarehousesView', () => {
|
||||
beforeEach(() => {
|
||||
vi.stubGlobal('ResizeObserver', ResizeObserverStub)
|
||||
document.body.innerHTML = ''
|
||||
vi.mocked(listPlatformWarehouses).mockReset().mockResolvedValue({ records: [warehouse], page: 1, size: 200, total: 1, pages: 1 })
|
||||
vi.mocked(listPlatformWarehouses).mockReset().mockResolvedValue({ records: [domesticWarehouse], page: 1, size: 20, total: 1, pages: 1 })
|
||||
vi.mocked(getPlatformWarehouse).mockReset().mockResolvedValue(detail)
|
||||
vi.mocked(createPlatformWarehouse).mockReset().mockResolvedValue('19005')
|
||||
vi.mocked(createFbaWarehouse).mockReset().mockResolvedValue('19006')
|
||||
vi.mocked(updatePlatformWarehouse).mockReset().mockResolvedValue(null)
|
||||
vi.mocked(importWarehouses).mockReset().mockResolvedValue(importPreview)
|
||||
})
|
||||
|
||||
it('automatically loads the fixed tenant and renders address and receiving capability from details', async () => {
|
||||
it('loads a server-paged warehouse list with backend address summaries and no row detail fan-out', async () => {
|
||||
const wrapper = await mountView()
|
||||
|
||||
expect(listPlatformWarehouses).toHaveBeenCalledWith(10001, 1, 200)
|
||||
expect(getPlatformWarehouse).toHaveBeenCalledWith(10001, '19001')
|
||||
expect(wrapper.text()).toContain('测试环境收货仓')
|
||||
expect(wrapper.text()).toContain('北苑街道 真实物流园 1 号库 A 栋')
|
||||
expect(wrapper.text()).toContain('周一至周六 08:30-18:00')
|
||||
expect(listPlatformWarehouses).toHaveBeenCalledWith({
|
||||
page: 1,
|
||||
size: 20,
|
||||
keyword: undefined,
|
||||
warehouseType: undefined,
|
||||
status: undefined,
|
||||
})
|
||||
expect(getPlatformWarehouse).not.toHaveBeenCalled()
|
||||
expect(wrapper.text()).toContain('义乌收货仓')
|
||||
expect(wrapper.text()).toContain('浙江省义乌市北苑街道 1 号库')
|
||||
expect(wrapper.text()).toContain('国内收货仓')
|
||||
expect(wrapper.text()).toContain('Asia/Shanghai')
|
||||
expect(wrapper.text()).not.toContain('全部收货仓')
|
||||
expect(wrapper.find('.query-toolbar').exists()).toBe(true)
|
||||
expect(wrapper.text()).toContain('中国 CN')
|
||||
expect(wrapper.text()).toContain('UTC+8')
|
||||
expect(wrapper.text()).toContain('共 1 个公共仓库')
|
||||
expect(wrapper.find('.data-table').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('updates filters locally and only reloads after search', async () => {
|
||||
const wrapper = await mountView()
|
||||
const keywordInput = wrapper.find('input[placeholder="仓库名称、编码、城市或地址"]')
|
||||
|
||||
await keywordInput.setValue('义乌')
|
||||
await flushPromises()
|
||||
expect(listPlatformWarehouses).toHaveBeenCalledTimes(1)
|
||||
|
||||
const searchButton = wrapper.findAll('button').find((button) => button.text().trim() === '查询')
|
||||
expect(searchButton).toBeDefined()
|
||||
await searchButton?.trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(listPlatformWarehouses).toHaveBeenCalledTimes(2)
|
||||
expect(wrapper.text()).toContain('测试环境收货仓')
|
||||
})
|
||||
|
||||
it('uses the fixed public tenant without rendering a tenant selector', async () => {
|
||||
const wrapper = await mountView()
|
||||
|
||||
expect(wrapper.find('[aria-label="目标企业"]').exists()).toBe(false)
|
||||
expect(listPlatformWarehouses).toHaveBeenCalledWith(10001, 1, 200)
|
||||
expect(wrapper.text()).toContain('公共仓库')
|
||||
})
|
||||
|
||||
it('filters the public warehouse table by warehouse type', async () => {
|
||||
it('submits filters and pagination to the API instead of filtering rows locally', async () => {
|
||||
vi.mocked(listPlatformWarehouses).mockResolvedValue({ records: [domesticWarehouse], page: 1, size: 20, total: 45, pages: 3 })
|
||||
const wrapper = await mountView()
|
||||
|
||||
wrapper.findComponent(QueryToolbar).vm.$emit('search', {
|
||||
keyword: '', warehouseType: 'FBA', status: '',
|
||||
keyword: 'FBA',
|
||||
warehouseType: 'FBA',
|
||||
status: 'ACTIVE',
|
||||
})
|
||||
await flushPromises()
|
||||
|
||||
expect(wrapper.text()).not.toContain('测试环境收货仓')
|
||||
expect(wrapper.text()).toContain('暂无符合筛选条件的仓库')
|
||||
expect(listPlatformWarehouses).toHaveBeenLastCalledWith({
|
||||
page: 1,
|
||||
size: 20,
|
||||
keyword: 'FBA',
|
||||
warehouseType: 'FBA',
|
||||
status: 'ACTIVE',
|
||||
})
|
||||
|
||||
wrapper.findComponent(DataTable).vm.$emit('update:page', 2)
|
||||
await flushPromises()
|
||||
|
||||
expect(listPlatformWarehouses).toHaveBeenLastCalledWith({
|
||||
page: 2,
|
||||
size: 20,
|
||||
keyword: 'FBA',
|
||||
warehouseType: 'FBA',
|
||||
status: 'ACTIVE',
|
||||
})
|
||||
})
|
||||
|
||||
it('shows a recoverable real API error without falling back to demo warehouses', async () => {
|
||||
it('shows a recoverable API error without falling back to demo warehouses', async () => {
|
||||
vi.mocked(listPlatformWarehouses).mockRejectedValueOnce(new Error('Gateway unavailable'))
|
||||
const wrapper = await mountView()
|
||||
|
||||
@@ -162,66 +243,219 @@ describe('WarehousesView real API integration', () => {
|
||||
expect(wrapper.text()).not.toContain('演示物流园')
|
||||
})
|
||||
|
||||
it('preserves backend-only address, email, capability and cutoff fields when updating', async () => {
|
||||
it('keeps create actions behind permissions and preserves a read-only table state', async () => {
|
||||
const wrapper = await mountView(['platform:warehouse:list'])
|
||||
|
||||
expect(wrapper.text()).not.toContain('新增仓库')
|
||||
expect(wrapper.text()).not.toContain('导入仓库')
|
||||
expect(wrapper.text()).toContain('仅查看')
|
||||
})
|
||||
|
||||
it('creates an FBA address from the fast path with selectable state and timezone values', async () => {
|
||||
const wrapper = await mountView()
|
||||
const editButton = wrapper.findAll('button').find((button) => button.text().trim() === '编辑')
|
||||
expect(editButton).toBeDefined()
|
||||
await editButton?.trigger('click')
|
||||
|
||||
wrapper.findComponent({ name: 'ElDropdown' }).vm.$emit('command', 'FBA')
|
||||
await flushPromises()
|
||||
|
||||
const typeFormItem = wrapper.findAll('.el-form-item').find((item) => item.text().includes('仓库类型'))
|
||||
expect(typeFormItem).toBeDefined()
|
||||
typeFormItem?.findComponent({ name: 'ElSelect' }).vm.$emit('update:modelValue', 'FBA')
|
||||
await wrapper.find('input[placeholder="例如 CN、US"]').setValue('US')
|
||||
await wrapper.find('input[placeholder="例如 Asia/Shanghai"]').setValue('America/Los_Angeles')
|
||||
const drawerText = document.querySelector('.el-drawer')?.textContent || ''
|
||||
expect(drawerText).toContain('新增FBA 地址')
|
||||
expect(drawerText).toContain('国家或地区')
|
||||
expect(drawerText).not.toContain('时区覆盖')
|
||||
expect(drawerText).not.toContain('联系人')
|
||||
expect(drawerText).not.toContain('收货时间')
|
||||
const countrySelect = wrapper.findAllComponents({ name: 'ElSelect' })
|
||||
.find((select) => select.props('placeholder') === '美国 US')
|
||||
expect(countrySelect).toBeDefined()
|
||||
expect(countrySelect!.props('modelValue')).toBe('US')
|
||||
expect(countrySelect!.props('disabled')).toBe(true)
|
||||
|
||||
const saveButton = wrapper.findAll('button').find((button) => button.text().trim() === '保存仓库')
|
||||
const stateSelect = wrapper.findAllComponents({ name: 'ElSelect' })
|
||||
.find((select) => select.props('placeholder') === '请选择州')
|
||||
expect(stateSelect).toBeDefined()
|
||||
|
||||
setField('input[placeholder="例如 LAX9"]', 'lax9')
|
||||
stateSelect!.vm.$emit('update:modelValue', 'CA')
|
||||
stateSelect!.vm.$emit('change', 'CA')
|
||||
await flushPromises()
|
||||
setField('input[placeholder="例如 Long Beach"]', 'Long Beach')
|
||||
setField('input[placeholder="例如 90802"]', '90802')
|
||||
setField('textarea[placeholder="请输入街道和门牌信息"]', '2400 E Spring St')
|
||||
|
||||
const saveButton = [...document.querySelectorAll('button')].find((button) => button.textContent?.trim() === '确认新增')
|
||||
expect(saveButton).toBeDefined()
|
||||
await saveButton?.trigger('click')
|
||||
saveButton!.dispatchEvent(new MouseEvent('click', { bubbles: true }))
|
||||
await flushPromises()
|
||||
|
||||
expect(createFbaWarehouse).toHaveBeenCalledWith({
|
||||
warehouseCode: 'LAX9',
|
||||
stateProvince: 'CA',
|
||||
city: 'Long Beach',
|
||||
postalCode: '90802',
|
||||
addressLine1: '2400 E Spring St',
|
||||
timezone: 'UTC-8',
|
||||
})
|
||||
expect(createPlatformWarehouse).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('hides domestic country, timezone and type inputs while submitting fixed CN and UTC+8 defaults', async () => {
|
||||
const wrapper = await mountView()
|
||||
|
||||
wrapper.findComponent({ name: 'ElDropdown' }).vm.$emit('command', 'DOMESTIC')
|
||||
await flushPromises()
|
||||
|
||||
const drawerText = document.querySelector('.el-drawer')?.textContent || ''
|
||||
expect(drawerText).not.toContain('国家或地区')
|
||||
expect(drawerText).not.toContain('时区')
|
||||
expect(drawerText).not.toContain('仓库类型')
|
||||
|
||||
setField('input[placeholder="请输入仓库名称"]', '义乌新仓')
|
||||
setField('input[placeholder="例如 浙江省"]', '浙江省')
|
||||
setField('input[placeholder="例如 义乌市"]', '义乌市')
|
||||
setField('textarea[placeholder="请输入街道、园区、楼栋及门牌信息"]', '稠州北路 100 号')
|
||||
|
||||
const saveButton = [...document.querySelectorAll('button')].find((button) => button.textContent?.trim() === '确认新增')
|
||||
expect(saveButton).toBeDefined()
|
||||
saveButton!.dispatchEvent(new MouseEvent('click', { bubbles: true }))
|
||||
await flushPromises()
|
||||
|
||||
expect(createPlatformWarehouse).toHaveBeenCalledOnce()
|
||||
expect(vi.mocked(createPlatformWarehouse).mock.calls[0][0]).toMatchObject({
|
||||
warehouseName: '义乌新仓',
|
||||
warehouseType: 'DOMESTIC',
|
||||
countryCode: 'CN',
|
||||
timezone: 'UTC+8',
|
||||
address: expect.objectContaining({ countryCode: 'CN', city: '义乌市' }),
|
||||
})
|
||||
})
|
||||
|
||||
it('uses country and state selectors for overseas warehouse creation and auto-fills timezone when safe', async () => {
|
||||
const wrapper = await mountView()
|
||||
|
||||
wrapper.findComponent({ name: 'ElDropdown' }).vm.$emit('command', 'OVERSEAS')
|
||||
await flushPromises()
|
||||
|
||||
const countrySelect = wrapper.findAllComponents({ name: 'ElSelect' })
|
||||
.find((select) => select.props('placeholder') === '请选择国家或地区')
|
||||
expect(countrySelect).toBeDefined()
|
||||
expect(countrySelect!.props('modelValue')).toBe('US')
|
||||
|
||||
const stateSelect = wrapper.findAllComponents({ name: 'ElSelect' })
|
||||
.find((select) => select.props('placeholder') === '请选择州')
|
||||
expect(stateSelect).toBeDefined()
|
||||
const timezoneSelect = wrapper.findAllComponents({ name: 'ElSelect' })
|
||||
.find((select) => select.props('placeholder') === '请选择时区')
|
||||
expect(timezoneSelect).toBeDefined()
|
||||
expect(wrapper.findAllComponents({ name: 'ElOption' }).some((option) => option.props('value') === 'UTC-8')).toBe(true)
|
||||
|
||||
setField('input[placeholder="请输入仓库名称"]', '洛杉矶海外仓')
|
||||
stateSelect!.vm.$emit('update:modelValue', 'CA')
|
||||
stateSelect!.vm.$emit('change', 'CA')
|
||||
setField('input[placeholder="例如 Long Beach"]', 'Long Beach')
|
||||
setField('textarea[placeholder="请输入街道、园区、楼栋及门牌信息"]', '2400 E Spring St')
|
||||
|
||||
const saveButton = [...document.querySelectorAll('button')].find((button) => button.textContent?.trim() === '确认新增')
|
||||
expect(saveButton).toBeDefined()
|
||||
saveButton!.dispatchEvent(new MouseEvent('click', { bubbles: true }))
|
||||
await flushPromises()
|
||||
|
||||
expect(createPlatformWarehouse).toHaveBeenCalledOnce()
|
||||
expect(vi.mocked(createPlatformWarehouse).mock.calls[0][0]).toMatchObject({
|
||||
warehouseName: '洛杉矶海外仓',
|
||||
warehouseType: 'OVERSEAS',
|
||||
countryCode: 'US',
|
||||
timezone: 'UTC-8',
|
||||
address: expect.objectContaining({ stateProvince: 'CA' }),
|
||||
})
|
||||
})
|
||||
|
||||
it('edits FBA warehouses with selectors for country, timezone and state', async () => {
|
||||
vi.mocked(listPlatformWarehouses).mockResolvedValueOnce({ records: [fbaWarehouse, domesticWarehouse], page: 1, size: 20, total: 2, pages: 1 })
|
||||
vi.mocked(getPlatformWarehouse).mockResolvedValueOnce(fbaDetail)
|
||||
const wrapper = await mountView()
|
||||
|
||||
const editButton = wrapper.find('.el-table__body-wrapper .table-actions button')
|
||||
expect(editButton).toBeDefined()
|
||||
await editButton.trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
const drawerText = document.querySelector('.el-drawer')?.textContent || ''
|
||||
expect(drawerText).toContain('编辑FBA 地址')
|
||||
expect(drawerText).not.toContain('例如 US')
|
||||
expect(drawerText).not.toContain('例如 UTC-8')
|
||||
|
||||
const countrySelect = wrapper.findAllComponents({ name: 'ElSelect' })
|
||||
.find((select) => select.props('placeholder') === '请选择国家或地区')
|
||||
const stateSelect = wrapper.findAllComponents({ name: 'ElSelect' })
|
||||
.find((select) => select.props('placeholder') === '请选择州')
|
||||
const timezoneSelect = wrapper.findAllComponents({ name: 'ElSelect' })
|
||||
.find((select) => select.props('placeholder') === '请选择时区')
|
||||
expect(countrySelect?.props('modelValue')).toBe('US')
|
||||
expect(stateSelect?.props('modelValue')).toBe('OH')
|
||||
expect(timezoneSelect?.props('modelValue')).toBe('UTC-5')
|
||||
expect(countrySelect).toBeDefined()
|
||||
|
||||
const saveButton = [...document.querySelectorAll('button')].find((button) => button.textContent?.trim() === '保存修改')
|
||||
expect(saveButton).toBeDefined()
|
||||
saveButton!.dispatchEvent(new MouseEvent('click', { bubbles: true }))
|
||||
await flushPromises()
|
||||
|
||||
expect(updatePlatformWarehouse).toHaveBeenCalledOnce()
|
||||
const [, , payload] = vi.mocked(updatePlatformWarehouse).mock.calls[0]
|
||||
expect(payload.contactEmail).toBe('warehouse@example.com')
|
||||
const [, payload] = vi.mocked(updatePlatformWarehouse).mock.calls[0]
|
||||
expect(payload).toMatchObject({
|
||||
tenantId: 10001, warehouseType: 'FBA', countryCode: 'US', timezone: 'America/Los_Angeles',
|
||||
})
|
||||
expect(payload.address).toMatchObject({
|
||||
countryCode: 'US', district: '北苑街道', postalCode: '322000', addressLine1: '真实物流园 1 号库', addressLine2: 'A 栋',
|
||||
latitude: '29.3', longitude: '120.0',
|
||||
warehouseType: 'FBA',
|
||||
countryCode: 'US',
|
||||
timezone: 'UTC-5',
|
||||
address: expect.objectContaining({ stateProvince: 'OH' }),
|
||||
})
|
||||
})
|
||||
|
||||
it('edits existing records with full fields and preserves backend-only capabilities', async () => {
|
||||
const wrapper = await mountView()
|
||||
|
||||
const editButton = wrapper.find('.el-table__body-wrapper .table-actions button')
|
||||
expect(editButton).toBeDefined()
|
||||
await editButton.trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
const saveButton = [...document.querySelectorAll('button')].find((button) => button.textContent?.trim() === '保存修改')
|
||||
expect(saveButton).toBeDefined()
|
||||
saveButton!.dispatchEvent(new MouseEvent('click', { bubbles: true }))
|
||||
await flushPromises()
|
||||
|
||||
expect(getPlatformWarehouse).toHaveBeenCalledWith('19001')
|
||||
expect(updatePlatformWarehouse).toHaveBeenCalledOnce()
|
||||
const [, payload] = vi.mocked(updatePlatformWarehouse).mock.calls[0]
|
||||
expect(payload.contactEmail).toBe('warehouse@example.com')
|
||||
expect(payload.capabilities).toContainEqual(expect.objectContaining({
|
||||
capabilityCode: 'RECEIVING', cutoffTime: '17:00:00', description: '周一至周六 08:30-18:00',
|
||||
capabilityCode: 'RECEIVING',
|
||||
cutoffTime: '17:00:00',
|
||||
description: '周一至周六 08:30-18:00',
|
||||
}))
|
||||
expect(payload.capabilities).toContainEqual(expect.objectContaining({ capabilityCode: 'STORAGE', description: '托盘仓储' }))
|
||||
})
|
||||
|
||||
it('shows field-level required errors and does not submit an empty warehouse', async () => {
|
||||
it('renders FBA import precheck totals and row-level errors without committing by default', async () => {
|
||||
const wrapper = await mountView()
|
||||
const createButton = wrapper.findAll('button').find((button) => button.text().trim() === '新增仓库')
|
||||
expect(createButton).toBeDefined()
|
||||
await createButton?.trigger('click')
|
||||
|
||||
await wrapper.findAll('button').find((button) => button.text().trim() === '导入仓库')?.trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(document.querySelector('input[placeholder="例如 广东省"]')).not.toBeNull()
|
||||
expect(document.querySelector('input[placeholder="例如 CN、US"]')).not.toBeNull()
|
||||
expect(document.querySelector('input[placeholder="例如 Asia/Shanghai"]')).not.toBeNull()
|
||||
expect(document.querySelector('input[placeholder="请输入仓库联系人姓名"]')).not.toBeNull()
|
||||
expect(document.querySelector('textarea[placeholder="请输入街道、园区、楼栋及库位信息"]')).not.toBeNull()
|
||||
|
||||
await wrapper.find('input[placeholder="例如 CN-NB-01"]').trigger('blur')
|
||||
await wrapper.vm.$nextTick()
|
||||
expect(wrapper.find('#warehouse-code-error').text()).toBe('请输入仓库编码')
|
||||
|
||||
const saveButton = wrapper.findAll('button').find((button) => button.text().trim() === '保存仓库')
|
||||
expect(saveButton).toBeDefined()
|
||||
await saveButton?.trigger('click')
|
||||
const upload = wrapper.findComponent({ name: 'ElUpload' })
|
||||
const file = new File(['content'], 'fba.xlsx', { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
|
||||
upload.props('onChange')({ name: file.name, raw: file })
|
||||
await flushPromises()
|
||||
|
||||
expect(createPlatformWarehouse).not.toHaveBeenCalled()
|
||||
expect(wrapper.text()).toContain('请输入仓库编码')
|
||||
expect(wrapper.text()).toContain('请输入仓库名称')
|
||||
expect(wrapper.text()).toContain('请输入城市')
|
||||
expect(wrapper.text()).toContain('请输入详细地址')
|
||||
const precheckButton = [...document.querySelectorAll('button')].find((button) => button.textContent?.trim() === '预检文件')
|
||||
expect(precheckButton).toBeDefined()
|
||||
precheckButton!.dispatchEvent(new MouseEvent('click', { bubbles: true }))
|
||||
await flushPromises()
|
||||
|
||||
expect(importWarehouses).toHaveBeenCalledWith(file, true, 'CREATE_ONLY')
|
||||
expect(document.body.textContent).toContain('新增')
|
||||
expect(document.body.textContent).toContain('更新')
|
||||
expect(document.body.textContent).toContain('无变化')
|
||||
expect(document.body.textContent).toContain('错误')
|
||||
expect(document.body.textContent).toContain('文件内编码重复')
|
||||
expect(importWarehouses).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user