92 lines
4.6 KiB
TypeScript
92 lines
4.6 KiB
TypeScript
import ElementPlus from 'element-plus'
|
|
import { flushPromises, mount } from '@vue/test-utils'
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import { readFileSync } from 'node:fs'
|
|
import { resolve } from 'node:path'
|
|
import OceanBookingsView from './OceanBookingsView.vue'
|
|
import { listOceanBookings } from '../api/platformOceanBookings'
|
|
|
|
const routerPush = vi.hoisted(() => vi.fn())
|
|
vi.mock('vue-router', () => ({ useRouter: () => ({ push: routerPush }) }))
|
|
vi.mock('@/core/access/accessPreview', () => ({ useAccessPreviewStore: () => ({ can: () => true }) }))
|
|
vi.mock('@/modules/iam', () => ({ listPlatformTenants: vi.fn().mockResolvedValue({ records: [] }) }))
|
|
vi.mock('../api/platformOceanBookings', () => ({ listOceanBookings: vi.fn() }))
|
|
|
|
const source = readFileSync(resolve(process.cwd(), 'src/modules/ocean-bookings/pages/OceanBookingsView.vue'), 'utf8')
|
|
|
|
describe('OceanBookingsView', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
vi.mocked(listOceanBookings).mockResolvedValue({ records: [], page: 1, size: 20, total: 0, pages: 0 })
|
|
})
|
|
it('keeps the operation column first and left fixed', () => {
|
|
expect(source.indexOf("key: 'actions'")).toBeLessThan(source.indexOf("prop: 'bookingNo'"))
|
|
expect(source).toContain("fixed: 'left'")
|
|
})
|
|
|
|
it('renders loading, empty and error states and keeps draft creation available', () => {
|
|
expect(source).toContain('LoadErrorState')
|
|
expect(source).toContain(':loading="loading"')
|
|
expect(source).toContain('新增订舱')
|
|
expect(source).toContain("router.push('/ocean-bookings/new')")
|
|
})
|
|
|
|
it('edits DRAFT rows and views RELEASED rows', () => {
|
|
expect(source).toContain('<Pencil v-if="row.status === \'DRAFT\'"')
|
|
expect(source).toContain("row.status === 'DRAFT' ? '编辑' : '查看'")
|
|
expect(source).not.toContain('MoreHorizontal')
|
|
expect(source).toContain('打印单据')
|
|
expect(source).toContain('OceanBookingPrintDialog')
|
|
expect(source).toContain("access.can('platform:firstleg:ocean-booking:list')")
|
|
})
|
|
|
|
it('uses only the frozen DRAFT and RELEASED status options', () => {
|
|
expect(source).toContain('options: oceanBookingStatusOptions')
|
|
expect(source).toContain(':status="oceanBookingStatusLabel(row.status)"')
|
|
expect(source).not.toContain('CONFIRMED')
|
|
expect(source).not.toContain('CHANGE_PENDING')
|
|
expect(source).not.toContain('CANCELLED')
|
|
})
|
|
|
|
it('keeps the prototype business field order after actions', () => {
|
|
const fields = ['bookingNo', 'customerName', 'billOfLadingNo', 'shipperName', 'consigneeName', 'containerCount', 'carrierName', 'bookingAgent', 'vesselName', 'pol', 'pod', 'etd', 'eta', 'status', 'updatedAt']
|
|
let previous = source.indexOf("key: 'actions'")
|
|
for (const field of fields) {
|
|
const current = source.indexOf(`prop: '${field}'`, previous + 1)
|
|
expect(current, field).toBeGreaterThan(previous)
|
|
previous = current
|
|
}
|
|
})
|
|
|
|
it('displays the server containerCount as the booking requirement total without detail N+1', async () => {
|
|
vi.mocked(listOceanBookings).mockResolvedValueOnce({ records: [{
|
|
id: '183', bookingNo: 'OB-260825-0183', status: 'RELEASED', containerCount: 1,
|
|
customerName: '回归客户', vesselName: null, voyageNo: null, etd: null, eta: null, updatedAt: null,
|
|
}], page: 1, size: 20, total: 1, pages: 1 } as never)
|
|
const wrapper = mount(OceanBookingsView, { global: { plugins: [ElementPlus] } })
|
|
|
|
await (wrapper.vm as unknown as { load: () => Promise<void> }).load()
|
|
await flushPromises()
|
|
|
|
const tableText = wrapper.find('.el-table__body-wrapper').text()
|
|
expect(tableText).toContain('OB-260825-0183')
|
|
expect(tableText).toContain('1')
|
|
expect(source).toContain("label: '订舱柜量'")
|
|
expect(source).not.toContain('getOceanBooking')
|
|
wrapper.unmount()
|
|
})
|
|
|
|
it('loads active customers by name and stays usable on narrow screens', () => {
|
|
expect(source).toContain("listPlatformTenants({ page: 1, size: 200, status: 'ACTIVE' })")
|
|
expect(source).toContain('label: customer.tenantName')
|
|
expect(source).not.toContain('customer.tenantCode')
|
|
expect(source).toContain('@media(max-width:420px)')
|
|
})
|
|
|
|
it('keeps desktop filter widths proportional instead of stretching short status fields', () => {
|
|
expect(source).toContain("key: 'customerId', type: 'select', label: '客户', placeholder: '全部客户', width: 220")
|
|
expect(source).toContain("key: 'keyword', type: 'input', label: '关键词', placeholder: '订舱号/提单号/船名/航次', width: 260")
|
|
expect(source).toContain("key: 'status', type: 'select', label: '状态', width: 160")
|
|
})
|
|
})
|