152 lines
8.7 KiB
TypeScript
152 lines
8.7 KiB
TypeScript
import { readFileSync } from 'node:fs'
|
|
import { resolve } from 'node:path'
|
|
import { describe, expect, it } from 'vitest'
|
|
import { unifiedOrderStatusOptions } from '../api/unifiedOrders'
|
|
|
|
const source = readFileSync(resolve(process.cwd(), 'src/modules/unified-orders/pages/UnifiedOrdersView.vue'), 'utf8')
|
|
const routeSource = readFileSync(resolve(process.cwd(), 'src/modules/unified-orders/routes.ts'), 'utf8')
|
|
|
|
describe('UnifiedOrdersView contract', () => {
|
|
it('only exposes the seven product main statuses', () => {
|
|
expect(unifiedOrderStatusOptions.map((item) => item.label)).toEqual([
|
|
'待审核', '待测量数据', '已入库', '待分柜', '装柜中', '装柜完成', '派送完成',
|
|
])
|
|
for (const legacyLabel of ['待客户确认', '差异处理中', '派送中', '进入分柜']) {
|
|
expect(source).not.toContain(legacyLabel)
|
|
}
|
|
})
|
|
|
|
it('renders accessible current-status tabs with keyboard navigation', () => {
|
|
expect(source).toContain('role="tablist"')
|
|
expect(source).toContain('role="tab"')
|
|
expect(source).toContain(':aria-selected="filters.mainStatus === tab.value"')
|
|
expect(source).toContain("event.key === 'ArrowRight'")
|
|
expect(source).toContain("event.key === 'ArrowLeft'")
|
|
expect(source).toContain("event.key === 'Home'")
|
|
expect(source).toContain("event.key === 'End'")
|
|
})
|
|
|
|
it('provides labeled prototype-aligned advanced filters backed by real query fields', () => {
|
|
for (const key of [
|
|
'receivingWarehouseId', 'destinationWarehouseId', 'inboundCode', 'internalOrderStatus', 'expectedArrivalDate',
|
|
'feeReviewStatus', 'containerNo', 'cabinetNo', 'channelName', 'sailingDate', 'loaded', 'fullContainer',
|
|
'measurementReviewStatus', 'fbaCode', 'createdRange',
|
|
]) expect(source).toContain(`key: '${key}'`)
|
|
for (const label of ['定位仓库', '交货仓', '费用审核状态', '是否已配载', '是否整柜', '测量数据审核状态', '商品 FBA 编码']) {
|
|
expect(source).toContain(`label: '${label}'`)
|
|
}
|
|
expect(source).toContain('listAllPlatformWarehouses')
|
|
expect(source).toContain("{ status: 'ACTIVE' }")
|
|
expect(source).toContain("warehouse.warehouseType === 'DOMESTIC'")
|
|
expect(source).toContain("loaded: optionalBoolean(filters.value.loaded)")
|
|
expect(source).toContain("fullContainer: optionalBoolean(filters.value.fullContainer)")
|
|
expect(source).toContain("{ value: 'UNRECORDED', label: '未录入' }")
|
|
expect(source).not.toContain("{ value: 'DRAFT', label: '草稿' }")
|
|
expect(source).not.toContain("{ value: 'CANCELLED', label: '已取消' }")
|
|
expect(source).not.toContain("key: 'orderNo'")
|
|
expect(source.match(/key: 'inboundCode', type: 'input'/g)).toHaveLength(1)
|
|
expect(source).not.toContain("key: 'keyword'")
|
|
const prototypeFieldOrder = [
|
|
'receivingWarehouseId', 'destinationWarehouseId', 'inboundCode', 'internalOrderStatus', 'expectedArrivalDate',
|
|
'feeReviewStatus', 'tenantId', 'containerNo', 'cabinetNo', 'channelName', 'sailingDate', 'loaded',
|
|
'fullContainer', 'measurementReviewStatus', 'fbaCode', 'createdRange',
|
|
]
|
|
const fieldPositions = prototypeFieldOrder.map((key) => source.indexOf(`key: '${key}'`))
|
|
expect(fieldPositions).toEqual([...fieldPositions].sort((left, right) => left - right))
|
|
expect(source).toContain('preference-key="unified-orders-query-v2"')
|
|
})
|
|
|
|
it('covers real list states and keeps operation column first and left-fixed', () => {
|
|
expect(source).toContain("{ key: 'actions', label: '操作', width: 180, fixed: 'left'")
|
|
expect(source).toContain("{ key: 'selection', type: 'selection', width: 52, fixed: 'left'")
|
|
expect(source).toContain('批量审核接口待接入')
|
|
expect(source).toContain('@selection-change="handleSelectionChange"')
|
|
expect(source).toContain('title="订单列表暂时无法加载"')
|
|
expect(source).toContain('empty-text="暂无符合条件的订单"')
|
|
expect(source).toContain(':loading="loading"')
|
|
expect(source).toContain('v-model:page="page"')
|
|
expect(source).toContain('v-model:page-size="pageSize"')
|
|
expect(source).toContain('slotName: \'orderStatus\'')
|
|
expect(source).toContain('slotName: \'measurementReviewStatus\'')
|
|
expect(source).toContain("NOT_SUBMITTED: '未提交'")
|
|
expect(source).toContain("{ key: 'customerRemark', prop: 'customerRemark', label: '备注'")
|
|
expect(source).toContain("{ key: 'latestInternalNote', prop: 'latestInternalNote', label: '客服内部备注'")
|
|
expect(source.match(/<LineClampText v-if="column\.key === 'remark'"/g)).toHaveLength(3)
|
|
})
|
|
|
|
it('keeps only confirmed business actions as explicit boundaries', () => {
|
|
expect(source).toContain('nextActionBoundary')
|
|
expect(source).toContain("can('platform:firstleg:inbound:view')")
|
|
expect(source).toContain('openMeasurement')
|
|
expect(source).not.toContain('待接入:智能分柜')
|
|
expect(source).not.toContain('updateMainStatus')
|
|
expect(source).not.toContain('人工进入分柜')
|
|
expect(source).not.toContain('performPlatformUnifiedOrderAction')
|
|
expect(source).not.toContain('/actions/')
|
|
})
|
|
|
|
it('approves pending review orders without exposing an order carrier assignment', () => {
|
|
expect(source).toContain("row.nextAction === 'APPROVE_ORDER'")
|
|
expect(source).toContain("can('platform:order:approve')")
|
|
expect(source).toContain('await approvePlatformUnifiedOrder(tenantId, orderId)')
|
|
expect(source).toContain('title="审核订单"')
|
|
expect(source).toContain('confirm-text="审核通过"')
|
|
expect(source).not.toContain('assignPlatformUnifiedOrderCarrier')
|
|
expect(source).not.toContain('listPlatformPartners')
|
|
expect(source).not.toContain('指派承运商')
|
|
expect(source).not.toContain('待平台指派')
|
|
})
|
|
|
|
it('provides unified detail, history and internal note states', () => {
|
|
expect(source).toContain('getPlatformUnifiedOrder')
|
|
expect(source).toContain('aria-label="状态历史"')
|
|
expect(source).toContain('aria-label="内部备注"')
|
|
expect(source).toContain('订单详情暂时无法加载')
|
|
expect(source).toContain('一、客户下单数据')
|
|
expect(source).toContain('二、外箱规数据')
|
|
expect(source).toContain('三、实际测量数据')
|
|
expect(source).toContain('measurementCollapsed = reactive({ customer: false, outer: false, actual: false })')
|
|
expect(source).toContain('function toggleMeasurementSection(section: keyof typeof measurementCollapsed)')
|
|
expect(source).toContain(':aria-expanded="!measurementCollapsed.customer"')
|
|
expect(source).toContain(':aria-expanded="!measurementCollapsed.outer"')
|
|
expect(source).toContain(':aria-expanded="!measurementCollapsed.actual"')
|
|
expect(source).toContain('class="measurement-section-summary"')
|
|
expect(source).toContain('<ChevronUp v-if="!measurementCollapsed.customer"')
|
|
expect(source).toContain('<ChevronDown v-else :size="18" />')
|
|
expect(source).toContain("{ key: 'girthCm', label: '箱规周长(cm)' }")
|
|
expect(source).toContain('runMoreAction($event, row as UnifiedOrderResource)')
|
|
expect(source).toContain('aria-label="更多订单操作"')
|
|
expect(source).toContain("can('platform:order:note')")
|
|
expect(source).toContain('await loadOrders()')
|
|
})
|
|
|
|
it('renders order detail as a routed full page instead of a drawer', () => {
|
|
expect(source).toContain('<template v-if="orderId">')
|
|
expect(source).toContain('class="order-detail-header"')
|
|
expect(source).toContain('aria-label="订单详情模块"')
|
|
expect(source).toContain("{ key: 'basic', label: '基本信息'")
|
|
expect(source).toContain("{ key: 'measurement', label: '测量数据'")
|
|
expect(source).not.toContain('<AppDrawer')
|
|
expect(source).not.toContain('detailOpen')
|
|
})
|
|
|
|
it('keeps the basic information compact and maps available order fields', () => {
|
|
expect(source).toContain('grid-template-columns: repeat(4, minmax(0, 1fr))')
|
|
for (const label of ['业务类型', '买单 / 退税', '提货方式', '配载状态', '目的仓类型', '总净重', '商检验', '提货联系人', '目的地地址']) {
|
|
expect(source).toContain(`<dt>${label}</dt>`)
|
|
}
|
|
expect(source).toContain("partyValue(detail.order.parties, 'SENDER', 'phone')")
|
|
expect(source).toContain("partyValue(detail.order.parties, 'RECEIVER', 'phone')")
|
|
expect(source).not.toContain("partyValue(detail.order.parties, 'CONSIGNEE'")
|
|
expect(source).toContain("cargoTotal(detail.order.cargoes, 'netWeightKg')")
|
|
expect(source).toContain('暂无费用数据')
|
|
})
|
|
|
|
it('does not expose the unconfirmed downstream workflow', () => {
|
|
expect(source).not.toContain('后半程作业')
|
|
expect(source).not.toContain('openWorkflow')
|
|
expect(source).not.toContain('workflowEligible')
|
|
expect(routeSource).not.toContain('unified-order-workflow')
|
|
})
|
|
})
|