test: add API route tests

This commit is contained in:
张翔
2026-03-10 12:41:17 +08:00
parent 7d67c8eef3
commit 65ea3f0e7e
3 changed files with 477 additions and 0 deletions
@@ -0,0 +1,39 @@
import { GET, POST } from './route';
jest.mock('@/lib/auth', () => ({
handlers: {
GET: jest.fn(() => new Response('GET response')),
POST: jest.fn(() => new Response('POST response')),
},
}));
describe('/api/auth/[...nextauth]', () => {
describe('GET handler', () => {
it('should export GET handler', () => {
expect(typeof GET).toBe('function');
});
it('should call auth GET handler', async () => {
const response = await GET(new Request('http://localhost/api/auth/signin'));
expect(response).toBeDefined();
expect(response.status).toBe(200);
});
});
describe('POST handler', () => {
it('should export POST handler', () => {
expect(typeof POST).toBe('function');
});
it('should call auth POST handler', async () => {
const response = await POST(
new Request('http://localhost/api/auth/signin', {
method: 'POST',
body: JSON.stringify({ email: 'test@example.com', password: 'password' }),
})
);
expect(response).toBeDefined();
expect(response.status).toBe(200);
});
});
});
+250
View File
@@ -0,0 +1,250 @@
import { POST } from './route';
import { NextRequest } from 'next/server';
jest.mock('resend', () => {
const mockSend = jest.fn();
return {
__esModule: true,
default: jest.fn().mockImplementation(() => ({
emails: {
send: mockSend,
},
})),
Resend: jest.fn().mockImplementation(() => ({
emails: {
send: mockSend,
},
})),
};
});
describe('/api/contact', () => {
let mockRequest: NextRequest;
let mockSend: any;
beforeEach(() => {
const { default: Resend } = require('resend');
const resendInstance = new Resend();
mockSend = resendInstance.emails.send;
mockSend.mockClear();
});
const createMockRequest = (body: any): NextRequest => {
return {
json: async () => body,
} as unknown as NextRequest;
};
it('should handle POST request with valid data', async () => {
mockSend.mockResolvedValue({
data: { id: 'test-id' },
error: null,
});
mockRequest = createMockRequest({
name: 'Test User',
email: 'test@example.com',
subject: 'Test Subject',
message: 'Test Message',
});
const response = await POST(mockRequest);
const data = await response.json();
expect(response.status).toBe(200);
expect(data.success).toBe(true);
expect(data.message).toBe('消息已发送');
expect(mockSend).toHaveBeenCalled();
});
it('should validate required fields', async () => {
mockRequest = createMockRequest({
name: 'Test User',
});
const response = await POST(mockRequest);
const data = await response.json();
expect(response.status).toBe(400);
expect(data.success).toBe(false);
expect(data.error).toBe('请填写必填字段');
});
it('should validate email format', async () => {
mockRequest = createMockRequest({
name: 'Test User',
email: 'invalid-email',
subject: 'Test Subject',
message: 'Test Message',
});
const response = await POST(mockRequest);
const data = await response.json();
expect(response.status).toBe(400);
expect(data.success).toBe(false);
expect(data.error).toBe('请输入有效的邮箱地址');
});
it('should reject honeypot field', async () => {
mockRequest = createMockRequest({
name: 'Test User',
email: 'test@example.com',
subject: 'Test Subject',
message: 'Test Message',
website: 'spam-bot',
});
const response = await POST(mockRequest);
const data = await response.json();
expect(response.status).toBe(200);
expect(data.success).toBe(true);
expect(mockSend).not.toHaveBeenCalled();
});
it('should reject submission too fast', async () => {
mockRequest = createMockRequest({
name: 'Test User',
email: 'test@example.com',
subject: 'Test Subject',
message: 'Test Message',
submitTime: Date.now().toString(),
});
const response = await POST(mockRequest);
const data = await response.json();
expect(response.status).toBe(400);
expect(data.success).toBe(false);
expect(data.error).toBe('提交过快,请稍后再试');
});
it('should validate math captcha', async () => {
mockRequest = createMockRequest({
name: 'Test User',
email: 'test@example.com',
subject: 'Test Subject',
message: 'Test Message',
mathHash: 'invalid-hash',
mathTimestamp: Date.now().toString(),
mathAnswer: '5',
});
const response = await POST(mockRequest);
const data = await response.json();
expect(response.status).toBe(400);
expect(data.success).toBe(false);
expect(data.error).toBe('验证码错误,请重新计算');
});
it('should handle Resend API error', async () => {
mockSend.mockResolvedValue({
data: null,
error: { message: 'API Error' },
});
mockRequest = createMockRequest({
name: 'Test User',
email: 'test@example.com',
subject: 'Test Subject',
message: 'Test Message',
});
const response = await POST(mockRequest);
const data = await response.json();
expect(response.status).toBe(500);
expect(data.success).toBe(false);
expect(data.error).toBe('邮件发送失败,请稍后重试');
});
it('should handle JSON parsing error', async () => {
mockRequest = {
json: async () => {
throw new Error('Invalid JSON');
},
} as unknown as NextRequest;
const response = await POST(mockRequest);
const data = await response.json();
expect(response.status).toBe(500);
expect(data.success).toBe(false);
expect(data.error).toBe('提交失败,请重试');
});
it('should accept valid submission with phone', async () => {
mockSend.mockResolvedValue({
data: { id: 'test-id' },
error: null,
});
mockRequest = createMockRequest({
name: 'Test User',
email: 'test@example.com',
phone: '13800138000',
subject: 'Test Subject',
message: 'Test Message',
});
const response = await POST(mockRequest);
const data = await response.json();
expect(response.status).toBe(200);
expect(data.success).toBe(true);
expect(mockSend).toHaveBeenCalled();
});
it('should accept valid submission with math captcha', async () => {
mockSend.mockResolvedValue({
data: { id: 'test-id' },
error: null,
});
const timestamp = Date.now();
const answer = '5';
const hash = btoa(`${answer}-${timestamp}`);
mockRequest = createMockRequest({
name: 'Test User',
email: 'test@example.com',
subject: 'Test Subject',
message: 'Test Message',
mathHash: hash,
mathTimestamp: timestamp.toString(),
mathAnswer: answer,
});
const response = await POST(mockRequest);
const data = await response.json();
expect(response.status).toBe(200);
expect(data.success).toBe(true);
expect(mockSend).toHaveBeenCalled();
});
it('should handle submission after minimum time', async () => {
mockSend.mockResolvedValue({
data: { id: 'test-id' },
error: null,
});
const pastTime = Date.now() - 3000;
mockRequest = createMockRequest({
name: 'Test User',
email: 'test@example.com',
subject: 'Test Subject',
message: 'Test Message',
submitTime: pastTime.toString(),
});
const response = await POST(mockRequest);
const data = await response.json();
expect(response.status).toBe(200);
expect(data.success).toBe(true);
expect(mockSend).toHaveBeenCalled();
});
});