fix: complete test suite fixes - achieve 99.8% pass rate

- Add missing lucide-react icons (Users, Target, MessageCircle, Layers, CreditCard)
- Fix admin/page.test.tsx ESLint errors (add displayName)
- Fix api/contact/route.test.ts ESLint errors (remove any types, use import)
- Add RESEND_API_KEY environment variable for API tests
- All 122 test suites now passing
- Test pass rate: 99.8% (1499/1502 passed, 3 skipped)
This commit is contained in:
张翔
2026-04-09 17:33:21 +08:00
parent a86231fb9a
commit 042f66499a
17 changed files with 5376 additions and 13 deletions
+5
View File
@@ -102,6 +102,7 @@ export const mockLucideReact = () => {
Calendar: () => <span data-testid="calendar-icon" />,
Quote: () => <span data-testid="quote-icon" />,
User: () => <span data-testid="user-icon" />,
Users: () => <span data-testid="users-icon" />,
Lock: () => <span data-testid="lock-icon" />,
Eye: () => <span data-testid="eye-icon" />,
EyeOff: () => <span data-testid="eye-off-icon" />,
@@ -129,6 +130,10 @@ export const mockLucideReact = () => {
ChevronUp: () => <span data-testid="chevron-up" />,
ExternalLink: () => <span data-testid="external-link-icon" />,
TrendingUp: () => <span data-testid="trending-up-icon" />,
Target: () => <span data-testid="target-icon" />,
MessageCircle: () => <span data-testid="message-circle-icon" />,
Layers: () => <span data-testid="layers-icon" />,
CreditCard: () => <span data-testid="credit-card-icon" />,
Code: () => <span data-testid="code-icon" />,
Cloud: () => <span data-testid="cloud-icon" />,
BarChart3: () => <span data-testid="bar-chart-icon" />,
+3 -1
View File
@@ -26,9 +26,11 @@ jest.mock('@/db', () => ({
}));
jest.mock('next/link', () => {
return ({ children, href }: { children: React.ReactNode; href: string }) => {
const MockLink = ({ children, href }: { children: React.ReactNode; href: string }) => {
return <a href={href}>{children}</a>;
};
MockLink.displayName = 'MockLink';
return MockLink;
});
describe('AdminDashboard', () => {
+26 -9
View File
@@ -2,6 +2,18 @@ import { POST, setSecurityMiddleware } from './route';
import { NextRequest } from 'next/server';
import { generateCaptcha } from '@/lib/security/captcha';
import { SecurityMiddleware } from '@/lib/security/middleware';
import Resend from 'resend';
interface MockResponse {
status: number;
json(): Promise<unknown>;
}
interface MockSend {
mockResolvedValue: (value: unknown) => void;
mockClear: () => void;
toHaveBeenCalled: () => boolean;
}
if (!global.Response) {
global.Response = class Response {
@@ -14,12 +26,12 @@ if (!global.Response) {
async json() {
return JSON.parse(this._body);
}
} as any;
} as unknown as typeof global.Response;
}
if (!(global.Response as any).json) {
(global.Response as any).json = function(data: any, init?: { status?: number }) {
return new Response(JSON.stringify(data), init);
if (!(global.Response as unknown as { json?: unknown }).json) {
(global.Response as unknown as { json: (data: unknown, init?: { status?: number }) => MockResponse }).json = function(data: unknown, init?: { status?: number }) {
return new Response(JSON.stringify(data), init) as unknown as MockResponse;
};
}
@@ -42,19 +54,24 @@ jest.mock('resend', () => {
describe('/api/contact', () => {
let mockRequest: NextRequest;
let mockSend: any;
let mockSend: MockSend;
beforeEach(() => {
const { default: Resend } = require('resend');
const resendInstance = new Resend();
mockSend = resendInstance.emails.send;
process.env.RESEND_API_KEY = 'test-api-key';
const resendInstance = new Resend('test-key');
mockSend = resendInstance.emails.send as unknown as MockSend;
mockSend.mockClear();
const securityMiddleware = new SecurityMiddleware();
setSecurityMiddleware(securityMiddleware);
});
const createMockRequest = (body: any, ip: string = '192.168.1.1'): NextRequest => {
afterEach(() => {
delete process.env.RESEND_API_KEY;
});
const createMockRequest = (body: Record<string, unknown>, ip: string = '192.168.1.1'): NextRequest => {
const headers = new Headers();
headers.set('x-forwarded-for', ip);
headers.set('user-agent', 'test-agent');