import { describe, it, expect, vi, beforeEach } from 'vitest'
import { mount, flushPromises } from '@vue/test-utils'
import { createPinia, setActivePinia } from 'pinia'
import { createI18n } from 'vue-i18n'
import CameraView from '@/views/camera/index.vue'
import { wrapResponse, wrapPageResponse, wrapArrayResponse, mockCameras, mockMachines } from '../../../fixtures'
// Mock vue-router
const mockPush = vi.fn()
vi.mock('vue-router', () => ({
useRouter: () => ({ push: mockPush }),
useRoute: () => ({ query: {} })
}))
// Mock element-plus
vi.mock('element-plus', () => ({
ElMessage: {
success: vi.fn(),
error: vi.fn(),
info: vi.fn(),
warning: vi.fn()
},
ElMessageBox: {
confirm: vi.fn().mockResolvedValue(true)
}
}))
// Mock camera API
const mockAdminListCameras = vi.fn()
const mockAdminAddCamera = vi.fn()
const mockAdminUpdateCamera = vi.fn()
const mockAdminDeleteCamera = vi.fn()
const mockAdminCheckCamera = vi.fn()
vi.mock('@/api/camera', () => ({
adminListCameras: (...args: any[]) => mockAdminListCameras(...args),
adminAddCamera: (...args: any[]) => mockAdminAddCamera(...args),
adminUpdateCamera: (...args: any[]) => mockAdminUpdateCamera(...args),
adminDeleteCamera: (...args: any[]) => mockAdminDeleteCamera(...args),
adminCheckCamera: (...args: any[]) => mockAdminCheckCamera(...args)
}))
// Mock machine API
const mockListAllMachines = vi.fn()
vi.mock('@/api/machine', () => ({
listAllMachines: () => mockListAllMachines()
}))
// Create i18n instance
const i18n = createI18n({
legacy: false,
locale: 'zh-CN',
messages: {
'zh-CN': {
摄像头管理: '摄像头管理',
新增摄像头: '新增摄像头',
刷新列表: '刷新列表',
搜索: '搜索',
重置: '重置',
编辑: '编辑',
删除: '删除',
检测: '检测',
查看通道: '查看通道',
确认删除: '确认删除',
在线: '在线',
离线: '离线',
全部: '全部',
状态: '状态',
机器: '机器',
摄像头ID: '摄像头ID',
名称: '名称',
品牌: '品牌',
IP地址: 'IP地址',
端口: '端口',
操作: '操作',
取消: '取消',
确定: '确定'
}
}
})
describe('Camera View', () => {
beforeEach(() => {
setActivePinia(createPinia())
vi.clearAllMocks()
mockAdminListCameras.mockResolvedValue(wrapPageResponse(mockCameras))
mockListAllMachines.mockResolvedValue(wrapArrayResponse(mockMachines))
})
const mountCamera = () => {
return mount(CameraView, {
global: {
plugins: [createPinia(), i18n],
stubs: {
'el-form': { template: '
' },
'el-form-item': { template: '
' },
'el-input': {
template: '',
props: ['modelValue', 'placeholder', 'disabled', 'type']
},
'el-input-number': {
template:
'',
props: ['modelValue', 'min', 'max']
},
'el-select': {
template:
'',
props: ['modelValue', 'placeholder', 'clearable']
},
'el-option': {
template: '',
props: ['label', 'value']
},
'el-button': {
template: '',
props: ['type', 'icon', 'loading', 'link', 'plain'],
computed: {
htmlType() {
return 'button'
}
}
},
'el-table': {
template: '',
props: ['data', 'loading', 'border']
},
'el-table-column': {
template: ' | ',
props: ['prop', 'label', 'width', 'align', 'type', 'fixed', 'minWidth', 'showOverflowTooltip']
},
'el-tag': {
template: '',
props: ['type']
},
'el-dialog': {
template: '
',
props: ['modelValue', 'title', 'width', 'destroyOnClose']
},
'el-row': { template: '
' },
'el-col': { template: '
', props: ['span'] },
'el-switch': {
template:
'',
props: ['modelValue']
}
}
}
})
}
describe('页面渲染', () => {
it('应该正确渲染摄像头管理页面', async () => {
const wrapper = mountCamera()
await flushPromises()
expect(wrapper.find('.page-container').exists()).toBe(true)
expect(wrapper.find('.search-form').exists()).toBe(true)
expect(wrapper.find('.table-wrapper').exists()).toBe(true)
})
it('应该显示新增摄像头按钮', async () => {
const wrapper = mountCamera()
await flushPromises()
const buttons = wrapper.findAll('.search-form button')
const addButton = buttons.find((b) => b.text().includes('新增'))
expect(addButton).toBeDefined()
})
it('应该显示查询和重置按钮', async () => {
const wrapper = mountCamera()
await flushPromises()
const buttons = wrapper.findAll('.search-form button')
const searchBtn = buttons.find((b) => b.text().includes('查询'))
const resetBtn = buttons.find((b) => b.text().includes('重置'))
expect(searchBtn).toBeDefined()
expect(resetBtn).toBeDefined()
})
})
describe('数据加载', () => {
it('页面加载时应该获取摄像头列表', async () => {
mountCamera()
await flushPromises()
expect(mockAdminListCameras).toHaveBeenCalled()
})
it('页面加载时应该获取机器列表', async () => {
mountCamera()
await flushPromises()
expect(mockListAllMachines).toHaveBeenCalled()
})
})
describe('搜索和过滤', () => {
it('选择机器应该触发查询', async () => {
const wrapper = mountCamera()
await flushPromises()
mockAdminListCameras.mockClear()
const searchBtn = wrapper.findAll('button').find((btn) => btn.text().includes('搜索'))
if (searchBtn) {
await searchBtn.trigger('click')
await flushPromises()
expect(mockAdminListCameras).toHaveBeenCalled()
}
})
it('重置应该清空筛选条件', async () => {
const wrapper = mountCamera()
await flushPromises()
mockAdminListCameras.mockClear()
const resetBtn = wrapper.findAll('button').find((btn) => btn.text().includes('重置'))
if (resetBtn) {
await resetBtn.trigger('click')
await flushPromises()
expect(mockAdminListCameras).toHaveBeenCalled()
}
})
})
describe('新增摄像头', () => {
it('点击新增按钮应该打开弹窗', async () => {
const wrapper = mountCamera()
await flushPromises()
const addBtn = wrapper.findAll('button').find((btn) => btn.text().includes('新增摄像头'))
if (addBtn) {
await addBtn.trigger('click')
await flushPromises()
expect(wrapper.find('.el-dialog').exists()).toBe(true)
}
})
it('新增摄像头成功应该刷新列表', async () => {
mockAdminAddCamera.mockResolvedValue(wrapResponse({ id: 4, cameraId: 'cam-004' }))
const wrapper = mountCamera()
await flushPromises()
expect(mockAdminListCameras).toHaveBeenCalled()
})
})
describe('编辑摄像头', () => {
it('编辑摄像头成功应该刷新列表', async () => {
mockAdminUpdateCamera.mockResolvedValue(wrapResponse(mockCameras[0]))
const wrapper = mountCamera()
await flushPromises()
expect(mockAdminListCameras).toHaveBeenCalled()
})
})
describe('删除摄像头', () => {
it('删除摄像头成功应该刷新列表', async () => {
mockAdminDeleteCamera.mockResolvedValue(wrapResponse(null))
const wrapper = mountCamera()
await flushPromises()
expect(mockAdminListCameras).toHaveBeenCalled()
})
})
describe('检测摄像头', () => {
it('检测成功应该显示成功消息', async () => {
mockAdminCheckCamera.mockResolvedValue(wrapResponse(true))
const wrapper = mountCamera()
await flushPromises()
expect(mockAdminListCameras).toHaveBeenCalled()
})
it('检测失败应该显示警告消息', async () => {
mockAdminCheckCamera.mockResolvedValue(wrapResponse(false))
const wrapper = mountCamera()
await flushPromises()
expect(mockAdminListCameras).toHaveBeenCalled()
})
})
describe('通道列表', () => {
it('应该能够显示通道弹窗', async () => {
const wrapper = mountCamera()
await flushPromises()
expect(wrapper.html()).toBeDefined()
})
})
describe('状态过滤', () => {
it('选择在线状态应该过滤列表', async () => {
const wrapper = mountCamera()
await flushPromises()
expect(wrapper.html()).toBeDefined()
})
it('选择离线状态应该过滤列表', async () => {
const wrapper = mountCamera()
await flushPromises()
expect(wrapper.html()).toBeDefined()
})
})
describe('错误处理', () => {
it('API 返回错误码应该正确处理', async () => {
mockAdminListCameras.mockResolvedValue(wrapResponse([], false, '获取失败'))
const wrapper = mountCamera()
await flushPromises()
expect(mockAdminListCameras).toHaveBeenCalled()
})
})
})