/** * 资产列表组件测试 * * 测试内容: * - 组件渲染 * - 数据加载 * - 搜索功能 * - 分页功能 * - 事件触发 */ import { describe, it, expect, vi, beforeEach } from 'vitest' import { mount, VueWrapper } from '@vue/test-utils' import { createPinia, setActivePinia } from 'pinia' import ElementPlus from 'element-plus' import AssetList from '@/views/assets/AssetList.vue' import * as assetApi from '@/api/assets' // Mock API模块 vi.mock('@/api/assets', () => ({ getAssetList: vi.fn(), deleteAsset: vi.fn(), getAssetStatistics: vi.fn() })) describe('AssetList组件', () => { let wrapper: VueWrapper let pinia: any beforeEach(() => { // 创建新的Pinia实例 pinia = createPinia() setActivePinia(pinia) // Mock API响应 vi.mocked(assetApi.getAssetList).mockResolvedValue({ items: [ { id: 1, assetCode: 'ASSET-20250124-0001', assetName: '联想台式机', deviceType: { id: 1, typeName: '计算机' }, organization: { id: 1, orgName: '天河网点' }, status: 'in_use', purchaseDate: '2024-01-15', purchasePrice: 4500.00 } ], total: 1, page: 1, pageSize: 20 }) vi.mocked(assetApi.getAssetStatistics).mockResolvedValue({ totalCount: 100, totalValue: 500000.00, statusDistribution: { in_stock: 30, in_use: 50, maintenance: 10, scrapped: 10 } }) }) afterEach(() => { if (wrapper) { wrapper.unmount() } vi.clearAllMocks() }) it('应该正确渲染组件', () => { wrapper = mount(AssetList, { global: { plugins: [pinia, ElementPlus], stubs: { 'el-table': true, 'el-pagination': true, 'el-input': true, 'el-button': true } } }) expect(wrapper.find('.asset-list').exists()).toBe(true) }) it('应该在挂载时加载资产列表', async () => { wrapper = mount(AssetList, { global: { plugins: [pinia, ElementPlus], stubs: { 'el-table': true, 'el-pagination': true } } }) await wrapper.vm.$nextTick() expect(assetApi.getAssetList).toHaveBeenCalledWith({ page: 1, page_size: 20 }) }) it('应该显示资产统计数据', async () => { wrapper = mount(AssetList, { global: { plugins: [pinia, ElementPlus], stubs: { 'el-table': true, 'el-statistic': true } } }) await wrapper.vm.$nextTick() await wrapper.vm.$nextTick() // 等待统计数据加载 expect(assetApi.getAssetStatistics).toHaveBeenCalled() }) it('应该支持搜索功能', async () => { wrapper = mount(AssetList, { global: { plugins: [pinia, ElementPlus], stubs: { 'el-table': true, 'el-input': true, 'el-button': true } } }) const searchKeyword = '联想' wrapper.vm.searchKeyword = searchKeyword await wrapper.vm.handleSearch() expect(assetApi.getAssetList).toHaveBeenCalledWith({ page: 1, page_size: 20, keyword: searchKeyword }) }) it('应该支持分页功能', async () => { wrapper = mount(AssetList, { global: { plugins: [pinia, ElementPlus], stubs: { 'el-table': true, 'el-pagination': true } } }) wrapper.vm.pagination.page = 2 await wrapper.vm.fetchAssets() expect(assetApi.getAssetList).toHaveBeenCalledWith({ page: 2, page_size: 20 }) }) it('应该触发刷新事件', async () => { wrapper = mount(AssetList, { global: { plugins: [pinia, ElementPlus], stubs: { 'el-table': true, 'el-button': true } } }) const refreshSpy = vi.spyOn(wrapper.vm, 'fetchAssets') await wrapper.vm.handleRefresh() expect(refreshSpy).toHaveBeenCalled() }) it('应该打开创建对话框', async () => { wrapper = mount(AssetList, { global: { plugins: [pinia, ElementPlus], stubs: { 'el-table': true, 'el-button': true, 'asset-create-dialog': true } } }) await wrapper.vm.openCreateDialog() expect(wrapper.vm.createDialogVisible).toBe(true) }) it('应该打开编辑对话框', async () => { const mockAsset = { id: 1, assetCode: 'ASSET-20250124-0001', assetName: '联想台式机' } wrapper = mount(AssetList, { global: { plugins: [pinia, ElementPlus], stubs: { 'el-table': true, 'asset-edit-dialog': true } } }) await wrapper.vm.openEditDialog(mockAsset) expect(wrapper.vm.editDialogVisible).toBe(true) expect(wrapper.vm.currentAsset).toEqual(mockAsset) }) it('应该删除资产', async () => { vi.mocked(assetApi.deleteAsset).mockResolvedValue({}) wrapper = mount(AssetList, { global: { plugins: [pinia, ElementPlus], stubs: { 'el-table': true, 'el-button': true } } }) // Mock确认对话框 vi.spyOn(wrapper.vm as any, '$confirm').mockResolvedValue('confirm') await wrapper.vm.handleDelete(1) expect(assetApi.deleteAsset).toHaveBeenCalledWith(1) }) it('应该在搜索时重置页码', async () => { wrapper = mount(AssetList, { global: { plugins: [pinia, ElementPlus], stubs: { 'el-table': true, 'el-input': true } } }) wrapper.vm.pagination.page = 5 wrapper.vm.searchKeyword = '测试' await wrapper.vm.handleSearch() expect(wrapper.vm.pagination.page).toBe(1) }) it('应该显示加载状态', async () => { wrapper = mount(AssetList, { global: { plugins: [pinia, ElementPlus], stubs: { 'el-table': true } } }) wrapper.vm.loading = true await wrapper.vm.$nextTick() expect(wrapper.find('.loading').exists()).toBe(true) }) it('应该处理API错误', async () => { vi.mocked(assetApi.getAssetList).mockRejectedValue(new Error('网络错误')) wrapper = mount(AssetList, { global: { plugins: [pinia, ElementPlus], stubs: { 'el-table': true } } }) const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {}) await wrapper.vm.fetchAssets() expect(consoleSpy).toHaveBeenCalled() consoleSpy.mockRestore() }) it('应该支持状态筛选', async () => { wrapper = mount(AssetList, { global: { plugins: [pinia, ElementPlus], stubs: { 'el-table': true, 'el-select': true } } }) wrapper.vm.filters.status = 'in_use' await wrapper.vm.handleFilter() expect(assetApi.getAssetList).toHaveBeenCalledWith({ page: 1, page_size: 20, status: 'in_use' }) }) it('应该支持设备类型筛选', async () => { wrapper = mount(AssetList, { global: { plugins: [pinia, ElementPlus], stubs: { 'el-table': true, 'el-select': true } } }) wrapper.vm.filters.deviceTypeId = 1 await wrapper.vm.handleFilter() expect(assetApi.getAssetList).toHaveBeenCalledWith({ page: 1, page_size: 20, device_type_id: 1 }) }) })