[backend] fix: 修复异常处理和类型转换问题

This commit is contained in:
xsl
2026-01-26 11:53:40 +08:00
parent 7ccc2a6ac6
commit 83e05bf85f
28639 changed files with 2506458 additions and 93 deletions
+11
View File
@@ -38,6 +38,17 @@ export const AuthProvider = ({ children }) => {
}
};
const clearAuth = () => {
localStorage.removeItem('token');
localStorage.removeItem('user');
setToken(null);
setUser(null);
setAuthState({
isAuthenticated: false,
isLoading: false,
});
};
const login = async (username, password) => {
try {
const response = await fetch(`${import.meta.env.VITE_API_BASE_URL}/auth/login`, {
@@ -0,0 +1,47 @@
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { renderHook, act, waitFor } from '@testing-library/react';
import { AuthProvider, useAuth } from './AuthContext';
vi.mock('../services/auth', () => ({
authAPI: {
login: vi.fn(),
getCurrentUser: vi.fn(),
logout: vi.fn(),
},
}));
describe('useAuth Hook - TC-006', () => {
beforeEach(() => {
localStorage.clear();
vi.clearAllMocks();
});
it('TC-006-01: 初始状态应该是未认证', () => {
const { result } = renderHook(() => useAuth(), {
wrapper: AuthProvider,
});
expect(result.current.isAuthenticated).toBe(false);
expect(result.current.user).toBe(null);
expect(result.current.token).toBe(null);
expect(result.current.loading).toBe(false);
});
it('TC-006-02: hasRole应该正确检查角色', () => {
const { result } = renderHook(() => useAuth(), {
wrapper: AuthProvider,
});
expect(result.current.hasRole(['admin'])).toBe(false);
expect(result.current.hasRole(['market'])).toBe(false);
expect(result.current.hasRole(['admin', 'market'])).toBe(false);
});
it('TC-006-03: canEdit应该默认返回false', () => {
const { result } = renderHook(() => useAuth(), {
wrapper: AuthProvider,
});
expect(result.current.canEdit(1)).toBe(false);
});
});
@@ -1,5 +1,4 @@
import React, { useEffect, useState } from 'react';
import { authAPI } from '../../services/auth';
import { projectAPI } from '../../services/project';
const Dashboard = () => {
+2 -1
View File
@@ -1,10 +1,11 @@
import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { useAuth } from '../../contexts/AuthContext';
import { projectAPI } from '../../services/project';
const ProjectList = ({ mode = 'list' }) => {
const { user } = useAuth();
const navigate = useNavigate();
const { user } = useAuth();
const [list, setList] = useState([]);
const [total, setTotal] = useState(0);
const [loading, setLoading] = useState(false);
@@ -1,5 +1,4 @@
import React, { useState, useEffect } from 'react';
import { authAPI } from '../../services/auth';
import { projectAPI } from '../../services/project';
const Statistics = () => {
+46
View File
@@ -0,0 +1,46 @@
import { describe, it, expect, vi } from 'vitest';
import { projectAPI } from './project';
vi.mock('../../services/api');
describe('projectAPI - TC-013', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('TC-013-06: projectAPI应该有getList方法', () => {
expect(typeof projectAPI.getList).toBe('function');
});
it('TC-013-07: projectAPI应该有getDetail方法', () => {
expect(typeof projectAPI.getDetail).toBe('function');
});
it('TC-013-08: projectAPI应该有create方法', () => {
expect(typeof projectAPI.create).toBe('function');
});
it('TC-013-09: projectAPI应该有update方法', () => {
expect(typeof projectAPI.update).toBe('function');
});
it('TC-013-10: projectAPI应该有delete方法', () => {
expect(typeof projectAPI.delete).toBe('function');
});
it('TC-013-11: projectAPI应该有getStatistics方法', () => {
expect(typeof projectAPI.getStatistics).toBe('function');
});
it('TC-013-12: projectAPI应该有getGroupStatistics方法', () => {
expect(typeof projectAPI.getGroupStatistics).toBe('function');
});
it('TC-013-13: projectAPI应该有getTimelineStatistics方法', () => {
expect(typeof projectAPI.getTimelineStatistics).toBe('function');
});
it('TC-013-14: projectAPI应该有export方法', () => {
expect(typeof projectAPI.export).toBe('function');
});
});
+34
View File
@@ -0,0 +1,34 @@
import { describe, it, expect, vi } from 'vitest';
import { userAPI } from './user';
vi.mock('../../services/api');
describe('userAPI - TC-014', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('TC-014-01: userAPI应该有getList方法', () => {
expect(typeof userAPI.getList).toBe('function');
});
it('TC-014-02: userAPI应该有getDetail方法', () => {
expect(typeof userAPI.getDetail).toBe('function');
});
it('TC-014-03: userAPI应该有create方法', () => {
expect(typeof userAPI.create).toBe('function');
});
it('TC-014-04: userAPI应该有update方法', () => {
expect(typeof userAPI.update).toBe('function');
});
it('TC-014-05: userAPI应该有delete方法', () => {
expect(typeof userAPI.delete).toBe('function');
});
it('TC-014-06: userAPI应该有resetPassword方法', () => {
expect(typeof userAPI.resetPassword).toBe('function');
});
});
+56
View File
@@ -0,0 +1,56 @@
import { describe, it, expect } from 'vitest';
import { formatMoney, formatPercentage, formatDate } from './format';
describe('formatMoney', () => {
it('TC-001-01: 应该正确格式化整数', () => {
expect(formatMoney(1234)).toBe('1,234.00');
});
it('TC-001-02: 应该正确格式化小数', () => {
expect(formatMoney(1234.56)).toBe('1,234.56');
});
it('TC-001-03: 应该处理千分位', () => {
expect(formatMoney(10000)).toBe('10,000.00');
});
it('TC-001-04: 应该处理零', () => {
expect(formatMoney(0)).toBe('0.00');
});
it('TC-001-05: 应该处理负数', () => {
expect(formatMoney(-1234.56)).toBe('-1,234.56');
});
it('TC-001-06: 应该四舍五入', () => {
expect(formatMoney(100.123)).toBe('100.12');
});
});
describe('formatPercentage', () => {
it('TC-002-01: 应该正确格式化50%', () => {
expect(formatPercentage(0.5)).toBe('50.00%');
});
it('TC-002-02: 应该正确格式化100%', () => {
expect(formatPercentage(1)).toBe('100.00%');
});
it('TC-002-03: 应该处理零', () => {
expect(formatPercentage(0)).toBe('0.00%');
});
it('TC-002-04: 应该保留两位小数', () => {
expect(formatPercentage(0.6666)).toBe('66.66%');
});
});
describe('formatDate', () => {
it('TC-003-01: 应该格式化日期字符串', () => {
expect(formatDate('2026-01-25')).toBe('2026/01/25');
});
it('TC-003-02: 应该格式化Date对象', () => {
expect(formatDate(new Date('2026-01-25'))).toBe('2026/01/25');
});
});
+60
View File
@@ -0,0 +1,60 @@
import { describe, it, expect } from 'vitest';
import { validateEmail, validatePhone, validateProjectNo } from './validate';
describe('validateEmail', () => {
it('TC-004-01: 有效邮箱', () => {
expect(validateEmail('test@example.com')).toBe(true);
});
it('TC-004-02: 有效邮箱(带点)', () => {
expect(validateEmail('test.name@example.com')).toBe(true);
});
it('TC-004-03: 无效邮箱(无@', () => {
expect(validateEmail('testexample.com')).toBe(false);
});
it('TC-004-04: 无效邮箱(无域名)', () => {
expect(validateEmail('test@')).toBe(false);
});
it('TC-004-05: 空字符串', () => {
expect(validateEmail('')).toBe(true);
});
});
describe('validatePhone', () => {
it('TC-005-01: 有效手机号', () => {
expect(validatePhone('13800000001')).toBe(true);
});
it('TC-005-02: 有效手机号(其他运营商)', () => {
expect(validatePhone('15900139000')).toBe(true);
});
it('TC-005-03: 无效手机号(太短)', () => {
expect(validatePhone('1380000')).toBe(false);
});
it('TC-005-04: 无效手机号(太长)', () => {
expect(validatePhone('138000000001')).toBe(false);
});
it('TC-005-05: 空字符串', () => {
expect(validatePhone('')).toBe(true);
});
});
describe('validateProjectNo', () => {
it('TC-006-01: 有效合同编号', () => {
expect(validateProjectNo('PRJ001')).toBe(true);
});
it('TC-006-02: 无效合同编号(包含小写)', () => {
expect(validateProjectNo('prj001')).toBe(false);
});
it('TC-006-03: 空字符串', () => {
expect(validateProjectNo('')).toBe(true);
});
});