test: 添加单元测试和端到端测试 refactor: 重构登录页面和上传模块 ci: 更新测试覆盖率阈值至42% build: 添加测试相关依赖 docs: 更新测试文档 style: 修复代码格式问题
136 lines
3.6 KiB
TypeScript
136 lines
3.6 KiB
TypeScript
import { describe, it, expect, jest, beforeAll, beforeEach } from '@jest/globals';
|
|
import { NextRequest } from 'next/server';
|
|
import '@testing-library/jest-dom';
|
|
|
|
const mockAuth = jest.fn();
|
|
const mockHasPermission = jest.fn();
|
|
const mockDbSelect = jest.fn();
|
|
const mockDbInsert = jest.fn();
|
|
|
|
jest.mock('@/lib/auth', () => ({
|
|
auth: mockAuth,
|
|
}));
|
|
|
|
jest.mock('@/lib/auth/permissions', () => ({
|
|
hasPermission: mockHasPermission,
|
|
}));
|
|
|
|
jest.mock('@/db', () => ({
|
|
db: {
|
|
select: () => ({
|
|
from: () => ({
|
|
where: () => ({
|
|
limit: mockDbSelect,
|
|
}),
|
|
orderBy: mockDbSelect,
|
|
}),
|
|
}),
|
|
insert: () => ({
|
|
values: () => ({
|
|
returning: mockDbInsert,
|
|
}),
|
|
}),
|
|
},
|
|
}));
|
|
|
|
jest.mock('drizzle-orm', () => ({
|
|
eq: jest.fn(),
|
|
}));
|
|
|
|
jest.mock('nanoid', () => ({
|
|
nanoid: () => 'test-id-123',
|
|
}));
|
|
|
|
jest.mock('bcryptjs', () => ({
|
|
hash: jest.fn().mockResolvedValue('hashed-password'),
|
|
}));
|
|
|
|
jest.mock('@/db/schema', () => ({
|
|
users: {},
|
|
}));
|
|
|
|
import { GET, POST } from './route';
|
|
|
|
describe('/api/admin/users', () => {
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
describe('GET', () => {
|
|
it('should return 401 when not authenticated', async () => {
|
|
mockAuth.mockResolvedValueOnce(null);
|
|
|
|
const request = new NextRequest('http://localhost/api/admin/users');
|
|
const response = await GET(request);
|
|
const data = await response.json();
|
|
|
|
expect(response.status).toBe(401);
|
|
expect(data.error).toBe('未授权');
|
|
});
|
|
|
|
it('should return 403 when user lacks permission', async () => {
|
|
mockAuth.mockResolvedValueOnce({
|
|
user: { id: '1', role: 'viewer' },
|
|
});
|
|
mockHasPermission.mockReturnValueOnce(false);
|
|
|
|
const request = new NextRequest('http://localhost/api/admin/users');
|
|
const response = await GET(request);
|
|
const data = await response.json();
|
|
|
|
expect(response.status).toBe(403);
|
|
expect(data.error).toBe('无权限');
|
|
});
|
|
|
|
it('should return users list when authorized', async () => {
|
|
mockAuth.mockResolvedValueOnce({
|
|
user: { id: '1', role: 'admin' },
|
|
});
|
|
mockHasPermission.mockReturnValueOnce(true);
|
|
mockDbSelect.mockResolvedValueOnce([
|
|
{ id: '1', email: 'admin@example.com', name: 'Admin', role: 'admin' },
|
|
]);
|
|
|
|
const request = new NextRequest('http://localhost/api/admin/users');
|
|
const response = await GET(request);
|
|
const data = await response.json();
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(data.users).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('POST', () => {
|
|
it('should return 401 when not authenticated', async () => {
|
|
mockAuth.mockResolvedValueOnce(null);
|
|
|
|
const request = new NextRequest('http://localhost/api/admin/users', {
|
|
method: 'POST',
|
|
body: JSON.stringify({ email: 'test@example.com', name: 'Test', password: 'password', role: 'viewer' }),
|
|
});
|
|
const response = await POST(request);
|
|
const data = await response.json();
|
|
|
|
expect(response.status).toBe(401);
|
|
expect(data.error).toBe('未授权');
|
|
});
|
|
|
|
it('should return 400 when missing required fields', async () => {
|
|
mockAuth.mockResolvedValueOnce({
|
|
user: { id: '1', role: 'admin' },
|
|
});
|
|
mockHasPermission.mockReturnValueOnce(true);
|
|
|
|
const request = new NextRequest('http://localhost/api/admin/users', {
|
|
method: 'POST',
|
|
body: JSON.stringify({ email: 'test@example.com' }),
|
|
});
|
|
const response = await POST(request);
|
|
const data = await response.json();
|
|
|
|
expect(response.status).toBe(400);
|
|
expect(data.error).toBe('缺少必填字段');
|
|
});
|
|
});
|
|
});
|