Files
012-kaopeilian/frontend/src/utils/__tests__/errorHandler.test.ts
111 998211c483 feat: 初始化考培练系统项目
- 从服务器拉取完整代码
- 按框架规范整理项目结构
- 配置 Drone CI 测试环境部署
- 包含后端(FastAPI)、前端(Vue3)、管理端

技术栈: Vue3 + TypeScript + FastAPI + MySQL
2026-01-24 19:33:28 +08:00

252 lines
7.2 KiB
TypeScript

/**
* 错误处理工具测试
*/
import { describe, it, expect, beforeEach, vi } from 'vitest'
import { errorHandler, ErrorType, ErrorLevel, handleHttpError, handleBusinessError } from '../errorHandler'
// Mock Element Plus
vi.mock('element-plus', () => ({
ElMessage: vi.fn(),
ElNotification: vi.fn()
}))
describe('errorHandler', () => {
beforeEach(() => {
vi.clearAllMocks()
localStorage.clear()
errorHandler.clearErrorLogs()
})
describe('错误标准化', () => {
it('应该正确处理 Error 对象', () => {
const error = new Error('Test error')
errorHandler.handleError(error, 'Test context')
const logs = errorHandler.getErrorLogs()
expect(logs).toHaveLength(1)
expect(logs[0].message).toBe('Test error')
expect(logs[0].type).toBe(ErrorType.UNKNOWN)
expect(logs[0].details.context).toBe('Test context')
})
it('应该正确识别网络错误', () => {
const networkError = new Error('Network request failed')
errorHandler.handleError(networkError)
const logs = errorHandler.getErrorLogs()
expect(logs[0].type).toBe(ErrorType.NETWORK)
})
it('应该正确识别权限错误', () => {
const permissionError = new Error('Permission denied')
errorHandler.handleError(permissionError)
const logs = errorHandler.getErrorLogs()
expect(logs[0].type).toBe(ErrorType.PERMISSION)
})
it('应该正确识别验证错误', () => {
const validationError = new Error('Validation failed')
errorHandler.handleError(validationError)
const logs = errorHandler.getErrorLogs()
expect(logs[0].type).toBe(ErrorType.VALIDATION)
})
})
describe('错误级别判断', () => {
it('应该正确判断关键错误', () => {
const criticalError = new Error('Critical system failure')
errorHandler.handleError(criticalError)
const logs = errorHandler.getErrorLogs()
expect(logs[0].level).toBe(ErrorLevel.CRITICAL)
})
it('应该正确判断高级别错误', () => {
const highError = new Error('Network timeout')
errorHandler.handleError(highError)
const logs = errorHandler.getErrorLogs()
expect(logs[0].level).toBe(ErrorLevel.HIGH)
})
it('应该正确判断中级别错误', () => {
const mediumError = new Error('Validation error')
errorHandler.handleError(mediumError)
const logs = errorHandler.getErrorLogs()
expect(logs[0].level).toBe(ErrorLevel.MEDIUM)
})
})
describe('错误日志管理', () => {
it('应该正确记录错误日志', () => {
const error1 = new Error('Error 1')
const error2 = new Error('Error 2')
errorHandler.handleError(error1)
errorHandler.handleError(error2)
const logs = errorHandler.getErrorLogs()
expect(logs).toHaveLength(2)
expect(logs[0].message).toBe('Error 1')
expect(logs[1].message).toBe('Error 2')
})
it('应该正确清空错误日志', () => {
errorHandler.handleError(new Error('Test error'))
expect(errorHandler.getErrorLogs()).toHaveLength(1)
errorHandler.clearErrorLogs()
expect(errorHandler.getErrorLogs()).toHaveLength(0)
})
it('应该限制错误日志队列大小', () => {
// 添加超过最大队列大小的错误
for (let i = 0; i < 105; i++) {
errorHandler.handleError(new Error(`Error ${i}`))
}
const logs = errorHandler.getErrorLogs()
expect(logs.length).toBeLessThanOrEqual(100)
})
})
describe('自定义错误创建', () => {
it('应该正确创建自定义错误', () => {
const customError = errorHandler.createError(
ErrorType.VALIDATION,
ErrorLevel.MEDIUM,
'Custom validation error',
{ field: 'email' }
)
expect(customError.type).toBe(ErrorType.VALIDATION)
expect(customError.level).toBe(ErrorLevel.MEDIUM)
expect(customError.message).toBe('Custom validation error')
expect(customError.details.field).toBe('email')
expect(customError.timestamp).toBeTypeOf('number')
})
})
})
describe('handleHttpError', () => {
it('应该正确处理 400 错误', () => {
const error = {
response: {
status: 400,
statusText: 'Bad Request',
data: { message: 'Invalid parameters' }
},
config: {
url: '/api/test',
method: 'POST'
}
}
const errorInfo = handleHttpError(error)
expect(errorInfo.type).toBe(ErrorType.VALIDATION)
expect(errorInfo.message).toBe('Invalid parameters')
})
it('应该正确处理 401 错误', () => {
const error = {
response: {
status: 401,
statusText: 'Unauthorized',
data: {}
},
config: {
url: '/api/protected',
method: 'GET'
}
}
const errorInfo = handleHttpError(error)
expect(errorInfo.type).toBe(ErrorType.PERMISSION)
expect(errorInfo.level).toBe(ErrorLevel.HIGH)
expect(errorInfo.message).toBe('登录已过期,请重新登录')
})
it('应该正确处理 500 错误', () => {
const error = {
response: {
status: 500,
statusText: 'Internal Server Error',
data: {}
},
config: {
url: '/api/test',
method: 'GET'
}
}
const errorInfo = handleHttpError(error)
expect(errorInfo.type).toBe(ErrorType.API)
expect(errorInfo.level).toBe(ErrorLevel.CRITICAL)
expect(errorInfo.message).toBe('服务器内部错误')
})
it('应该正确处理网络错误', () => {
const error = {
request: {},
config: {
url: '/api/test',
method: 'GET'
}
}
const errorInfo = handleHttpError(error)
expect(errorInfo.type).toBe(ErrorType.NETWORK)
expect(errorInfo.level).toBe(ErrorLevel.HIGH)
expect(errorInfo.message).toBe('网络连接失败,请检查网络设置')
})
})
describe('handleBusinessError', () => {
it('应该正确处理认证业务错误', () => {
const errorInfo = handleBusinessError('AUTH_EXPIRED', '认证已过期')
expect(errorInfo.type).toBe(ErrorType.PERMISSION)
expect(errorInfo.level).toBe(ErrorLevel.HIGH)
expect(errorInfo.message).toBe('认证已过期')
})
it('应该正确处理验证业务错误', () => {
const errorInfo = handleBusinessError('VALID_EMAIL', '邮箱格式不正确')
expect(errorInfo.type).toBe(ErrorType.VALIDATION)
expect(errorInfo.level).toBe(ErrorLevel.LOW)
expect(errorInfo.message).toBe('邮箱格式不正确')
})
it('应该正确处理网络业务错误', () => {
const errorInfo = handleBusinessError('NETWORK_TIMEOUT', '请求超时')
expect(errorInfo.type).toBe(ErrorType.NETWORK)
expect(errorInfo.level).toBe(ErrorLevel.HIGH)
expect(errorInfo.message).toBe('请求超时')
})
it('应该正确处理通用业务错误', () => {
const errorInfo = handleBusinessError('UNKNOWN_ERROR', '未知错误')
expect(errorInfo.type).toBe(ErrorType.API)
expect(errorInfo.level).toBe(ErrorLevel.MEDIUM)
expect(errorInfo.message).toBe('未知错误')
})
})