Skip to content

Commit 5cc566d

Browse files
authored
Merge pull request #363 from Code102SoftwareProject/dev
Dev
2 parents 3915b12 + 34af9e8 commit 5cc566d

214 files changed

Lines changed: 19489 additions & 10095 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci-build-check.yml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,80 @@ jobs:
3838
continue-on-error: false
3939
env:
4040
CI: true
41+
# Database
42+
MONGODB_URI: mongodb://localhost:27017/test-db
43+
44+
# JWT & Auth
45+
JWT_SECRET: dd8a48e6f99d7b4c3b6a4c7e9587a2cc7f8b9e3a1d5f6g8h2j3k4m5n6p7q8r9t1u2v3w4x5y6z7-ci-test
46+
ADMIN_JWT_SECRET: d8da04f2c803f88c68e38c47bad261223d01cc73e5f89d15e02bbf9f858f53b0f7220e5c23eb1f34ad355f821298d196-ci-test
47+
M_KEY: e685b3de592422cdceff763ca3e784a2c792e4e7e5984cf0ea86544555612b80-ci-test
48+
49+
# Mock external services for testing
50+
R2_ACCESS_KEY_ID: mock-r2-access-key-id
51+
R2_SECRET_ACCESS_KEY: mock-r2-secret-access-key
52+
R2_ACCOUNT_ID: mock-r2-account-id
53+
R2_BUCKET_NAME: mock-test-bucket
54+
R2_ENDPOINT: https://mock-endpoint.r2.cloudflarestorage.com
55+
56+
SENDGRID_API_KEY: SG.mock-sendgrid-api-key-for-testing-only
57+
SENDGRID_FROM_EMAIL: test@example.com
58+
DAILY_API_KEY: mock-daily-api-key-for-testing-only
59+
GOOGLE_CLIENT_ID: mock-google-client-id
60+
GOOGLE_CLIENT_SECRET: mock-google-client-secret
61+
GEMINI_API_KEY: mock-gemini-api-key-for-testing-only
62+
SYSTEM_API_KEY: mock-system-api-key-for-testing-only
63+
64+
# Test environment
65+
NODE_ENV: test
66+
NEXT_TELEMETRY_DISABLED: 1
4167

4268
- name: Build application
4369
run: npm run build
4470
continue-on-error: false
4571
env:
4672
CI: true
73+
# Database
74+
MONGODB_URI: mongodb://localhost:27017/test-db
75+
76+
# JWT & Auth - Make sure these are long enough and properly formatted
77+
JWT_SECRET: dd8a48e6f99d7b4c3b6a4c7e9587a2cc7f8b9e3a1d5f6g8h2j3k4m5n6p7q8r9t1u2v3w4x5y6z7-ci-build
78+
ADMIN_JWT_SECRET: d8da04f2c803f88c68e38c47bad261223d01cc73e5f89d15e02bbf9f858f53b0f7220e5c23eb1f34ad355f821298d196-ci-build
79+
M_KEY: e685b3de592422cdceff763ca3e784a2c792e4e7e5984cf0ea86544555612b80-ci-build
80+
81+
# Cloudflare R2 Storage
82+
R2_ACCESS_KEY_ID: mock-r2-access-key-id
83+
R2_SECRET_ACCESS_KEY: mock-r2-secret-access-key
84+
R2_ACCOUNT_ID: mock-r2-account-id
85+
R2_BUCKET_NAME: mock-skillswaphub-bucket
86+
R2_ENDPOINT: https://mock-endpoint.r2.cloudflarestorage.com
87+
88+
# Email Services
89+
SENDGRID_API_KEY: SG.mock-sendgrid-api-key-for-ci-build-only
90+
SENDGRID_FROM_EMAIL: test@example.com
91+
MEETING_NOTI_MAIL: test@example.com
92+
MEETING_NOTI_PW: mock-email-password
93+
94+
# Daily.co Video
95+
DAILY_API_KEY: mock-daily-api-key-for-ci-build-only
96+
97+
# Google OAuth
98+
GOOGLE_CLIENT_ID: mock-google-client-id.apps.googleusercontent.com
99+
GOOGLE_CLIENT_SECRET: mock-google-client-secret
100+
NEXT_PUBLIC_GOOGLE_CLIENT_ID: mock-google-client-id.apps.googleusercontent.com
101+
102+
# AI Service
103+
GEMINI_API_KEY: mock-gemini-api-key-for-ci-build-only
104+
105+
# System API
106+
SYSTEM_API_KEY: mock-system-api-key-for-ci-build-only
107+
108+
# Socket Connection
109+
NEXT_PUBLIC_SOCKET: https://mock-socket-server.example.com/
110+
111+
# Build Configuration - Use 'ci' instead of 'production' to avoid production validations
112+
NODE_ENV: ci
113+
NEXT_TELEMETRY_DISABLED: 1
114+
SKIP_DB_VALIDATION: true
47115

48116
- name: Check build output
49117
run: |

Enhanced-Suspension-Test-Guide.md

Whitespace-only changes.

SUSPENSION-POPUP-SUMMARY.md

Whitespace-only changes.
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
/**
2+
* Admin Forum Reports Tests
3+
* Test suite for the admin forum report management functionality
4+
*/
5+
6+
import React from 'react';
7+
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
8+
import '@testing-library/jest-dom';
9+
import userEvent from '@testing-library/user-event';
10+
import ForumReportsContent from '@/components/Admin/dashboardContent/ForumReportsContent';
11+
import Swal from 'sweetalert2';
12+
13+
// Mock dependencies
14+
jest.mock('sweetalert2', () => ({
15+
__esModule: true,
16+
default: {
17+
fire: jest.fn(() => Promise.resolve({ isConfirmed: true })),
18+
close: jest.fn()
19+
}
20+
}));
21+
22+
// Mock fetch
23+
global.fetch = jest.fn();
24+
const mockFetch = global.fetch as jest.MockedFunction<typeof global.fetch>;
25+
const mockSwal = Swal as jest.Mocked<typeof Swal>;
26+
27+
describe('Admin Forum Reports Component', () => {
28+
const mockReports = [
29+
{
30+
_id: 'report-1',
31+
postId: {
32+
_id: 'post-1',
33+
title: 'Inappropriate Post',
34+
content: 'This is an inappropriate post content',
35+
author: { _id: 'user-1' },
36+
likes: 5,
37+
dislikes: 10,
38+
replies: 2,
39+
views: 100,
40+
createdAt: '2023-06-15T10:00:00Z'
41+
},
42+
reportedBy: {
43+
_id: 'user-2',
44+
firstName: 'Jane',
45+
lastName: 'Doe',
46+
email: 'jane@example.com',
47+
avatar: 'avatar.jpg'
48+
},
49+
reportType: 'inappropriate_content',
50+
description: 'This post contains inappropriate content',
51+
status: 'pending',
52+
priority: 'high',
53+
aiAnalysis: {
54+
isAnalyzed: true,
55+
analysisResult: 'potentially_harmful',
56+
confidence: 0.85,
57+
detectedIssues: ['offensive language', 'adult content'],
58+
summary: 'Post contains potentially offensive content',
59+
recommendedAction: 'review',
60+
analysisDate: '2023-06-15T10:30:00Z',
61+
modelUsed: 'Gemini 2.0'
62+
},
63+
postSnapshot: {
64+
title: 'Inappropriate Post',
65+
content: 'This is an inappropriate post content',
66+
authorId: 'user-1',
67+
authorName: 'John Smith',
68+
forumId: 'forum-1',
69+
forumTitle: 'General Discussion',
70+
capturedAt: '2023-06-15T10:15:00Z'
71+
},
72+
createdAt: '2023-06-15T10:15:00Z'
73+
},
74+
{
75+
_id: 'report-2',
76+
postId: {
77+
_id: 'post-2',
78+
title: 'Spam Post',
79+
content: 'This is spam content',
80+
author: { _id: 'user-3' },
81+
likes: 0,
82+
dislikes: 15,
83+
replies: 0,
84+
views: 30,
85+
createdAt: '2023-06-14T09:00:00Z'
86+
},
87+
reportedBy: {
88+
_id: 'user-4',
89+
firstName: 'Alice',
90+
lastName: 'Johnson',
91+
email: 'alice@example.com'
92+
},
93+
reportType: 'spam',
94+
description: 'This post is spam',
95+
status: 'under_review',
96+
priority: 'medium',
97+
aiAnalysis: {
98+
isAnalyzed: true,
99+
analysisResult: 'harmful',
100+
confidence: 0.92,
101+
detectedIssues: ['spam', 'promotional content'],
102+
summary: 'Post is likely spam',
103+
recommendedAction: 'remove',
104+
analysisDate: '2023-06-14T09:30:00Z',
105+
modelUsed: 'Gemini 2.0'
106+
},
107+
adminId: {
108+
_id: 'admin-1',
109+
username: 'admin',
110+
email: 'admin@example.com'
111+
},
112+
postSnapshot: {
113+
title: 'Spam Post',
114+
content: 'This is spam content',
115+
authorId: 'user-3',
116+
authorName: 'Bob Williams',
117+
forumId: 'forum-1',
118+
forumTitle: 'General Discussion',
119+
capturedAt: '2023-06-14T09:15:00Z'
120+
},
121+
createdAt: '2023-06-14T09:15:00Z'
122+
}
123+
];
124+
125+
const mockPagination = {
126+
currentPage: 1,
127+
totalPages: 1,
128+
totalCount: 2,
129+
hasNext: false,
130+
hasPrev: false
131+
};
132+
133+
beforeEach(() => {
134+
jest.clearAllMocks();
135+
136+
// Default mock responses
137+
mockFetch.mockResolvedValue({
138+
ok: true,
139+
json: async () => ({
140+
success: true,
141+
data: {
142+
reports: mockReports,
143+
pagination: mockPagination,
144+
statusSummary: {
145+
pending: 1,
146+
under_review: 1,
147+
resolved: 0,
148+
dismissed: 0,
149+
auto_resolved: 0
150+
},
151+
aiSummary: {
152+
safe: 0,
153+
potentially_harmful: 1,
154+
harmful: 1,
155+
requires_review: 0
156+
}
157+
}
158+
}),
159+
} as Response);
160+
});
161+
162+
// Test Case 1: Component renders and displays reports
163+
test('renders forum reports dashboard and displays reports', async () => {
164+
render(<ForumReportsContent />);
165+
166+
// Check for loading spinner initially
167+
const loadingSpinner = document.querySelector('.animate-spin');
168+
expect(loadingSpinner).toBeInTheDocument();
169+
170+
// Wait for reports to load
171+
await waitFor(() => {
172+
expect(screen.getByText('Forum Post Reports')).toBeInTheDocument();
173+
});
174+
175+
// Check that reports are displayed
176+
expect(screen.getByText('Inappropriate Post')).toBeInTheDocument();
177+
expect(screen.getByText('Spam Post')).toBeInTheDocument();
178+
179+
// Check that status filters are displayed
180+
expect(screen.getByRole('option', { name: 'All Status' })).toBeInTheDocument();
181+
expect(screen.getByRole('option', { name: 'Pending' })).toBeInTheDocument();
182+
expect(screen.getByRole('option', { name: 'Under Review' })).toBeInTheDocument();
183+
184+
// Check that priority badges are displayed
185+
expect(screen.getByText('HIGH')).toBeInTheDocument();
186+
expect(screen.getByText('MEDIUM')).toBeInTheDocument();
187+
188+
// Check that AI analysis results are displayed
189+
expect(screen.getByText('potentially harmful')).toBeInTheDocument();
190+
expect(screen.getByText('harmful')).toBeInTheDocument();
191+
});
192+
});

0 commit comments

Comments
 (0)