Files
admin-web/src/modules/finance/pages/FinanceFormalSettlementExport.test.ts
T
2026-09-15 09:58:15 +08:00

161 lines
8.6 KiB
TypeScript

import ElementPlus from 'element-plus'
import { createPinia, setActivePinia } from 'pinia'
import { createMemoryHistory, createRouter } from 'vue-router'
import { enableAutoUnmount, flushPromises, mount } from '@vue/test-utils'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { useAccessPreviewStore } from '@/core/access/accessPreview'
import { useAuthStore } from '@/core/auth/auth'
import { createPlatformExportTask } from '@/modules/downloads'
import { listPlatformTenants } from '@/modules/iam'
import { showExportTaskCreatedDialog } from '@/shared/components/exportTaskCreatedDialog'
import { getFinanceSettlement, listFinancePayableSettlements, listFinanceReceivableSettlements } from '../api/finance'
import type { FinanceSettlementDetail } from '../types'
import FinanceFormalSettlementPage from './FinanceFormalSettlementPage.vue'
vi.mock('@/modules/downloads', () => ({ createPlatformExportTask: vi.fn() }))
vi.mock('@/modules/iam', () => ({ listPlatformTenants: vi.fn() }))
vi.mock('@/modules/suppliers', () => ({ categoryLabels: {}, listSuppliers: vi.fn() }))
vi.mock('@/shared/components/exportTaskCreatedDialog', () => ({ showExportTaskCreatedDialog: vi.fn() }))
vi.mock('../api/finance', async (importOriginal) => ({
...await importOriginal<typeof import('../api/finance')>(),
getFinanceSettlement: vi.fn(),
listFinancePayableSettlements: vi.fn(),
listFinanceReceivableSettlements: vi.fn(),
}))
class ResizeObserverStub implements ResizeObserver {
observe() {}
unobserve() {}
disconnect() {}
}
function createMemoryStorage(): 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),
}
}
function piniaWithPermissions(permissions: string[]) {
const pinia = createPinia()
setActivePinia(pinia)
const auth = useAuthStore()
auth.token = 'token'
auth.permissions = permissions
useAccessPreviewStore().initializeAfterLogin()
return pinia
}
function testRouter() {
return createRouter({
history: createMemoryHistory(),
routes: [
{ path: '/', name: 'settlements', component: { template: '<div />' } },
{ path: '/downloads', name: 'download-center', component: { template: '<div />' } },
],
})
}
const detail: FinanceSettlementDetail = {
id: '701', settlementNo: 'AR-701', customerId: '10001', reconciliationStatementId: '501', direction: 'RECEIVABLE',
amount: 300, paidAmount: 0, outstandingAmount: 300, currency: 'CNY', status: 'ISSUED', version: 0,
lines: [], transactions: [], revisions: [],
}
enableAutoUnmount(afterEach)
describe('formal settlement download-center exports', () => {
beforeEach(() => {
vi.stubGlobal('ResizeObserver', ResizeObserverStub)
vi.stubGlobal('localStorage', createMemoryStorage())
vi.stubGlobal('sessionStorage', createMemoryStorage())
vi.mocked(listPlatformTenants).mockReset().mockResolvedValue({ records: [], page: 1, size: 200, total: 0, pages: 1 })
vi.mocked(listFinanceReceivableSettlements).mockReset().mockResolvedValue([])
vi.mocked(listFinancePayableSettlements).mockReset().mockResolvedValue([])
vi.mocked(getFinanceSettlement).mockReset().mockResolvedValue(detail)
vi.mocked(createPlatformExportTask).mockReset().mockResolvedValue({ taskName: '应收结算单列表', taskNo: 'EXP-001' } as never)
vi.mocked(showExportTaskCreatedDialog).mockReset().mockResolvedValue(false)
})
it('creates an AR list task with current filters and no paging or direction parameters', async () => {
const router = testRouter()
await router.push('/'); await router.isReady()
const pinia = piniaWithPermissions(['platform:finance:settlement-ar:list', 'platform:finance:settlement-ar:export', 'platform:download:list'])
const wrapper = mount(FinanceFormalSettlementPage, { props: { kind: 'receivable' }, global: { plugins: [pinia, ElementPlus, router] } })
await flushPromises()
const vm = wrapper.vm as unknown as { filters: Record<string, unknown>; exportRows(): Promise<void> }
vm.filters = { customerId: '10001', status: 'ISSUED', settlementNo: ' AR-001 ', supplierName: '' }
await vm.exportRows()
expect(createPlatformExportTask).toHaveBeenCalledWith({
exportType: 'FINANCE_RECEIVABLE_SETTLEMENT_LIST', format: 'XLSX', taskName: '应收结算单列表',
parameters: { customerId: '10001', status: 'ISSUED', settlementNo: 'AR-001' },
})
expect(createPlatformExportTask).not.toHaveBeenCalledWith(expect.objectContaining({ parameters: expect.objectContaining({ direction: expect.anything(), page: expect.anything(), pageSize: expect.anything() }) }))
})
it('creates an AP list task with the supplier filter', async () => {
const router = testRouter()
await router.push('/'); await router.isReady()
const pinia = piniaWithPermissions(['platform:finance:settlement-ap:list', 'platform:finance:settlement-ap:export', 'platform:download:list'])
const wrapper = mount(FinanceFormalSettlementPage, { props: { kind: 'payable' }, global: { plugins: [pinia, ElementPlus, router] } })
await flushPromises()
const vm = wrapper.vm as unknown as { filters: Record<string, unknown>; exportRows(): Promise<void> }
vm.filters = { customerId: '10002', status: 'PARTIALLY_PAID', settlementNo: 'AP-002', supplierName: '承运供应商' }
await vm.exportRows()
expect(createPlatformExportTask).toHaveBeenCalledWith({
exportType: 'FINANCE_PAYABLE_SETTLEMENT_LIST', format: 'XLSX', taskName: '应付结算单列表',
parameters: { customerId: '10002', status: 'PARTIALLY_PAID', settlementNo: 'AP-002', supplierName: '承运供应商' },
})
})
it('exports a detail by settlement business key and opens the download center on confirmation', async () => {
vi.mocked(createPlatformExportTask).mockResolvedValueOnce({ taskName: '应收结算单详情', taskNo: 'EXP-DETAIL-1' } as never)
vi.mocked(showExportTaskCreatedDialog).mockResolvedValueOnce(true)
const router = testRouter()
await router.push('/'); await router.isReady()
const pinia = piniaWithPermissions(['platform:finance:settlement-ar:list', 'platform:finance:settlement-ar:export', 'platform:download:list'])
const wrapper = mount(FinanceFormalSettlementPage, { props: { kind: 'receivable', settlementId: '701' }, global: { plugins: [pinia, ElementPlus, router] } })
await flushPromises()
const vm = wrapper.vm as unknown as { exportDetail(): Promise<void> }
await vm.exportDetail()
expect(createPlatformExportTask).toHaveBeenCalledWith({
exportType: 'FINANCE_RECEIVABLE_SETTLEMENT_DETAIL', format: 'XLSX', taskName: '应收结算单详情', parameters: { settlementId: '701' },
})
expect(showExportTaskCreatedDialog).toHaveBeenCalledWith({ taskName: '应收结算单详情', taskNo: 'EXP-DETAIL-1', dense: true })
expect(router.currentRoute.value.name).toBe('download-center')
})
it('uses the payable detail type without a direction parameter', async () => {
vi.mocked(getFinanceSettlement).mockResolvedValueOnce({ ...detail, id: '801', settlementNo: 'AP-801', direction: 'PAYABLE' })
vi.mocked(createPlatformExportTask).mockResolvedValueOnce({ taskName: '应付结算单详情', taskNo: 'EXP-DETAIL-2' } as never)
const router = testRouter()
await router.push('/'); await router.isReady()
const pinia = piniaWithPermissions(['platform:finance:settlement-ap:list', 'platform:finance:settlement-ap:export', 'platform:download:list'])
const wrapper = mount(FinanceFormalSettlementPage, { props: { kind: 'payable', settlementId: '801' }, global: { plugins: [pinia, ElementPlus, router] } })
await flushPromises()
await (wrapper.vm as unknown as { exportDetail(): Promise<void> }).exportDetail()
expect(createPlatformExportTask).toHaveBeenCalledWith({
exportType: 'FINANCE_PAYABLE_SETTLEMENT_DETAIL', format: 'XLSX', taskName: '应付结算单详情', parameters: { settlementId: '801' },
})
})
it('hides export actions unless both export and download-list permissions are present', async () => {
const router = testRouter()
await router.push('/'); await router.isReady()
const pinia = piniaWithPermissions(['platform:finance:settlement-ar:list', 'platform:download:list'])
const wrapper = mount(FinanceFormalSettlementPage, { props: { kind: 'receivable' }, global: { plugins: [pinia, ElementPlus, router] } })
await flushPromises()
expect(wrapper.find('.settlement-list-actions').text()).not.toContain('导出')
})
})