feat: create security monitoring dashboard
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
import { describe, it, expect, jest, beforeAll, afterEach } from '@jest/globals';
|
||||
import React from 'react';
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import '@testing-library/jest-dom';
|
||||
import SecurityDashboard from './page';
|
||||
|
||||
jest.mock('lucide-react', () => ({
|
||||
Shield: () => <span data-testid="shield-icon" />,
|
||||
AlertTriangle: () => <span data-testid="alert-icon" />,
|
||||
Activity: () => <span data-testid="activity-icon" />,
|
||||
Lock: () => <span data-testid="lock-icon" />,
|
||||
RefreshCw: () => <span data-testid="refresh-cw-icon" />,
|
||||
TrendingUp: () => <span data-testid="trending-up-icon" />,
|
||||
TrendingDown: () => <span data-testid="trending-down-icon" />,
|
||||
}));
|
||||
|
||||
jest.mock('@/components/ui/button', () => ({
|
||||
Button: ({ children, disabled, ...props }: any) => (
|
||||
<button disabled={disabled} {...props}>
|
||||
{children}
|
||||
</button>
|
||||
),
|
||||
}));
|
||||
|
||||
jest.mock('@/components/ui/card', () => ({
|
||||
Card: ({ children }: any) => <div data-testid="card">{children}</div>,
|
||||
CardHeader: ({ children }: any) => <div data-testid="card-header">{children}</div>,
|
||||
CardTitle: ({ children }: any) => <h3 data-testid="card-title">{children}</h3>,
|
||||
CardContent: ({ children }: any) => <div data-testid="card-content">{children}</div>,
|
||||
}));
|
||||
|
||||
global.fetch = jest.fn(() =>
|
||||
Promise.resolve({
|
||||
ok: true,
|
||||
json: () => Promise.resolve({
|
||||
success: true,
|
||||
logs: [
|
||||
{
|
||||
id: '1',
|
||||
timestamp: Date.now(),
|
||||
type: 'captcha',
|
||||
severity: 'high',
|
||||
message: '验证码验证失败',
|
||||
ip: '192.168.1.1',
|
||||
},
|
||||
],
|
||||
stats: {
|
||||
totalRequests: 100,
|
||||
blockedRequests: 5,
|
||||
captchaAttempts: 10,
|
||||
rateLimitHits: 3,
|
||||
maliciousContentDetected: 2,
|
||||
successRate: 95,
|
||||
},
|
||||
}),
|
||||
} as Response)
|
||||
);
|
||||
|
||||
describe('SecurityDashboard', () => {
|
||||
beforeAll(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('Rendering', () => {
|
||||
it('should render security dashboard', () => {
|
||||
render(<SecurityDashboard />);
|
||||
expect(screen.getByText('安全监控仪表板')).toBeInTheDocument();
|
||||
expect(screen.getByText('实时监控网站安全状态和威胁检测')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render all stat cards', () => {
|
||||
render(<SecurityDashboard />);
|
||||
expect(screen.getByText('总请求数')).toBeInTheDocument();
|
||||
expect(screen.getByText('已拦截请求')).toBeInTheDocument();
|
||||
expect(screen.getByText('验证码尝试')).toBeInTheDocument();
|
||||
expect(screen.getByText('频率限制命中')).toBeInTheDocument();
|
||||
expect(screen.getByText('恶意内容检测')).toBeInTheDocument();
|
||||
expect(screen.getByText('成功率')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display stats values', async () => {
|
||||
render(<SecurityDashboard />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('100')).toBeInTheDocument();
|
||||
expect(screen.getByText('5')).toBeInTheDocument();
|
||||
expect(screen.getByText('10')).toBeInTheDocument();
|
||||
expect(screen.getByText('3')).toBeInTheDocument();
|
||||
expect(screen.getByText('2')).toBeInTheDocument();
|
||||
expect(screen.getByText('95%')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Security Logs', () => {
|
||||
it('should render security logs section', async () => {
|
||||
render(<SecurityDashboard />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('安全日志')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('should display log entries', async () => {
|
||||
render(<SecurityDashboard />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('验证码验证失败')).toBeInTheDocument();
|
||||
expect(screen.getByText('IP: 192.168.1.1')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('should have filter buttons', () => {
|
||||
render(<SecurityDashboard />);
|
||||
expect(screen.getByText('全部')).toBeInTheDocument();
|
||||
expect(screen.getByText('高危')).toBeInTheDocument();
|
||||
expect(screen.getByText('中危')).toBeInTheDocument();
|
||||
expect(screen.getByText('低危')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Refresh Functionality', () => {
|
||||
it('should have refresh button', async () => {
|
||||
render(<SecurityDashboard />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('refresh-cw-icon')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('should call fetch when refresh is clicked', async () => {
|
||||
render(<SecurityDashboard />);
|
||||
|
||||
await waitFor(() => {
|
||||
const refreshButton = screen.getAllByRole('button')[0];
|
||||
expect(refreshButton).not.toBeDisabled();
|
||||
|
||||
refreshButton.click();
|
||||
|
||||
expect(global.fetch).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user