- 从服务器拉取完整代码 - 按框架规范整理项目结构 - 配置 Drone CI 测试环境部署 - 包含后端(FastAPI)、前端(Vue3)、管理端 技术栈: Vue3 + TypeScript + FastAPI + MySQL
252 lines
7.2 KiB
TypeScript
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('未知错误')
|
|
})
|
|
})
|