diff --git a/.github/workflows/badge-assignment.yml b/.github/workflows/badge-assignment.yml deleted file mode 100644 index ff759626..00000000 --- a/.github/workflows/badge-assignment.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Daily Badge Assignment - -on: - schedule: - # Runs daily at midnight UTC (adjust timezone as needed) - - cron: "0 0 * * *" - - # Allow manual trigger - workflow_dispatch: - -jobs: - assign-badges: - runs-on: ubuntu-latest - - steps: - - name: Call Badge Assignment API - run: | - curl -X POST \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer ${{ secrets.CRON_SECRET }}" \ - ${{ secrets.APP_URL }}/api/badge-assignments - env: - CRON_SECRET: ${{ secrets.CRON_SECRET }} - APP_URL: ${{ secrets.APP_URL }} diff --git a/.github/workflows/ci-build-check.yml b/.github/workflows/ci-build-check.yml new file mode 100644 index 00000000..b07ea6d5 --- /dev/null +++ b/.github/workflows/ci-build-check.yml @@ -0,0 +1,119 @@ +name: CI - Build and Test + +on: + # Trigger on pull requests to main branch + pull_request: + branches: [ main, master ] + + # Trigger on pushes to main branch (merges) + push: + branches: [ main, master ] + + # Allow manual trigger + workflow_dispatch: + +jobs: + build-and-test: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [18.x, 20.x] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run tests + run: npm test + continue-on-error: false + env: + CI: true + + - name: Build application + run: npm run build + continue-on-error: false + env: + CI: true + + - name: Check build output + run: | + if [ ! -d ".next" ]; then + echo "Build failed - .next directory not found" + exit 1 + fi + echo "Build successful - .next directory exists" + + - name: Upload build artifacts (on failure) + if: failure() + uses: actions/upload-artifact@v4 + with: + name: build-logs-${{ matrix.node-version }} + path: | + .next/ + npm-debug.log* + yarn-debug.log* + yarn-error.log* + retention-days: 5 + + # Additional job for documentation build (if needed) + build-docs: + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.x' + cache: 'npm' + + - name: Install main dependencies + run: npm ci + + - name: Install documentation dependencies + run: | + cd documentation + npm ci + + - name: Build documentation + run: | + cd documentation + npm run build + continue-on-error: false + + # Security and quality checks + security-audit: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.x' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run security audit + run: npm audit --audit-level=high + continue-on-error: true + + - name: Check for outdated packages + run: npm outdated || true diff --git a/.github/workflows/pr-quality-check.yml b/.github/workflows/pr-quality-check.yml new file mode 100644 index 00000000..fe475f59 --- /dev/null +++ b/.github/workflows/pr-quality-check.yml @@ -0,0 +1,32 @@ +name: PR Quality Check + +on: + pull_request: + types: [opened, synchronize, reopened] + +permissions: + contents: read + pull-requests: write + issues: write + +jobs: + quick-check: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.x' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Build check + run: npm run build + env: + CI: true diff --git a/__tests__/components/MeetingBox.test.tsx b/__tests__/components/MeetingBox.test.tsx index 32bd7d65..c6b223ba 100644 --- a/__tests__/components/MeetingBox.test.tsx +++ b/__tests__/components/MeetingBox.test.tsx @@ -1,722 +1,471 @@ /** * MeetingBox Component Tests - * Tests the meeting management functionality including scheduling, accepting, and cancelling meetings */ import React from 'react'; -import { render, screen, fireEvent, waitFor, act } from '@testing-library/react'; +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import '@testing-library/jest-dom'; import MeetingBox from '@/components/messageSystem/MeetingBox'; -// Create shared mocks for router -const mockPush = jest.fn(); -const mockRefresh = jest.fn(); - -// Mock the router -jest.mock('next/navigation', () => ({ - useRouter: () => ({ - push: mockPush, - refresh: mockRefresh - }) -})); - -// Mock meeting API services -jest.mock('@/services/meetingApiServices', () => ({ - fetchMeetings: jest.fn(), - createMeeting: jest.fn(), - updateMeeting: jest.fn() -})); - -// Mock session API services for cache invalidation -jest.mock('@/services/sessionApiServices', () => ({ - invalidateUsersCaches: jest.fn() -})); - -// Mock debounced API service -jest.mock('@/services/debouncedApiService', () => { - const mockService = { - makeRequest: jest.fn(), - invalidate: jest.fn() - }; - return { - debouncedApiService: mockService, - makeRequest: mockService.makeRequest, - invalidate: mockService.invalidate - }; -}); - -// Mock utility functions -jest.mock('@/utils/avatarUtils', () => ({ - processAvatarUrl: jest.fn((url) => url), - getFirstLetter: jest.fn((firstName, userId) => firstName?.[0] || 'U'), - createFallbackAvatar: jest.fn(() => 'data:image/svg+xml;base64,mock') -})); - -// Mock OptimizedAvatar component -jest.mock('@/components/ui/OptimizedAvatar', () => { - return function MockOptimizedAvatar({ userId, firstName, lastName }: any) { +// Mock child components +jest.mock('@/components/meetingSystem/CreateMeetingModal', () => { + return function MockCreateMeetingModal({ onClose, onCreate, receiverName }: any) { return ( -
- Avatar for {firstName} {lastName} ({userId}) +
+
Create Meeting Modal for {receiverName}
+ +
); }; }); -// Mock Alert component -jest.mock('@/components/ui/Alert', () => { - return function MockAlert({ type, title, message, isOpen, onClose }: any) { - if (!isOpen) return null; +jest.mock('@/components/meetingSystem/CancelMeetingModal', () => { + return function MockCancelMeetingModal({ meetingId, onClose, onCancel, userName }: any) { return ( -
- {title &&
{title}
} -
{message}
- +
+
Cancel Meeting Modal for {userName}
+ +
); }; }); -// Mock ConfirmationDialog component -jest.mock('@/components/ui/ConfirmationDialog', () => { - return function MockConfirmationDialog({ - isOpen, - onClose, - onConfirm, - title, - message, - type, - confirmText +jest.mock('@/components/meetingSystem/MeetingList', () => { + return function MockMeetingList({ + pendingRequests, + upcomingMeetings, + onScheduleMeeting, + onMeetingAction, + onCancelMeeting }: any) { - if (!isOpen) return null; return ( -
-
{title}
-
{message}
-
{type}
- - +
+
{pendingRequests.length}
+
{upcomingMeetings.length}
+ + + + {pendingRequests.map((meeting: any) => ( +
+ + +
+ ))} + + {upcomingMeetings.map((meeting: any) => ( +
+ +
+ ))}
); }; }); -// Mock CreateMeetingModal component -jest.mock('@/components/meetingSystem/CreateMeetingModal', () => { - return function MockCreateMeetingModal({ onClose, onCreate, receiverName }: any) { +jest.mock('@/components/meetingSystem/SavedNotesList', () => { + return function MockSavedNotesList({ notes }: any) { return ( -
-
Creating meeting with {receiverName}
- - +
+
{notes.length}
); }; }); -// Mock CancelMeetingModal component -jest.mock('@/components/meetingSystem/CancelMeetingModal', () => { - return function MockCancelMeetingModal({ meetingId, onClose, onCancel, userName }: any) { - return ( -
-
Cancelling meeting for {userName}
- - +jest.mock('@/components/ui/Alert', () => { + return function MockAlert({ isOpen, type, message, onClose }: any) { + return isOpen ? ( +
+
{message}
+
- ); + ) : null; }; }); -// Mock fetch for API calls -global.fetch = jest.fn(); +jest.mock('@/components/ui/ConfirmationDialog', () => { + return function MockConfirmationDialog({ isOpen, title, onConfirm, onClose }: any) { + return isOpen ? ( +
+
{title}
+ + +
+ ) : null; + }; +}); -// Mock URL.createObjectURL for notes download -global.URL.createObjectURL = jest.fn(() => 'mock-blob-url'); -global.URL.revokeObjectURL = jest.fn(); +// Mock API Services +const mockFetchMeetings = jest.fn(); +const mockCreateMeeting = jest.fn(); +const mockUpdateMeeting = jest.fn(); +const mockCancelMeetingWithReason = jest.fn(); +const mockFetchAllUserMeetingNotes = jest.fn(); +const mockFilterMeetingsByType = jest.fn(); +const mockCheckMeetingLimit = jest.fn(); +const mockCanCancelMeeting = jest.fn(); -describe('MeetingBox Component', () => { - const mockProps = { - chatRoomId: '6873cdd898892472c9621cf1', - userId: '6873cc50ac4e1d6e1cddf33f', - onClose: jest.fn(), - onMeetingUpdate: jest.fn() - }; +jest.mock('@/services/meetingApiServices', () => ({ + fetchMeetings: (...args: any[]) => mockFetchMeetings(...args), + createMeeting: (...args: any[]) => mockCreateMeeting(...args), + updateMeeting: (...args: any[]) => mockUpdateMeeting(...args), + cancelMeetingWithReason: (...args: any[]) => mockCancelMeetingWithReason(...args), + fetchMeetingCancellation: jest.fn(), + acknowledgeMeetingCancellation: jest.fn(), + checkMeetingNotesExist: jest.fn().mockResolvedValue(false), + fetchAllUserMeetingNotes: (...args: any[]) => mockFetchAllUserMeetingNotes(...args), + downloadMeetingNotesFile: jest.fn(), + filterMeetingsByType: (...args: any[]) => mockFilterMeetingsByType(...args), + checkMeetingLimit: (...args: any[]) => mockCheckMeetingLimit(...args), + canCancelMeeting: (...args: any[]) => mockCanCancelMeeting(...args), +})); - const mockMeetings = [ - { - _id: 'meeting-1', - senderId: 'other-user-id', // Other user is sender - receiverId: '6873cc50ac4e1d6e1cddf33f', // Test user is receiver - description: 'Test meeting 1', - meetingTime: '2025-07-20T10:00:00Z', - state: 'pending', - acceptStatus: false, - meetingLink: null - }, - { - _id: 'meeting-2', - senderId: 'other-user-id', - receiverId: '6873cc50ac4e1d6e1cddf33f', - description: 'Test meeting 2', - meetingTime: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(), // Tomorrow - state: 'accepted', - acceptStatus: true, - meetingLink: 'https://meet.example.com/room123' - }, - { - _id: 'meeting-3', - senderId: '6873cc50ac4e1d6e1cddf33f', - receiverId: 'other-user-id', - description: 'Past meeting', - meetingTime: '2025-07-10T10:00:00Z', - state: 'completed', - acceptStatus: true, - meetingLink: null - } - ]; - - const mockChatRoom = { - _id: '6873cdd898892472c9621cf1', - participants: ['6873cc50ac4e1d6e1cddf33f', 'other-user-id'] - }; +const mockFetchChatRoom = jest.fn(); +const mockFetchUserProfile = jest.fn(); - const mockUserProfile = { - _id: 'other-user-id', - firstName: 'John', - lastName: 'Doe', - avatar: 'https://example.com/avatar.jpg' - }; +jest.mock('@/services/chatApiServices', () => ({ + fetchChatRoom: (...args: any[]) => mockFetchChatRoom(...args), + fetchUserProfile: (...args: any[]) => mockFetchUserProfile(...args), +})); + +jest.mock('@/services/sessionApiServices', () => ({ + invalidateUsersCaches: jest.fn(), +})); + +jest.mock('@/services/debouncedApiService', () => ({ + debouncedApiService: { + fetchUserProfile: jest.fn(), + makeRequest: jest.fn(), + }, +})); - // Get the mocked functions - const mockFetchMeetings = require('@/services/meetingApiServices').fetchMeetings as jest.MockedFunction; - const mockCreateMeeting = require('@/services/meetingApiServices').createMeeting as jest.MockedFunction; - const mockUpdateMeeting = require('@/services/meetingApiServices').updateMeeting as jest.MockedFunction; - const mockInvalidateUsersCaches = require('@/services/sessionApiServices').invalidateUsersCaches as jest.MockedFunction; - const mockMakeRequest = require('@/services/debouncedApiService').debouncedApiService.makeRequest as jest.MockedFunction; - const mockInvalidate = require('@/services/debouncedApiService').debouncedApiService.invalidate as jest.MockedFunction; - const mockRouter = require('next/navigation').useRouter(); - const mockPush = mockRouter.push as jest.MockedFunction; +// Mock data +const mockChatRoom = { + _id: 'chat-room-1', + participants: ['user1', 'user2'], + messages: [] +}; + +const mockUserProfile = { + _id: 'user2', + firstName: 'John', + lastName: 'Doe', + avatar: '/avatar.png' +}; + +const mockMeetings = [ + { + _id: 'meeting-1', + description: 'Frontend Development Discussion', + meetingTime: new Date('2025-07-20T14:00:00Z').toISOString(), + state: 'pending', + senderId: 'user2', + receiverId: 'user1', + createdAt: new Date('2025-07-18T10:00:00Z').toISOString() + }, + { + _id: 'meeting-2', + description: 'Project Planning', + meetingTime: new Date('2025-07-22T16:00:00Z').toISOString(), + state: 'accepted', + senderId: 'user1', + receiverId: 'user2', + createdAt: new Date('2025-07-17T10:00:00Z').toISOString() + } +]; + +const mockFilteredMeetings = { + pendingRequests: [mockMeetings[0]], + upcomingMeetings: [mockMeetings[1]], + pastMeetings: [], + cancelledMeetings: [] +}; + +const mockSavedNotes = [ + { + _id: 'note-1', + meetingId: 'meeting-3', + title: 'Meeting Notes 1', + content: 'Content of the first note', + tags: ['development'], + wordCount: 100, + lastModified: new Date('2025-07-15T15:00:00Z').toISOString(), + createdAt: new Date('2025-07-15T15:00:00Z').toISOString(), + isPrivate: false + } +]; + +// Default props +const defaultProps = { + chatRoomId: 'chat-room-1', + userId: 'user1', + onClose: jest.fn(), + onMeetingUpdate: jest.fn() +}; +describe('MeetingBox Component', () => { beforeEach(() => { jest.clearAllMocks(); - // Mock chat room fetch - (global.fetch as jest.Mock).mockImplementation((url: string) => { - if (url.includes('/api/chatrooms')) { - return Promise.resolve({ - ok: true, - json: () => Promise.resolve({ - success: true, - chatRooms: [mockChatRoom] - }) - }); - } - - if (url.includes('/api/users/profile')) { - return Promise.resolve({ - ok: true, - json: () => Promise.resolve({ - success: true, - user: mockUserProfile - }) - }); - } - - if (url.includes('/api/meeting/cancel')) { - return Promise.resolve({ - ok: true, - json: () => Promise.resolve({ - meeting: { ...mockMeetings[0], state: 'cancelled' } - }) - }); - } - - if (url.includes('/api/meeting-notes')) { - return Promise.resolve({ - ok: true, - json: () => Promise.resolve({ - _id: 'notes-1', - content: 'Test meeting notes content', - title: 'Meeting Notes', - userName: 'Test User', - createdAt: '2025-07-10T10:00:00Z' - }) - }); - } - - return Promise.resolve({ - ok: false, - json: () => Promise.resolve({ error: 'Not found' }) - }); - }); - - // Mock API services + // Setup default mocks + mockFetchChatRoom.mockResolvedValue(mockChatRoom); + mockFetchUserProfile.mockResolvedValue(mockUserProfile); mockFetchMeetings.mockResolvedValue(mockMeetings); - mockCreateMeeting.mockResolvedValue({ - _id: 'new-meeting-id', - senderId: '6873cc50ac4e1d6e1cddf33f', - receiverId: 'other-user-id', - description: 'New test meeting', - meetingTime: '2025-07-30T15:00:00Z', - state: 'pending' - }); - mockUpdateMeeting.mockResolvedValue({ - ...mockMeetings[0], - state: 'accepted' - }); - - // Mock debounced API service - mockMakeRequest.mockImplementation((key: string, fn: () => any) => fn()); + mockFilterMeetingsByType.mockReturnValue(mockFilteredMeetings); + mockFetchAllUserMeetingNotes.mockResolvedValue(mockSavedNotes); + mockCanCancelMeeting.mockReturnValue({ canCancel: true, reason: null }); + mockCheckMeetingLimit.mockReturnValue(0); }); - afterEach(() => { - jest.resetAllMocks(); - }); - - describe('Initial Rendering', () => { - it('should render the meeting box with header and schedule button', async () => { - render(); + describe('Rendering', () => { + it('should render loading state initially', async () => { + mockFetchMeetings.mockImplementation(() => new Promise(() => {})); // Never resolve - await waitFor(() => { - expect(screen.getByText('Meetings')).toBeInTheDocument(); - expect(screen.getByText('New')).toBeInTheDocument(); - }); - }); - - it('should show loading state initially', () => { - render(); + render(); expect(screen.getByText('Loading meetings...')).toBeInTheDocument(); }); - it('should fetch chat room data and meetings on mount', async () => { - render(); + it('should render the main meeting interface after loading', async () => { + render(); await waitFor(() => { - expect(global.fetch).toHaveBeenCalledWith( - expect.stringContaining('/api/chatrooms?chatRoomId=6873cdd898892472c9621cf1') - ); - expect(mockFetchMeetings).toHaveBeenCalledWith( - '6873cc50ac4e1d6e1cddf33f', - 'other-user-id' - ); + expect(screen.getByText('Meetings')).toBeInTheDocument(); }); - }); - }); - - describe('Meeting Display and Categorization', () => { - it('should categorize and display meetings correctly', async () => { - render(); - await waitFor(() => { - expect(screen.queryByText('Loading meetings...')).not.toBeInTheDocument(); - }); - - // Should show different meeting categories - expect(screen.getByText('Pending Requests (1)')).toBeInTheDocument(); - expect(screen.getByText('Upcoming Meetings (1)')).toBeInTheDocument(); + expect(screen.getByRole('button', { name: /new/i })).toBeInTheDocument(); + expect(screen.getByTestId('meeting-list')).toBeInTheDocument(); }); - it('should show empty state when no meetings exist', async () => { - mockFetchMeetings.mockResolvedValueOnce([]); - - render(); + it('should render saved notes section', async () => { + render(); await waitFor(() => { - expect(screen.getByText('No meetings scheduled')).toBeInTheDocument(); - expect(screen.getByText('Schedule Meeting')).toBeInTheDocument(); + expect(screen.getByText(/saved meeting notes/i)).toBeInTheDocument(); }); }); }); - describe('Meeting Creation', () => { - it('should open create meeting modal when schedule button is clicked', async () => { - // Use meetings with no active count to allow modal opening - mockFetchMeetings.mockResolvedValueOnce([mockMeetings[2]]); // Only past meeting - - render(); + describe('Data Fetching', () => { + it('should fetch chat room and meetings on mount', async () => { + render(); await waitFor(() => { - expect(screen.queryByText('Loading meetings...')).not.toBeInTheDocument(); - }); - - const scheduleButton = screen.getByText('New'); - - act(() => { - fireEvent.click(scheduleButton); + expect(mockFetchChatRoom).toHaveBeenCalledWith(defaultProps.chatRoomId); }); + // Give more time for fetchMeetings to be called await waitFor(() => { - expect(screen.getByTestId('create-meeting-modal')).toBeInTheDocument(); - }); + expect(mockFetchMeetings).toHaveBeenCalled(); + }, { timeout: 3000 }); }); - it('should create a new meeting successfully', async () => { - // Use meetings with no active count to allow modal opening - mockFetchMeetings.mockResolvedValueOnce([mockMeetings[2]]); // Only past meeting - - render(); + it('should fetch saved notes when component loads', async () => { + render(); await waitFor(() => { - expect(screen.queryByText('Loading meetings...')).not.toBeInTheDocument(); - }); - - // Open create modal - const scheduleButton = screen.getByText('New'); - - act(() => { - fireEvent.click(scheduleButton); - }); - - await waitFor(() => { - expect(screen.getByTestId('create-meeting-modal')).toBeInTheDocument(); - }); - - // Submit meeting creation - const createButton = screen.getByTestId('create-meeting-submit'); - fireEvent.click(createButton); - - await waitFor(() => { - expect(mockCreateMeeting).toHaveBeenCalledWith({ - senderId: '6873cc50ac4e1d6e1cddf33f', - receiverId: 'other-user-id', - description: 'Test meeting description', - meetingTime: new Date('2025-07-15T10:00') - }); + expect(mockFetchAllUserMeetingNotes).toHaveBeenCalled(); }); }); + }); - it('should show error when meeting limit is reached', async () => { - // Mock meetings with 2 active meetings - const activeMeetings = [ - { ...mockMeetings[0], state: 'pending' }, - { ...mockMeetings[1], state: 'accepted', meetingTime: '2025-07-30T10:00:00Z' } - ]; - mockFetchMeetings.mockResolvedValueOnce(activeMeetings); - - render(); + describe('Meeting Management', () => { + it('should open create meeting modal when new button is clicked', async () => { + render(); await waitFor(() => { - expect(screen.queryByText('Loading meetings...')).not.toBeInTheDocument(); + expect(screen.getByRole('button', { name: /new/i })).toBeInTheDocument(); }); - - const scheduleButton = screen.getByText('New'); - fireEvent.click(scheduleButton); - await waitFor(() => { - expect(screen.getByTestId('alert')).toBeInTheDocument(); - expect(screen.getByText('Meeting Limit Reached')).toBeInTheDocument(); - }); + fireEvent.click(screen.getByRole('button', { name: /new/i })); + + expect(screen.getByTestId('create-meeting-modal')).toBeInTheDocument(); }); - }); - describe('Meeting Actions', () => { - it('should accept a meeting request', async () => { - render(); + it('should handle meeting creation', async () => { + const newMeeting = { + _id: 'new-meeting-id', + description: 'Test Meeting', + meetingTime: new Date('2025-07-20T14:00:00Z').toISOString(), + state: 'pending', + senderId: 'user1', + receiverId: 'user2' + }; - await waitFor(() => { - expect(screen.queryByText('Loading meetings...')).not.toBeInTheDocument(); - }); + mockCreateMeeting.mockResolvedValue(newMeeting); - // Find and click accept button for pending meeting - const acceptButton = screen.getByText('Accept'); - fireEvent.click(acceptButton); + render(); - // Confirm the action await waitFor(() => { - expect(screen.getByTestId('confirmation-dialog')).toBeInTheDocument(); + fireEvent.click(screen.getByRole('button', { name: /new/i })); }); - const confirmButton = screen.getByTestId('confirmation-confirm'); - fireEvent.click(confirmButton); + fireEvent.click(screen.getByText('Create Meeting')); await waitFor(() => { - expect(mockUpdateMeeting).toHaveBeenCalledWith('meeting-1', 'accept'); + expect(mockCreateMeeting).toHaveBeenCalledWith({ + senderId: 'user1', + receiverId: 'user2', + description: 'Test Meeting', + meetingTime: expect.any(Date) + }); }); }); - it('should decline a meeting request', async () => { - render(); + it('should handle meeting acceptance with confirmation', async () => { + const updatedMeeting = { + ...mockMeetings[0], + state: 'accepted' + }; - await waitFor(() => { - expect(screen.queryByText('Loading meetings...')).not.toBeInTheDocument(); - }); - - const declineButton = screen.getByText('Decline'); - fireEvent.click(declineButton); - - await waitFor(() => { - expect(screen.getByTestId('confirmation-dialog')).toBeInTheDocument(); - expect(screen.getByText('Decline Meeting')).toBeInTheDocument(); - }); + mockUpdateMeeting.mockResolvedValue(updatedMeeting); - const confirmButton = screen.getByTestId('confirmation-confirm'); - fireEvent.click(confirmButton); + render(); await waitFor(() => { - expect(mockUpdateMeeting).toHaveBeenCalledWith('meeting-1', 'reject'); + expect(screen.getByTestId('meeting-list')).toBeInTheDocument(); }); - }); - - it('should cancel a meeting with reason', async () => { - render(); - await waitFor(() => { - expect(screen.queryByText('Loading meetings...')).not.toBeInTheDocument(); - }); - - // Find cancel button (should be on upcoming meeting) - const cancelButton = screen.getByText('Cancel'); - fireEvent.click(cancelButton); + fireEvent.click(screen.getByText('Accept')); - await waitFor(() => { - expect(screen.getByTestId('cancel-meeting-modal')).toBeInTheDocument(); - }); + // Should show confirmation dialog + expect(screen.getByTestId('confirmation-dialog')).toBeInTheDocument(); + expect(screen.getByText('Accept Meeting')).toBeInTheDocument(); - const submitCancelButton = screen.getByTestId('cancel-meeting-submit'); - fireEvent.click(submitCancelButton); + fireEvent.click(screen.getByTestId('confirm-button')); await waitFor(() => { - expect(global.fetch).toHaveBeenCalledWith('/api/meeting/cancel', - expect.objectContaining({ - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: expect.stringContaining('meeting-2') - }) - ); + expect(mockUpdateMeeting).toHaveBeenCalledWith('meeting-1', 'accept'); }); }); - }); - describe('Meeting Navigation', () => { - it('should navigate to meeting room when join button is clicked', async () => { - render(); + it('should handle meeting cancellation', async () => { + const cancelledMeeting = { + ...mockMeetings[1], + state: 'cancelled' + }; - await waitFor(() => { - expect(screen.queryByText('Loading meetings...')).not.toBeInTheDocument(); - }); - - const joinButton = screen.getByText('Join Meeting'); - expect(joinButton).toBeInTheDocument(); - - fireEvent.click(joinButton); + mockCancelMeetingWithReason.mockResolvedValue(cancelledMeeting); - expect(mockPush).toHaveBeenCalledWith('/meeting/meeting-2'); - }); - }); - - describe('Meeting Notes Functionality', () => { - it('should download meeting notes for completed meetings', async () => { - render(); + render(); await waitFor(() => { - expect(screen.queryByText('Loading meetings...')).not.toBeInTheDocument(); + expect(screen.getByTestId('meeting-list')).toBeInTheDocument(); }); - - // Click on past meetings to see download option - const pastMeetingsButton = screen.getByText('Past Meetings (1)'); - fireEvent.click(pastMeetingsButton); - await waitFor(() => { - const downloadButton = screen.getByText('Download Notes'); - fireEvent.click(downloadButton); - }); - - // Verify notes API was called - await waitFor(() => { - expect(global.fetch).toHaveBeenCalledWith( - expect.stringContaining('/api/meeting-notes?meetingId=meeting-3') - ); - }); - }); - }); - - describe('View Toggles', () => { - it('should toggle past meetings view', async () => { - render(); + fireEvent.click(screen.getByText('Cancel')); - await waitFor(() => { - expect(screen.queryByText('Loading meetings...')).not.toBeInTheDocument(); - }); - - const pastMeetingsButton = screen.getByText('Past Meetings (1)'); - fireEvent.click(pastMeetingsButton); + expect(screen.getByTestId('cancel-meeting-modal')).toBeInTheDocument(); - // Should show past meetings section - expect(screen.getByText('Past meeting')).toBeInTheDocument(); - }); - - it('should toggle cancelled meetings view', async () => { - // Add a cancelled meeting to the mock data - const meetingsWithCancelled = [ - ...mockMeetings, - { - _id: 'meeting-4', - senderId: '6873cc50ac4e1d6e1cddf33f', - receiverId: 'other-user-id', - description: 'Cancelled meeting', - meetingTime: '2025-07-18T10:00:00Z', - state: 'cancelled', - acceptStatus: false, - meetingLink: null - } - ]; - mockFetchMeetings.mockResolvedValueOnce(meetingsWithCancelled); - - render(); + fireEvent.click(screen.getByText('Cancel Meeting')); await waitFor(() => { - expect(screen.queryByText('Loading meetings...')).not.toBeInTheDocument(); + expect(mockCancelMeetingWithReason).toHaveBeenCalledWith('meeting-2', 'user1', 'Test cancellation reason'); }); - - const cancelledMeetingsButton = screen.getByText('Cancelled Meetings (1)'); - fireEvent.click(cancelledMeetingsButton); - - expect(screen.getByText('Cancelled meeting')).toBeInTheDocument(); }); }); describe('Error Handling', () => { - it('should handle meeting creation errors', async () => { - mockCreateMeeting.mockRejectedValueOnce(new Error('Failed to create meeting')); - // Use meetings with no active count to allow modal opening - mockFetchMeetings.mockResolvedValueOnce([mockMeetings[2]]); // Only past meeting + it('should show error alert when meeting creation fails', async () => { + mockCreateMeeting.mockRejectedValue(new Error('Failed to create meeting')); - render(); + render(); await waitFor(() => { - expect(screen.queryByText('Loading meetings...')).not.toBeInTheDocument(); + fireEvent.click(screen.getByRole('button', { name: /new/i })); }); - - const scheduleButton = screen.getByText('New'); - act(() => { - fireEvent.click(scheduleButton); - }); - - await waitFor(() => { - expect(screen.getByTestId('create-meeting-modal')).toBeInTheDocument(); - }); - - const createButton = screen.getByTestId('create-meeting-submit'); - fireEvent.click(createButton); + fireEvent.click(screen.getByText('Create Meeting')); await waitFor(() => { - expect(screen.getByTestId('alert')).toBeInTheDocument(); + expect(screen.getByTestId('alert-error')).toBeInTheDocument(); expect(screen.getByText('Failed to create meeting')).toBeInTheDocument(); }); }); + }); - it('should handle meeting update errors', async () => { - mockUpdateMeeting.mockRejectedValueOnce(new Error('Update failed')); - - render(); - - await waitFor(() => { - expect(screen.queryByText('Loading meetings...')).not.toBeInTheDocument(); - }); - - const acceptButton = screen.getByText('Accept'); - fireEvent.click(acceptButton); + describe('Saved Notes', () => { + it('should toggle saved notes section', async () => { + render(); await waitFor(() => { - expect(screen.getByTestId('confirmation-dialog')).toBeInTheDocument(); + expect(screen.getByText(/saved meeting notes/i)).toBeInTheDocument(); }); - const confirmButton = screen.getByTestId('confirmation-confirm'); - fireEvent.click(confirmButton); + const toggleButton = screen.getByText(/saved meeting notes/i); + fireEvent.click(toggleButton); await waitFor(() => { - expect(screen.getByTestId('alert')).toBeInTheDocument(); - expect(screen.getByText('Failed to accept meeting')).toBeInTheDocument(); + expect(screen.getByTestId('saved-notes-list')).toBeInTheDocument(); }); }); }); - describe('Component Cleanup', () => { - it('should call onMeetingUpdate when meetings change', async () => { - render(); + describe('Callback Functions', () => { + it('should call onMeetingUpdate when meetings are loaded', async () => { + render(); await waitFor(() => { - expect(mockProps.onMeetingUpdate).toHaveBeenCalled(); + expect(defaultProps.onMeetingUpdate).toHaveBeenCalled(); }); }); }); - describe('Alert and Confirmation Management', () => { - it('should close alert when close button is clicked', async () => { - mockCreateMeeting.mockRejectedValueOnce(new Error('Test error')); - // Use meetings with no active count to allow modal opening - mockFetchMeetings.mockResolvedValueOnce([mockMeetings[2]]); // Only past meeting - - render(); - - await waitFor(() => { - expect(screen.queryByText('Loading meetings...')).not.toBeInTheDocument(); + describe('Edge Cases', () => { + it('should handle empty meetings list', async () => { + mockFetchMeetings.mockResolvedValue([]); + mockFilterMeetingsByType.mockReturnValue({ + pendingRequests: [], + upcomingMeetings: [], + pastMeetings: [], + cancelledMeetings: [] }); - - // Trigger an error to show alert - const scheduleButton = screen.getByText('New'); - act(() => { - fireEvent.click(scheduleButton); - }); + render(); await waitFor(() => { - expect(screen.getByTestId('create-meeting-modal')).toBeInTheDocument(); + expect(screen.getByTestId('meeting-list')).toBeInTheDocument(); + expect(screen.getByTestId('pending-requests-count')).toHaveTextContent('0'); + expect(screen.getByTestId('upcoming-meetings-count')).toHaveTextContent('0'); }); + }); - const createButton = screen.getByTestId('create-meeting-submit'); - fireEvent.click(createButton); + it('should handle meeting limit restriction', async () => { + mockCheckMeetingLimit.mockReturnValue(2); // At limit - await waitFor(() => { - expect(screen.getByTestId('alert')).toBeInTheDocument(); - }); - - const closeAlertButton = screen.getByTestId('alert-close'); - fireEvent.click(closeAlertButton); + render(); await waitFor(() => { - expect(screen.queryByTestId('alert')).not.toBeInTheDocument(); + fireEvent.click(screen.getByRole('button', { name: /new/i })); }); - }); - - it('should close confirmation dialog when cancel is clicked', async () => { - render(); await waitFor(() => { - expect(screen.queryByText('Loading meetings...')).not.toBeInTheDocument(); + expect(screen.getByTestId('alert-warning')).toBeInTheDocument(); + // The exact text from the component + expect(screen.getByText(/maximum of 2 active meetings/i)).toBeInTheDocument(); }); + }); - const acceptButton = screen.getByText('Accept'); - fireEvent.click(acceptButton); - - await waitFor(() => { - expect(screen.getByTestId('confirmation-dialog')).toBeInTheDocument(); + it('should handle cancellation when meeting cannot be cancelled', async () => { + mockCanCancelMeeting.mockReturnValue({ + canCancel: false, + reason: 'Meeting is too close to start time' }); - const cancelButton = screen.getByTestId('confirmation-cancel'); - fireEvent.click(cancelButton); + render(); await waitFor(() => { - expect(screen.queryByTestId('confirmation-dialog')).not.toBeInTheDocument(); + fireEvent.click(screen.getByText('Cancel')); }); + + expect(screen.getByTestId('alert-warning')).toBeInTheDocument(); + expect(screen.getByText('Meeting is too close to start time')).toBeInTheDocument(); }); }); -}); +}); \ No newline at end of file diff --git a/__tests__/components/SessionBox.test.tsx b/__tests__/components/SessionBox.test.tsx index b0d6880a..6e978068 100644 --- a/__tests__/components/SessionBox.test.tsx +++ b/__tests__/components/SessionBox.test.tsx @@ -6,6 +6,7 @@ import React from 'react'; import { render, screen, fireEvent, waitFor, act } from '@testing-library/react'; import '@testing-library/jest-dom'; import SessionBox from '@/components/messageSystem/SessionBox'; +import { useSessionActions } from '@/hooks/useSessionActions'; // Mock Next.js router const mockPush = jest.fn(); @@ -87,6 +88,11 @@ jest.mock('@/utils/avatarUtils', () => ({ processAvatarUrl: jest.fn((url) => url || '/default-avatar.png'), })); +// Mock the useSessionActions hook +jest.mock('@/hooks/useSessionActions', () => ({ + useSessionActions: jest.fn(), +})); + // Mock data const mockUser = { _id: '6873cc50ac4e1d6e1cddf33f', @@ -110,8 +116,8 @@ const mockSession = { _id: 'session-id-1', user1Id: mockUser, user2Id: mockOtherUser, - skill1Id: { _id: 'skill1', name: 'React' }, - skill2Id: { _id: 'skill2', name: 'Node.js' }, + skill1Id: { _id: 'skill1', skillName: 'React' }, + skill2Id: { _id: 'skill2', skillName: 'Node.js' }, descriptionOfService1: 'I can teach React basics', descriptionOfService2: 'I want to learn Node.js', startDate: '2025-01-15', @@ -197,9 +203,33 @@ describe('SessionBox Component', () => { onSessionUpdate: jest.fn() }; + // Default mock implementation for useSessionActions + const defaultMockSessionActions = { + sessions: [], + counterOffers: {}, + loading: false, + processingSession: null, + pendingSessionCount: 0, + activeSessionCount: 0, + fetchSessions: jest.fn(), + handleAcceptReject: jest.fn(), + handleDeleteSession: jest.fn(), + handleCounterOfferResponse: jest.fn(), + handleRequestCompletion: jest.fn(), + handleCompletionResponse: jest.fn(), + handleRatingSubmit: jest.fn(), + setLoading: jest.fn(), + setSessions: jest.fn(), + setCounterOffers: jest.fn(), + setPendingSessionCount: jest.fn(), + setActiveSessionCount: jest.fn() + }; + beforeEach(() => { jest.clearAllMocks(); global.fetch = createMockFetch({}); + // Reset to default mock implementation + (useSessionActions as jest.MockedFunction).mockReturnValue(defaultMockSessionActions); }); afterEach(() => { @@ -210,6 +240,12 @@ describe('SessionBox Component', () => { it('should show New Session button', async () => { global.fetch = createMockFetch({ sessions: [] }); + // Mock the hook to return empty sessions + (useSessionActions as jest.MockedFunction).mockReturnValue({ + ...defaultMockSessionActions, + sessions: [] + }); + render(); await waitFor(() => { @@ -220,6 +256,12 @@ describe('SessionBox Component', () => { it('should show empty state when no sessions exist', async () => { global.fetch = createMockFetch({ sessions: [] }); + // Mock the hook to return empty sessions + (useSessionActions as jest.MockedFunction).mockReturnValue({ + ...defaultMockSessionActions, + sessions: [] + }); + render(); await waitFor(() => { @@ -236,11 +278,19 @@ describe('SessionBox Component', () => { counterOffers: [] }); + // Mock the hook to return the session + (useSessionActions as jest.MockedFunction).mockReturnValue({ + ...defaultMockSessionActions, + sessions: [mockSession], + pendingSessionCount: 1, + activeSessionCount: 1 + }); + render(); await waitFor(() => { - expect(screen.getByText('I can teach React basics')).toBeInTheDocument(); - expect(screen.getByText('I want to learn Node.js')).toBeInTheDocument(); + expect(screen.getByText('React')).toBeInTheDocument(); + expect(screen.getByText('Node.js')).toBeInTheDocument(); expect(screen.getByText('pending')).toBeInTheDocument(); }); }); @@ -257,6 +307,14 @@ describe('SessionBox Component', () => { counterOffers: [] }); + // Mock the hook to return multiple sessions + (useSessionActions as jest.MockedFunction).mockReturnValue({ + ...defaultMockSessionActions, + sessions: multiplePendingSessions, + pendingSessionCount: 3, + activeSessionCount: 3 + }); + render(); await waitFor(() => { @@ -269,6 +327,12 @@ describe('SessionBox Component', () => { it('should open create session modal when New Session button is clicked', async () => { global.fetch = createMockFetch({ sessions: [] }); + // Mock the hook to return empty sessions + (useSessionActions as jest.MockedFunction).mockReturnValue({ + ...defaultMockSessionActions, + sessions: [] + }); + render(); await waitFor(() => { @@ -291,6 +355,14 @@ describe('SessionBox Component', () => { counterOffers: [] }); + // Mock the hook to return 3 active sessions + (useSessionActions as jest.MockedFunction).mockReturnValue({ + ...defaultMockSessionActions, + sessions: multiplePendingSessions, + pendingSessionCount: 3, + activeSessionCount: 3 + }); + render(); await waitFor(() => { @@ -322,7 +394,7 @@ describe('SessionBox Component', () => { render(); await waitFor(() => { - expect(screen.getByText('Failed to load user information')).toBeInTheDocument(); + expect(screen.getByText('Failed to load user')).toBeInTheDocument(); }); }); @@ -351,6 +423,12 @@ describe('SessionBox Component', () => { it('should close create session modal when close button is clicked', async () => { global.fetch = createMockFetch({ sessions: [] }); + // Mock the hook to return empty sessions + (useSessionActions as jest.MockedFunction).mockReturnValue({ + ...defaultMockSessionActions, + sessions: [] + }); + render(); await waitFor(() => { @@ -374,6 +452,14 @@ describe('SessionBox Component', () => { counterOffers: [] }); + // Mock the hook to return the session + (useSessionActions as jest.MockedFunction).mockReturnValue({ + ...defaultMockSessionActions, + sessions: [mockSession], + pendingSessionCount: 1, + activeSessionCount: 1 + }); + render(); await waitFor(() => { diff --git a/__tests__/components/userDashboard/UserDashboardContent.test.tsx b/__tests__/components/userDashboard/UserDashboardContent.test.tsx new file mode 100644 index 00000000..aa7c3f01 --- /dev/null +++ b/__tests__/components/userDashboard/UserDashboardContent.test.tsx @@ -0,0 +1,89 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import UserDashboardContent from '@/components/User/DashboardContent/UserDashboardContent'; +import { useAuth } from '@/lib/context/AuthContext'; +import { useSessionTimer } from '@/lib/hooks/useSessionTimer'; + + +// Mock child components +jest.mock('@/components/Dashboard/UserSkills', () => { + const MockUserSkills = () =>
; + MockUserSkills.displayName = 'MockUserSkills'; + return MockUserSkills; +}); +jest.mock('@/components/Dashboard/SkillsRequested', () => ({ + SkillsRequested: () =>
, + SkillsOffered: () =>
+})); +jest.mock('@/components/Dashboard/ReviewSummary', () => ({ + ReviewSummary: () =>
+})); +jest.mock('@/components/Dashboard/EarnedBadges', () => { + const MockEarnedBadges = () =>
; + MockEarnedBadges.displayName = 'MockEarnedBadges'; + return MockEarnedBadges; +}); + +jest.mock('@/components/Dashboard/ProfileCard', () => { + const MockProfileCard = () =>
; + MockProfileCard.displayName = 'MockProfileCard'; + return MockProfileCard; +}); +jest.mock('@/components/Dashboard/TimeSpentChart', () => ({ + TimeSpentChart: () =>
+})); +jest.mock('@/components/Dashboard/SkillMatchOverview', () => { + const MockSkillMatchOverview = () =>
; + MockSkillMatchOverview.displayName = 'MockSkillMatchOverview'; + return MockSkillMatchOverview; +}); + +// Mock hooks +jest.mock('@/lib/context/AuthContext', () => ({ + useAuth: jest.fn() +})); +jest.mock('@/lib/hooks/useSessionTimer', () => ({ + useSessionTimer: jest.fn() +})); + +describe('UserDashboardContent', () => { + const mockUser = { + _id: '123', + firstName: 'Samha', + lastName: 'fathima' + }; + + beforeEach(() => { + (useAuth as jest.Mock).mockReturnValue({ user: mockUser }); + (useSessionTimer as jest.Mock).mockReturnValue(null); + }); + + it('renders greeting with user full name', () => { + render( + + ); + + expect(screen.getByText(/Hi Samha fathima, Welcome back!/i)).toBeInTheDocument(); + }); + + it('renders all child components when user is present', () => { + render( + + ); + + expect(screen.getByTestId('UserSkills')).toBeInTheDocument(); + expect(screen.getByTestId('SkillsRequested')).toBeInTheDocument(); + expect(screen.getByTestId('SkillsOffered')).toBeInTheDocument(); + expect(screen.getByTestId('ReviewSummary')).toBeInTheDocument(); + expect(screen.getByTestId('EarnedBadges')).toBeInTheDocument(); + expect(screen.getByTestId('ProfileCard')).toBeInTheDocument(); + expect(screen.getByTestId('TimeSpentChart')).toBeInTheDocument(); + expect(screen.getByTestId('SkillMatchOverview')).toBeInTheDocument(); + }); +}); diff --git a/__tests__/manual/KYCManual.html b/__tests__/manual/KYCManual.html new file mode 100644 index 00000000..70b2bab2 --- /dev/null +++ b/__tests__/manual/KYCManual.html @@ -0,0 +1,211 @@ + + + + + KYC Test Results + + + +

KYC Test Results

+
+

Tester: P. Renulucshmi

+ +

Browser: Chrome

+

Device: desktop

+

Date: 2025-07-17

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#Test NameCategoryPriorityPreconditionsStepsExpected ResultActual ResultStatus
1Upload valid NIC + selfieCREATIONHIGHUser logged in; KYC form visible + 1. Enter full name
2. Enter valid NIC
3. Upload NIC file + (<2MB)
4. Upload selfie-with-NIC
5. Click Submit +
+ New submission appears in Admin KYC list with status “Not Reviewed” + new submission appearsPASS
2Reject blank-field submissionVALIDATIONHIGHKYC page loaded1. Leave all fields empty
2. Click Submit
+ Inline errors under each field (“Full Name is required”, etc.); form + not submitted + please fill out this field appearedPASS
3Reject invalid NIC formatVALIDATIONMEDIUMKYC form visible1. Enter “abc123” in NIC Number
2. Click Submit
+ Validation message “Enter a valid NIC” under NIC field; no + submission + + Red inline error was there until we enter correct format "Enter + either Old NIC (9 digits + V/X) or New NIC (12 digits)" + PASS
4Reject oversize file uploadVALIDATIONMEDIUMKYC form visible1. Select >2MB file for NIC Document
2. Click Submit
Error toast “File must be under 2MB”; input resetsfile must be less than 2MB inline errorPASS
5View pending submissionsFILTERINGLOWAt least one KYC exists1. Navigate to KYC tab
2. Observe table
+ Table lists NIC, Recipient, Date Submitted, Status, Reviewed, + Documents, Accept/Reject + yes all the columns were presentPASS
6Download NIC & selfie filesFUNCTIONALITYMEDIUMKYC list visible1. Click download NIC icon
2. Click download Person icon
Each file downloads with correct name and contentfile downloaded after a clickPASS
7Accept a KYC submissionWORKFLOWHIGHOne “Not Reviewed” row present1. Click green ✔
2. Confirm if prompted
Status → “Accepted”; Reviewed date = todayaccepted as expectedPASS
8Reject a KYC submissionWORKFLOWHIGHOne “Not Reviewed” row present1. Click red ✖
2. Confirm if prompted
Status → “Rejected”; Reviewed date = todayRejected as expectedPASS
9Search by recipient nameFILTERINGLOWMultiple names present1. Type partial name in search boxTable filters to matching Recipient rows-PASS
10Sort by date submittedSORTINGLOWTable visible1. Click Date Submitted header
2. Click again
Rows toggle ascending/descending by Date Submittedyes it works as expectedPASS
11Filter by statusFILTERINGLOWVarious statuses exist1. Open status dropdown
2. Select “Accepted”
Table shows only rows with Status = Acceptedonly showed acccepted recordsPASS
+ + diff --git a/__tests__/manual/ReportingManual.html b/__tests__/manual/ReportingManual.html new file mode 100644 index 00000000..dba4d0b1 --- /dev/null +++ b/__tests__/manual/ReportingManual.html @@ -0,0 +1,170 @@ + + + + + Reporting Test Execution Results + + + + +
+

Reporting Page Test Results

+

Tester: P. Renulucshmi

+

Date: 2025-07-17

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#Test NameCategoryPriorityPreconditionsTest StepsExpected ResultActual ResultStatus
RP01Reporting List RendersVIEWHIGHLogged in as Admin; ≥1 report exists + 1. Navigate to Reporting
+ 2. Wait for table to load +
Table displays all columns and rows correctlyAll reports appeared as expectedPASS
RP02Search ReportsFUNCTIONALITYMEDIUM≥3 reports with distinct data + 1. Enter “Not Following” in search
+ 2. Press Enter +
Only matching rows remain visibleSearch filtered correctlyPASS
RP03Filter by StatusFUNCTIONALITYMEDIUMReports in multiple statuses exist + 1. Open Status dropdown
+ 2. Select “Under Review” +
Only “Under Review” rows remainFilter worked as expectedPASS
RP04Download Report DataUTILITYLOWTable loaded + 1. Click the download (↓) icon on a row + Report data downloads successfullyDownload triggered with correct payloadPASS
RP05Email Reporting UserWORKFLOW–EMAILHIGHA pending report exists + 1. Click ✉️ next to Reporting User
+ 2. Send “Investigating…” email +
Status changes to “Under Review”Email sent; status updatedPASS
RP06Email Reported UserWORKFLOW–EMAILHIGHReport is “Under Review” + 1. Click ✉️ next to Reported User
+ 2. Send “Please provide details” email +
Email confirmation shownEmail sent successfullyPASS
RP07Issue Warning on False ReportWORKFLOW–ACTIONMEDIUMStatus “Under Review” + 1. Click ❌ (reject) icon
+ 2. Choose “Warn Reporter” +
Reporter warned; status = “Resolved – Reporter Warned”Warning email sent; status updatedPASS
RP08Issue Warning to Reported UserWORKFLOW–ACTIONMEDIUMStatus “Under Review” + 1. Click 🛡️ (warn) icon
+ 2. Confirm +
Reported user warned; status = “Resolved – Reported Warned”Warning email sent; status updatedPASS
RP09Resolve ReportWORKFLOW–COMPLETEHIGHAny non-resolved status + 1. Click ✔️ (resolve) icon
+ 2. Confirm +
Status changes to “Resolved”Report marked ResolvedPASS
+ + diff --git a/__tests__/manual/Session-System-Manual-Testing.md b/__tests__/manual/Session-System-Manual-Testing.md deleted file mode 100644 index 9145c88d..00000000 --- a/__tests__/manual/Session-System-Manual-Testing.md +++ /dev/null @@ -1,890 +0,0 @@ -# Session System Manual Testing Guide - -## Overview -This document provides comprehensive manual testing test cases for the complete Session System in the SkillSwap Hub platform. The session system enables users to create, manage, and complete skill-swap sessions with other users. - -## Test Environment Setup -- **Browser:** Chrome, Firefox, Safari, Edge -- **Users:** Minimum 3 test users with different skills -- **Data:** Pre-populated user skills and profiles -- **Network:** Test on different connection speeds - ---- - -## Test Categories - -### 1. Session Creation & Management -### 2. Session Acceptance & Rejection -### 3. Counter Offers System -### 4. Progress Tracking -### 5. Work Submission & Review -### 6. Session Completion Flow -### 7. Session Cancellation -### 8. Reporting System -### 9. UI/UX Components -### 10. Edge Cases & Error Handling - ---- - -## 1. SESSION CREATION & MANAGEMENT - -### TC-SC-001: Create New Session Request -**Priority:** High -**Prerequisites:** -- User A and User B exist with different skills -- User A is logged in -- Users have less than 3 active sessions between them - -**Test Steps:** -1. Navigate to User B's profile or chat -2. Click "New Session" button -3. Select skill you want to learn from User B -4. Select skill you want to offer to User B -5. Enter detailed description of service you'll provide -6. Set start date (today or future) -7. Set expected end date (optional) -8. Click "Create Session Request" - -**Expected Results:** -- Session created with status "pending" -- User B receives notification -- Session appears in both users' session lists -- Session ID generated and stored -- All required fields validated - -**Test Data:** -- Valid user IDs -- Valid skill IDs -- Description: minimum 10 characters -- Start date: today or future -- End date: after start date - ---- - -### TC-SC-002: Session Creation Validation -**Priority:** High -**Prerequisites:** User logged in with skills - -**Test Steps:** -1. Try creating session with missing required fields -2. Try creating session with yourself -3. Try creating session with non-existent user -4. Try creating session with invalid skill IDs -5. Try creating session with past start date -6. Try creating session when already have 3 active sessions - -**Expected Results:** -- Appropriate error messages for each validation -- Form prevents submission with invalid data -- Clear feedback on what needs to be corrected -- Session limit error when at maximum - ---- - -### TC-SC-003: Session List Display -**Priority:** Medium -**Prerequisites:** Multiple sessions exist - -**Test Steps:** -1. Navigate to sessions page -2. Verify all session statuses display correctly -3. Check session sorting (newest first) -4. Verify user and skill information populated -5. Check session action buttons based on status - -**Expected Results:** -- Sessions grouped by status (pending, active, completed, etc.) -- Correct user names and avatars displayed -- Skill titles and descriptions shown -- Appropriate action buttons for each status -- Pagination if many sessions exist - ---- - -## 2. SESSION ACCEPTANCE & REJECTION - -### TC-AR-001: Accept Session Request -**Priority:** High -**Prerequisites:** -- Session exists with status "pending" -- User B (receiver) is logged in - -**Test Steps:** -1. Navigate to session request -2. Review session details -3. Click "Accept" button -4. Confirm acceptance in modal dialog - -**Expected Results:** -- Session status changes to "active" -- Progress tracking created for both users -- Notification sent to requester (User A) -- Session appears in active sessions -- Session workspace becomes accessible - ---- - -### TC-AR-002: Reject Session Request -**Priority:** High -**Prerequisites:** -- Session exists with status "pending" -- User B (receiver) is logged in - -**Test Steps:** -1. Navigate to session request -2. Review session details -3. Click "Reject" button -4. Optionally provide rejection reason -5. Confirm rejection - -**Expected Results:** -- Session status changes to "rejected" -- Rejection timestamp recorded -- Notification sent to requester -- Session appears in rejected sessions -- Rejection reason stored if provided - ---- - -### TC-AR-003: Edit Session Before Acceptance -**Priority:** Medium -**Prerequisites:** -- User A created session -- Session status is "pending" -- User A is logged in - -**Test Steps:** -1. Navigate to pending session -2. Click "Edit" button -3. Modify description or dates -4. Save changes - -**Expected Results:** -- Session updated with new information -- Last modified timestamp updated -- User B sees updated information -- Edit history maintained - ---- - -## 3. COUNTER OFFERS SYSTEM - -### TC-CO-001: Create Counter Offer -**Priority:** Medium -**Prerequisites:** -- Session exists with status "pending" or "active" -- User has permission to create counter offer - -**Test Steps:** -1. Navigate to session details -2. Click "Counter Offer" button -3. Modify offered skill or description -4. Adjust dates if needed -5. Provide reason for counter offer -6. Submit counter offer - -**Expected Results:** -- Counter offer created and linked to session -- Original session status unchanged -- Notification sent to other user -- Counter offer appears in session interface - ---- - -### TC-CO-002: Accept Counter Offer -**Priority:** Medium -**Prerequisites:** Counter offer exists - -**Test Steps:** -1. Navigate to session with counter offer -2. Review counter offer details -3. Click "Accept Counter Offer" -4. Confirm acceptance - -**Expected Results:** -- Original session updated with counter offer terms -- Counter offer marked as accepted -- Session progresses to appropriate status -- Both users notified of acceptance - ---- - -### TC-CO-003: Reject Counter Offer -**Priority:** Medium -**Prerequisites:** Counter offer exists - -**Test Steps:** -1. Navigate to session with counter offer -2. Review counter offer details -3. Click "Reject Counter Offer" -4. Optionally provide reason -5. Confirm rejection - -**Expected Results:** -- Counter offer marked as rejected -- Original session terms remain -- Rejection reason stored -- User notified of rejection - ---- - -## 4. PROGRESS TRACKING - -### TC-PT-001: Update Session Progress -**Priority:** High -**Prerequisites:** -- Active session exists -- User is session participant - -**Test Steps:** -1. Navigate to session workspace -2. Go to Progress tab -3. Update completion percentage (0-100%) -4. Select progress status (not_started, in_progress, completed, blocked) -5. Add progress notes -6. Set or update due date -7. Save progress update - -**Expected Results:** -- Progress saved to database -- Other user can see updated progress -- Progress timeline updated -- Percentage validates (0-100) -- Status reflects actual progress - ---- - -### TC-PT-002: View Progress Timeline -**Priority:** Medium -**Prerequisites:** Session with progress updates - -**Test Steps:** -1. Navigate to session Progress tab -2. View progress history -3. Check timestamps and notes -4. Verify progress by both users displayed - -**Expected Results:** -- Chronological progress timeline -- Both users' progress shown separately -- Clear timestamps for each update -- Progress notes displayed properly - ---- - -### TC-PT-003: Progress Notifications -**Priority:** Medium -**Prerequisites:** Active session with progress tracking - -**Test Steps:** -1. User A updates progress significantly -2. Check if User B receives notification -3. Verify notification content accuracy - -**Expected Results:** -- Notification sent to other user -- Progress percentage included in notification -- Link to session provided in notification - ---- - -## 5. WORK SUBMISSION & REVIEW - -### TC-WS-001: Submit Work -**Priority:** High -**Prerequisites:** -- Active session exists -- User has work to submit - -**Test Steps:** -1. Navigate to session workspace -2. Go to "Submit Work" tab -3. Enter work title and description -4. Upload files (if applicable) -5. Select work type -6. Submit work - -**Expected Results:** -- Work submission created -- Files uploaded successfully -- Other user notified of submission -- Work appears in "View Works" tab -- Submission timestamp recorded - ---- - -### TC-WS-002: File Upload Validation -**Priority:** High -**Prerequisites:** Submit Work tab open - -**Test Steps:** -1. Try uploading different file types -2. Try uploading oversized files -3. Try uploading malicious files -4. Test multiple file uploads - -**Expected Results:** -- Only allowed file types accepted -- File size limits enforced -- Security validation performed -- Multiple files handled correctly -- Clear error messages for invalid files - ---- - -### TC-WS-003: Review Submitted Work -**Priority:** High -**Prerequisites:** Work has been submitted - -**Test Steps:** -1. Navigate to "View Works" tab -2. Select work submission to review -3. Download and view attached files -4. Click "Accept" or "Reject" work -5. Provide review comments -6. Submit review - -**Expected Results:** -- Work details displayed correctly -- Files download properly -- Review options available -- Comments recorded with review -- Submitter notified of review result - ---- - -### TC-WS-004: Work Rejection Workflow -**Priority:** Medium -**Prerequisites:** Work submission exists - -**Test Steps:** -1. Review submitted work -2. Click "Reject" button -3. Provide detailed rejection reason -4. Submit rejection - -**Expected Results:** -- Work marked as rejected -- Rejection reason stored -- Submitter notified with reason -- Work can be resubmitted after fixes - ---- - -## 6. SESSION COMPLETION FLOW - -### TC-CF-001: Request Session Completion -**Priority:** High -**Prerequisites:** -- Active session with substantial progress -- User believes session should be completed - -**Test Steps:** -1. Navigate to session overview -2. Click "Request Completion" button -3. Confirm completion request -4. Optionally add completion notes - -**Expected Results:** -- Completion request created -- Other user notified of request -- Session status updated to show pending completion -- Request timestamp recorded - ---- - -### TC-CF-002: Approve Session Completion -**Priority:** High -**Prerequisites:** Completion request exists - -**Test Steps:** -1. Navigate to session with completion request -2. Review completion request details -3. Click "Approve Completion" -4. Confirm approval - -**Expected Results:** -- Session status changes to "completed" -- Both users receive completion notification -- Rating system becomes available -- Session workspace becomes read-only - ---- - -### TC-CF-003: Reject Completion Request -**Priority:** High -**Prerequisites:** Completion request exists - -**Test Steps:** -1. Navigate to session with completion request -2. Review completion request -3. Click "Reject Completion" -4. Provide rejection reason -5. Submit rejection - -**Expected Results:** -- Completion request rejected -- Session remains active -- Rejection reason provided to requester -- Session can continue - ---- - -### TC-CF-004: Post-Completion Rating -**Priority:** Medium -**Prerequisites:** Session completed - -**Test Steps:** -1. Navigate to completed session -2. Access rating interface -3. Provide rating (1-5 stars) -4. Write detailed review comment -5. Submit rating - -**Expected Results:** -- Rating recorded for other user -- Review comment saved -- Rating affects user's overall rating -- Cannot rate same session twice - ---- - -## 7. SESSION CANCELLATION - -### TC-CAN-001: Cancel Active Session -**Priority:** High -**Prerequisites:** -- Active session exists -- User is session participant - -**Test Steps:** -1. Navigate to active session -2. Click "Cancel Session" option -3. Provide cancellation reason -4. Confirm cancellation - -**Expected Results:** -- Session status changes to "canceled" -- Other user notified of cancellation -- Cancellation reason stored -- Session becomes read-only - ---- - -### TC-CAN-002: Cancel Request Workflow -**Priority:** Medium -**Prerequisites:** Session exists - -**Test Steps:** -1. User A requests session cancellation -2. User B receives cancellation request -3. User B can approve or reject cancellation -4. Test both approval and rejection paths - -**Expected Results:** -- Cancellation request system works -- Both users involved in decision -- Clear communication about cancellation -- Proper status updates - ---- - -## 8. REPORTING SYSTEM - -### TC-REP-001: Report Session Issue -**Priority:** Medium -**Prerequisites:** -- Session exists -- User experienced issue - -**Test Steps:** -1. Navigate to session Report tab -2. Select issue category -3. Provide detailed description -4. Upload evidence files (optional) -5. Submit report - -**Expected Results:** -- Report created and stored -- Admin notification sent -- Report ID generated -- Evidence files uploaded correctly - ---- - -### TC-REP-002: Report Categories -**Priority:** Low -**Prerequisites:** Report tab accessible - -**Test Steps:** -1. Test each report category: - - Inappropriate behavior - - Quality issues - - Communication problems - - Technical issues - - Violation of terms - -**Expected Results:** -- All categories selectable -- Appropriate sub-options for each category -- Relevant guidance text displayed - ---- - -## 9. UI/UX COMPONENTS - -### TC-UI-001: Session Box Component -**Priority:** Medium -**Prerequisites:** Users with sessions - -**Test Steps:** -1. Navigate to chat interface -2. Open session box with another user -3. Test all interactive elements -4. Verify session counter (3 max limit) -5. Test responsive design - -**Expected Results:** -- Session box loads properly -- All buttons functional -- Session limit displayed correctly -- Responsive on different screen sizes -- Performance smooth - ---- - -### TC-UI-002: Session Workspace Tabs -**Priority:** Medium -**Prerequisites:** Active session - -**Test Steps:** -1. Navigate to session workspace -2. Test each tab: - - Overview - - Submit Work - - View Works - - Progress - - Report Issue -3. Verify tab navigation works -4. Check disabled states for completed/canceled sessions - -**Expected Results:** -- All tabs accessible when appropriate -- Tab content loads correctly -- Navigation smooth -- Proper disabling of tabs when session completed/canceled - ---- - -### TC-UI-003: Modal Components -**Priority:** Medium -**Prerequisites:** Various modal-triggering actions - -**Test Steps:** -1. Test each modal: - - Create Session Modal - - Edit Session Modal - - Counter Offer Modal - - Rejection Reason Modal - - Rating Modal -2. Verify modal functionality -3. Test escape key and click-outside closing - -**Expected Results:** -- Modals open and close properly -- Form validation works in modals -- Data persists correctly -- Good user experience - ---- - -### TC-UI-004: Alert and Confirmation Dialogs -**Priority:** Low -**Prerequisites:** Actions that trigger alerts - -**Test Steps:** -1. Trigger various alerts (success, error, warning, info) -2. Test confirmation dialogs -3. Verify auto-close functionality -4. Test manual close - -**Expected Results:** -- Alerts display with correct styling -- Auto-close works for appropriate alerts -- Confirmation dialogs require user action -- Clear and informative messages - ---- - -## 10. EDGE CASES & ERROR HANDLING - -### TC-EC-001: Network Connectivity Issues -**Priority:** Medium -**Prerequisites:** Session system loaded - -**Test Steps:** -1. Disconnect network during session creation -2. Reconnect and retry -3. Test partial form submission with connection loss -4. Verify data recovery mechanisms - -**Expected Results:** -- Graceful handling of network errors -- Clear error messages -- Data not lost on reconnection -- Retry mechanisms work - ---- - -### TC-EC-002: Concurrent User Actions -**Priority:** Medium -**Prerequisites:** Two users in same session - -**Test Steps:** -1. Both users try to accept/reject simultaneously -2. Both users update progress at same time -3. Test work submission conflicts -4. Test completion request timing - -**Expected Results:** -- First action wins, second gets appropriate error -- No data corruption -- Clear conflict resolution -- Proper user feedback - ---- - -### TC-EC-003: Data Validation Edge Cases -**Priority:** Medium -**Prerequisites:** Various form inputs - -**Test Steps:** -1. Test extremely long text inputs -2. Test special characters and emoji -3. Test SQL injection attempts -4. Test XSS attempts -5. Test malformed date inputs - -**Expected Results:** -- Input length limits enforced -- Special characters handled properly -- Security vulnerabilities prevented -- Malformed data rejected gracefully - ---- - -### TC-EC-004: Session Limit Edge Cases -**Priority:** Medium -**Prerequisites:** Users near session limits - -**Test Steps:** -1. Create exactly 3 active sessions between users -2. Try to create 4th session -3. Complete one session and try creating new one -4. Test with different session statuses - -**Expected Results:** -- Limit enforced correctly -- Clear error message when limit reached -- Counter updates when sessions complete -- Different statuses counted correctly - ---- - -### TC-EC-005: User Permission Edge Cases -**Priority:** High -**Prerequisites:** Various user scenarios - -**Test Steps:** -1. Test suspended user creating sessions -2. Test deleted user in existing session -3. Test unauthorized user accessing session -4. Test admin user accessing any session - -**Expected Results:** -- Suspended users blocked appropriately -- Deleted users handled gracefully -- Unauthorized access prevented -- Admin access works where intended - ---- - -### TC-EC-006: Database Consistency -**Priority:** High -**Prerequisites:** Complex session scenarios - -**Test Steps:** -1. Create session and immediately refresh page -2. Test orphaned progress records -3. Test session without required references -4. Verify data migration scenarios - -**Expected Results:** -- Data consistency maintained -- Orphaned records handled -- Required references validated -- Migration scripts work correctly - ---- - -## Performance Testing - -### TC-PERF-001: Load Testing -**Priority:** Medium -**Test Steps:** -1. Load 100+ sessions for single user -2. Test pagination and filtering -3. Measure page load times -4. Test with large file uploads - -**Expected Results:** -- Page loads within 3 seconds -- Pagination handles large datasets -- File uploads complete successfully -- No memory leaks detected - ---- - -## Security Testing - -### TC-SEC-001: Authentication & Authorization -**Priority:** High -**Test Steps:** -1. Access session endpoints without authentication -2. Try accessing other users' sessions -3. Test admin-only functions as regular user -4. Verify JWT token validation - -**Expected Results:** -- All endpoints properly secured -- Authorization checks work correctly -- Admin functions protected -- Token validation prevents access - ---- - -## Browser Compatibility - -### TC-BC-001: Cross-Browser Testing -**Priority:** Medium -**Test Steps:** -1. Test core session functionality in: - - Chrome (latest) - - Firefox (latest) - - Safari (latest) - - Edge (latest) -2. Test responsive design on mobile browsers - -**Expected Results:** -- Consistent functionality across browsers -- UI displays correctly -- Mobile experience optimized -- No JavaScript errors - ---- - -## Data Migration Testing - -### TC-MIG-001: Schema Migrations -**Priority:** High (for production deployments) -**Prerequisites:** Access to migration endpoints - -**Test Steps:** -1. Test session schema migration -2. Test completion data migration -3. Verify data integrity after migration -4. Test rollback procedures - -**Expected Results:** -- Migrations complete successfully -- No data loss during migration -- Schema changes applied correctly -- Rollback works if needed - ---- - -## Accessibility Testing - -### TC-ACC-001: Screen Reader Compatibility -**Priority:** Medium -**Test Steps:** -1. Test with screen reader software -2. Verify keyboard navigation works -3. Check ARIA labels and roles -4. Test high contrast mode - -**Expected Results:** -- Screen readers can navigate interface -- All interactive elements accessible via keyboard -- Proper ARIA labels implemented -- High contrast mode supported - ---- - -## Test Execution Checklist - -### Pre-Testing Setup -- [ ] Test environment configured -- [ ] Test users created with various skill sets -- [ ] Database backup taken -- [ ] Test data prepared -- [ ] Browser dev tools available - -### Test Execution -- [ ] Execute tests in order of priority -- [ ] Document all bugs found -- [ ] Capture screenshots for UI issues -- [ ] Record network requests for API issues -- [ ] Test on different devices/screen sizes - -### Post-Testing -- [ ] Compile bug report -- [ ] Verify critical path functionality -- [ ] Test fixes for reported bugs -- [ ] Update test cases based on findings -- [ ] Clean up test data - ---- - -## Bug Reporting Template - -### Bug Report Format -``` -**Bug ID:** [Unique identifier] -**Test Case:** [Reference to test case] -**Priority:** [High/Medium/Low] -**Severity:** [Critical/Major/Minor] -**Environment:** [Browser, OS, etc.] -**Steps to Reproduce:** -1. -2. -3. - -**Expected Result:** -**Actual Result:** -**Screenshots/Videos:** [If applicable] -**Additional Notes:** -``` - ---- - -## Test Sign-off Criteria - -The session system testing is considered complete when: -- [ ] All High priority test cases pass -- [ ] 95% of Medium priority test cases pass -- [ ] Critical security tests pass -- [ ] Performance tests meet requirements -- [ ] No critical or major bugs remain -- [ ] Cross-browser compatibility verified -- [ ] Mobile responsiveness confirmed -- [ ] Data integrity validated - ---- - -**Document Version:** 1.0 -**Last Updated:** July 16, 2025 -**Prepared By:** Manual Testing Team -**Review Status:** Ready for execution - -This comprehensive test suite covers all aspects of the session system and should be executed thoroughly before any production deployment. Each test case should be executed multiple times under different conditions to ensure robustness and reliability of the session system. diff --git a/__tests__/manual/adminDashboardManual.html b/__tests__/manual/adminDashboardManual.html new file mode 100644 index 00000000..562000b8 --- /dev/null +++ b/__tests__/manual/adminDashboardManual.html @@ -0,0 +1,146 @@ + + + + + Admin Dashboard Results + + + + +

Admin Dashboard Test Results

+

Tester: P. Renulucshmi

+

Date: 2025-07-17

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#Test NameCategoryPriorityPreconditionsTest StepsExpected ResultActual ResultStatus
1Dashboard Cards LoadVIEWHIGHLogged in as Admin/SuperAdmin1. Navigate to /admin/dashboard
2. Wait for page load
All five metric cards appear with correct valuesits loading as expectedPASS
2Cards AccuracyVERIFICATIONHIGHDashboard loaded; known backend data1. Compare card values to API/DB
2. Refresh page
Each card value matches the source of truthit matches with database count as wellPASS
3Registration Chart PlotVISUALIZATIONMEDIUM≥1 registration record exists1. Observe line chart
2. Hover data points
Chart shows daily points; tooltip shows date & count + when hover points in shows no of users registered on a specific day + PASS
4Chart Date Range FilterFUNCTIONALITYMEDIUMDate‑range dropdown visible1. Select Last 7 Days
2. Select All Time
Chart re‑renders to selected rangechart re renders when we change the drop downPASS
5Skill Distribution DonutVISUALIZATIONMEDIUM≥1 skill assignment exists1. Observe donut chart
2. Hover slices
Each slice shows category & %; total sums to 100%each hover shows no of skills in each cateogoryPASS
6Loading SkeletonsUXLOWNetwork throttled1. Throttle to Slow 3G
2. Reload page
Skeleton placeholders displayed until data arrivesuntil data arrives it shows loading signPASS
7Network Calls VerificationDEBUGLOWDevTools open1. Monitor Network tab
2. Reload page
GET /api/dashboard fires once; no 404/500 errors + A single GET /api/dashboard request fired on load (200 OK), followed + by two GET /api/skillLists requests; no 404/500 errors. + PASS
+ + diff --git a/__tests__/manual/adminLoginManual.html b/__tests__/manual/adminLoginManual.html new file mode 100644 index 00000000..f6be63e8 --- /dev/null +++ b/__tests__/manual/adminLoginManual.html @@ -0,0 +1,108 @@ + + + + + Admin Login Test Results + + + + +

Admin Login Test Results

+

Tester: P. Renulucshmi

+

Date: 2025-07-17

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#Test NamePriorityPreconditionsStepsExpectedActualStatus
1Page Load & UI ElementsHIGHBrowser open; Admin login page reachableNavigate to /admin/login
Observe form fields and buttons
Username, Password fields and Login button are visibleyes can view the pagePASS
2Empty Fields ValidationMEDIUMLogin page openLeave both fields blank
Click Login
Inline errors: “Username required” and “Password required”yes validatedPASS
3Invalid CredentialsHIGHLogin page openEnter wrong username/password
Click Login
Error toast: “Invalid credentials”Invalid username or password inline errorPASS
4Successful LoginHIGHValid admin credentialsFill in correct username & password
Click Login
Redirect to /admin/dashboardit redirect to dashboardPASS
5Password Mask ToggleLOWLogin form visibleEnter password
Click show/hide icon
Password toggles between masked and plain textwhen click the toggle password is visiblePASS
+ + diff --git a/__tests__/manual/adminManagementManual.html b/__tests__/manual/adminManagementManual.html new file mode 100644 index 00000000..5fe5cb73 --- /dev/null +++ b/__tests__/manual/adminManagementManual.html @@ -0,0 +1,201 @@ + + + + + Admin Management Results + + + +

Admin Management Test Results

+
+

Tester: P. Renulucshmi

+

Browser: Chrome

+

Device: desktop

+

Date: 2025-07-17

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#Test NameCategoryPriorityPreconditionsTest StepsExpected ResultActual ResultStatus
1View Admin ListVIEWINGMEDIUMLogged in as Admin or Super Admin; Admin Management page open + 1. Navigate to Admin Management
2. Wait for table to load +
+ Table shows Username, Email, Role, Permissions, Created, Actions; ≥1 + row present + table with the all columns showedPASS
2Search by Username or EmailFILTERINGLOWAdmin Mgmt page loaded with ≥2 entries1. Type part of a username or email into search boxOnly matching rows remain visibleyes search box is functioning as expectedPASS
3Filter by RoleFILTERINGLOWMixed Admin & Super Admin rows present1. Select Admin then Super Admin from dropdownTable filters to show only rows for the selected rolefilter show only respected columnPASS
4Edit Admin DetailsUPDATEMEDIUMAt least one row present; Edit icon visible + 1. Click ✏️ on a row
2. Change email or role
3. Click Save +
That row updates to reflect the new email/rolethe row update after editPASS
5Delete Another AdminDELETIONHIGHAnother user’s row exists1. Click 🗑️ on that row
2. Confirm deletion
Row is removed; success message shownsuccessfully deletedPASS
6Prevent Self‑DeletionVALIDATIONHIGHYour own row present1. Attempt to click 🗑️ on your own rowDelete button disabled or error “Cannot delete yourself.”its not allowing to deleted myselfPASS
7Create New Admin (Super only)CREATIONHIGHLogged in as Super Admin; Create Admin button visible + 1. Click Create Admin
2. Fill Username, Email, Password, + Role=Admin, Permissions
3. Click Create Admin +
New admin appears in the table with correct detailsyes superadmin can create new adminPASS
8Deny Access to Admin Mgmt (Admin only)VALIDATIONHIGHLogged in as normal Admin1. Look for Admin Management tab/menu itemNo Admin Management entry is visible to normal Admin + admin admin management tab is not visible. only visible for + superAdmin + PASS
9Validate Create‑FormVALIDATIONMEDIUMCreate Admin modal open + 1. Leave required fields blank or invalid
2. Click Create Admin +
Inline validation errors appear; form not submittedusername ,password ,email validation are includedPASS
10Permission PersistenceFUNCTIONALITYMEDIUMAfter Create or Edit1. Reload Admin Management pageCreated/edited admins & permissions persist correctlyafter reload also its persistedPASS
+ + diff --git a/__tests__/manual/adminSuggestionsManual.html b/__tests__/manual/adminSuggestionsManual.html new file mode 100644 index 00000000..f2f1ea1e --- /dev/null +++ b/__tests__/manual/adminSuggestionsManual.html @@ -0,0 +1,68 @@ + + + + Admin Suggestions Management Test Results + + + + +
+

Admin Suggestions Management - Test Execution Results

+

Tester: Fathima Samha

+

Version: Not specified

+

Browser: Chrome

+

Device: Desktop

+

Test Date: 2025-07-17

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#Test NamePriorityPreconditionsTest StepsExpected ResultActual ResultStatus
1Error StateHIGHAPI returns error1. Simulate API error
2. Load Suggestions page
Error message shownError message displayed: "Failed to load suggestions"PASS
2Empty StateMEDIUMNo suggestions in DB1. Load Suggestions page"No suggestions found" message shownNo suggestions found message displayedPASS
3Search by NameHIGHSuggestions exist1. Enter name in search
2. Observe results
Only matching suggestions shownSearch filters suggestions by name correctlyPASS
4Search by TitleHIGHSuggestions exist1. Enter title in search
2. Observe results
Only matching suggestions shownSearch filters suggestions by title correctlyPASS
5Clear SearchMEDIUMSearch active1. Click clear buttonSearch input cleared, all suggestions shownSearch cleared, all suggestions displayedPASS
6Filter by CategoryMEDIUMMultiple categories exist1. Select category filterOnly suggestions in selected category shownCategory filter worksPASS
7Pagination Next/PrevHIGH>1 page of suggestions1. Click next/prev pageSuggestions list updates to correct pagePagination works, correct page shownPASS
8Pagination Direct PageMEDIUM>5 pages of suggestions1. Click a page numberSuggestions list updates to selected pageDirect page navigation worksPASS
9Approve SuggestionHIGHSuggestions exist1. Click approve on suggestionStatus updates to Approved, toast shownStatus updated, toast shownPASS
10Reject SuggestionHIGHSuggestions exist1. Click reject on suggestionStatus updates to Rejected, toast shownStatus updated, toast shownPASS
11View Suggestion DetailsMEDIUMSuggestions exist1. Click on suggestion row/cardModal opens with suggestion detailsModal opens, details shownPASS
12Close Suggestion ModalMEDIUMModal open1. Click close buttonModal closesModal closedPASS
13Open Summary ModalHIGHSuggestions exist1. Click "View Summary"Summary modal opensSummary modal opensPASS
14Close Summary ModalMEDIUMSummary modal open1. Click close buttonModal closesModal closedPASS
15Summary Modal Error StateHIGHAPI returns error1. Simulate API error
2. Open summary modal
Error message shownError message displayed: "Failed to load summary"PASS
16Summary Modal Empty StateMEDIUMNo pending suggestions1. Open summary modal"No pending suggestions to summarize" shownMessage displayedPASS
17Summary Modal Insights TabHIGHSummary data exists1. Open summary modal
2. View Insights tab
Insights and analysis displayedInsights shownPASS
18Summary Modal Similarity TabHIGHSummary data exists1. Open summary modal
2. View Similarity tab
Similarity groups displayedSimilarity groups shownPASS
19Category Stats in SummaryMEDIUMSummary data exists1. Open summary modal
2. View category breakdown
Category stats shownCategory stats displayedPASS
20Action Recommendations in SummaryMEDIUMSummary data exists1. Open summary modal
2. View recommendations
Recommendations shownRecommendations displayedPASS
+ + + \ No newline at end of file diff --git a/__tests__/manual/adminUsersManual.html b/__tests__/manual/adminUsersManual.html new file mode 100644 index 00000000..810f7253 --- /dev/null +++ b/__tests__/manual/adminUsersManual.html @@ -0,0 +1,64 @@ + + + + Admin Users Management Test Results + + + + +
+

Admin Users Management - Test Execution Results

+

Tester: Fathima Samha

+

Version: Not specified

+

Browser: Chrome

+

Device: Desktop

+

Test Date: 2025-07-17

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#Test NamePriorityPreconditionsTest StepsExpected ResultActual ResultStatus
1Users List LoadsHIGHAdmin logged in1. Navigate to Users pageList of users loads, shows user infoUser list loaded, all info visiblePASS
3Error StateHIGHAPI returns error1. Simulate API error
2. Load Users page
Error message shownError message displayed: "Failed to fetch users"PASS
4Empty StateMEDIUMNo users in DB1. Load Users page"No users found" message shownNo users found message displayedPASS
5Search by NameHIGHUsers exist1. Enter name in search
2. Observe results
Only matching users shownSearch filters users by name correctlyPASS
6Search by EmailHIGHUsers exist1. Enter email in search
2. Observe results
Only matching users shownSearch filters users by email correctlyPASS
7Search by TitleMEDIUMUsers exist1. Enter title in search
2. Observe results
Only matching users shownSearch filters users by title correctlyPASS
8Clear SearchMEDIUMSearch active1. Click clear buttonSearch input cleared, all users shownSearch cleared, all users displayedPASS
9Pagination Next/PrevHIGH>1 page of users1. Click next/prev pageUser list updates to correct pagePagination works, correct page shownPASS
10Pagination Direct PageMEDIUM>5 pages of users1. Click a page numberUser list updates to selected pageDirect page navigation worksPASS
11Change Page SizeMEDIUMUsers exist1. Change page size dropdownUser list updates, correct # per pagePage size changes, correct number shownPASS
12Sort by NameHIGHUsers exist1. Sort by first/last nameList sorted correctlySort by name works as expectedPASS
13Sort by EmailMEDIUMUsers exist1. Sort by emailList sorted correctlySort by email works as expectedPASS
14Sort by Created AtMEDIUMUsers exist1. Sort by created dateList sorted correctlySort by created date worksPASS
15Sort Order ToggleMEDIUMUsers exist1. Toggle sort orderList order reversesSort order toggles as expectedPASS
16Delete User (Soft)HIGHUsers exist1. Click delete on user
2. Confirm in modal
User removed from list, toast shownUser deleted, toast shownPASS
17Cancel DeleteMEDIUMUsers exist1. Click delete
2. Cancel modal
No user deleted, modal closesModal closed, no user deletedPASS
+ + + \ No newline at end of file diff --git a/__tests__/manual/badgeManagerManual.html b/__tests__/manual/badgeManagerManual.html new file mode 100644 index 00000000..02030f71 --- /dev/null +++ b/__tests__/manual/badgeManagerManual.html @@ -0,0 +1,189 @@ + + + + + BadgeManager Results + + + +

BadgeManager Test Results

+
+

Tester: P. Renulucshmi

+ +

Browser: Chrome

+

Device: desktop

+

Date: 2025-07-17

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#Test NameCategoryPriorityPreconditionsTest StepsExpected ResultActual ResultStatus
1Badge Name RequiredADDHIGH“Add New Badge” form visible; all fields empty + 1. Leave Badge Name blank
2. Fill other fields correctly
3. + Click Add Badge +
Inline error “Badge Name is required”; form not submittedBadge name is required inline errorPASS
2Badge Name Min‑Length (≥3 chars)ADDMEDIUM“Add New Badge” form visible + 1. Enter 1–2 chars in Badge Name
2. Fill others correctly
3. + Click Add Badge +
+ Inline error “Name must be at least 3 characters”; submit disabled + inline error Badge name must be at least 3 characters long.PASS
3Description Required & Min‑LengthADDHIGH“Add New Badge” form visible + 1. Leave Description blank or <10 chars
2. Fill other fields + correctly
3. Click Add Badge +
+ Inline error “Description must be at least 10 characters”; form not + submitted + inline error showedPASS
4Image Required & FormatADDHIGH“Add New Badge” form visible1. Leave Badge Image empty
2. Click Add Badge
+ Inline error “Please upload an image” or “Unsupported file format” + + Invalid image type. Please use JPEG, PNG, GIF or WEBP inline error + PASS
5Image Size Limit (≤2 MB)ADDMEDIUM“Add New Badge” form visible1. Upload file >2 MB
2. Click Add Badge
Inline error “Image must be smaller than 2 MB”Image size should be less than 2MB inline errorPASS
6Edit Badge Inline ValidationUPDATEHIGHAt least one badge card present + 1. Click Edit on a badge
2. Clear or shorten Badge + Name/Description +
Same inline errors as BM01–BM03; Save blocked until validinline error showedPASS
7Submit Edit Updates ListUPDATEMEDIUMEdit form open; fields valid1. Modify name or image
2. Click Save
Badge card updates immediately without full reloadits updated without reloading pagePASS
8Delete Badge ConfirmationDELETEMEDIUMAt least one badge card present1. Click Delete on a badge
2. Confirm deletion
+ Confirmation dialog appears; after confirm, badge removed and + success alert shown + Badge deleted successfully! alert shownPASS
+ + diff --git a/__tests__/manual/badgeManual.html b/__tests__/manual/badgeManual.html new file mode 100644 index 00000000..92485fa4 --- /dev/null +++ b/__tests__/manual/badgeManual.html @@ -0,0 +1,117 @@ + + + + + Badges Test Results + + + + +

Badges Test Results

+
+

Tester: P.Renulucshmi

+

Date: 17/07/2025

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#Test NamePriorityPreconditionsTest StepsExpected ResultActual ResultStatus
1Page Load & Default List (BG01)HighUser authenticated; at least 1 badge exists + 1. Navigate to /badges
+ 2. Wait for page load to complete +
All badges rendered as cards; Category dropdown set to “All”yes worked as expectedPass
2Filter by Category (BG02)MediumMultiple badges across categories exist + 1. Select “Achievement Milestone” in Category dropdown
+ 2. Observe the displayed badge list +
Only “Achievement Milestone” badges remain visiblework as expectedPass
+ + diff --git a/__tests__/manual/feedbackManual.html b/__tests__/manual/feedbackManual.html new file mode 100644 index 00000000..c679fdee --- /dev/null +++ b/__tests__/manual/feedbackManual.html @@ -0,0 +1,65 @@ + + + + Feedback Form Test Results + + + + +
+

Feedback Form - Test Execution Results

+

Tester: Fathima Samha

+

Version: Not specified

+

Browser: Chrome

+

Device: Desktop

+

Test Date: 2025-07-17

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#Test NamePriorityPreconditionsTest StepsExpected ResultActual ResultStatus
1Feedback RequiredHIGHOn Feedback form1. Leave Feedback empty
2. Submit
Error: "Feedback must be at least 10 characters long"Error shownPASS
2Feedback Only SpacesHIGHOn Feedback form1. Enter only spaces in Feedback
2. Submit
Error: "Feedback cannot be only spaces"Error shownPASS
3Feedback Not Enough LettersHIGHOn Feedback form1. Enter "1234567890" in Feedback
2. Submit
Error: "Feedback must contain at least 10 letters"Error shownPASS
4Feedback Too ShortHIGHOn Feedback form1. Enter "short" in Feedback
2. Submit
Error: "Feedback must be at least 10 characters long"Error shownPASS
5Valid FeedbackHIGHOn Feedback form1. Enter valid feedback (10+ letters)
2. Submit
Feedback submitted, success message shownSuccess message shownPASS
6Rating RequiredHIGHOn Feedback form1. Deselect all ratings
2. Submit
Error: "Required" or similarError shownPASS
7Rating Min/MaxHIGHOn Feedback form1. Select rating below 1 or above 5 (if possible)
2. Submit
Error: "Rating must be between 1 and 5"Not possible in UIPASS
8Zero RatingHIGHOn Feedback form1. Set rating to 0 (if possible)
2. Submit
Error: "Rating must be between 1 and 5"Error shownFAIL
9Anonymous OptionMEDIUMOn Feedback form1. Check "Submit as anonymous"
2. Submit valid feedback
Feedback submitted as anonymousSuccess, no name shownPASS
10Display Name ValidationMEDIUMOn Feedback form1. Enter "12" as Display Name
2. Submit
Error: "Display name must contain at least 3 letters"Error shownPASS
11Display Name ValidMEDIUMOn Feedback form1. Enter "Samha" as Display Name
2. Submit valid feedback
Feedback submitted, name shownSuccess, name shownPASS
12Success Story OptionalMEDIUMOn Feedback form1. Leave Success Story empty
2. Submit valid feedback
Feedback submitted, no errorSuccessPASS
13Success Story Required When AllowedHIGHOn Feedback form1. Check "Allow to post as success story"
2. Leave Success Story empty
3. Submit
Error: "Success story must contain at least 10 letters"Error shownPASS
14Success Story Not Enough LettersHIGHOn Feedback form1. Check "Allow to post as success story"
2. Enter "1234567890" in Success Story
3. Submit
Error: "Success story must contain at least 10 letters"Error shownPASS
15Valid Success StoryHIGHOn Feedback form1. Check "Allow to post as success story"
2. Enter valid story (10+ letters)
3. Submit
Feedback submitted, success message shownSuccess message shownPASS
16Form Reset After SubmitMEDIUMOn Feedback form1. Submit valid feedback
2. Observe form
Form resets, fields clearedForm resetPASS
17API Error on SubmitMEDIUMOn Feedback form1. Simulate API error
2. Submit valid feedback
Error toast shownError toast shownPASS
+ + + \ No newline at end of file diff --git a/__tests__/manual/meeting_test_results_table_2025-07-17.html b/__tests__/manual/meeting_test_results_table_2025-07-17.html new file mode 100644 index 00000000..38ffc5dd --- /dev/null +++ b/__tests__/manual/meeting_test_results_table_2025-07-17.html @@ -0,0 +1,84 @@ + + + + + Meeting System Test Results + + + +
+

Meeting System Test Execution Results

+

Tester: Adeepa K

+

Version: Not specified

+

Browser: chrome

+

Device: desktop

+

Test Date: 2025-07-17

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#Test NameCategoryPriorityPreconditionsTest StepsExpected ResultActual ResultStatus
1Access Meeting Dashboard - Authenticated UserACCESSHIGHUser has valid account and is logged in1. Navigate to /dashboard
2. Click on 'Meetings' tab
3. Verify meeting interface loads
Meeting dashboard displays with meeting list and controlsPASS
2Access Meeting Dashboard - Unauthenticated UserACCESSHIGHUser is not logged in1. Navigate to /dashboard
2. Attempt to access meetings section
User redirected to login page or shown authentication messagePASS
3Schedule New Meeting - Valid DataCREATIONHIGHUser is logged in and has chat conversation with another user1. Open chat with another user
2. Click 'Meeting' button
3. Click 'Schedule New Meeting'
4. Fill description, future date and time
5. Click 'Schedule Meeting'
Meeting request sent successfully, notification shownDescription is required + +PASS
4Schedule Meeting - Empty DescriptionCREATIONMEDIUMUser is in meeting creation modal1. Leave description field empty
2. Fill date and time
3. Try to submit
Error message: 'Description is required'Description is required + +PASS
5Schedule Meeting - Past DateCREATIONMEDIUMUser is in meeting creation modal1. Fill description
2. Select past date
3. Fill time
4. Try to submit
Error message: 'Meeting date must be in the future'Meeting date must be in the futurePASS
6Schedule Meeting - Missing TimeCREATIONMEDIUMUser is in meeting creation modal1. Fill description
2. Select future date
3. Leave time empty
4. Try to submit
Error message: 'Time is required'PASS
7Meeting Limit ValidationCREATIONHIGHUser already has 2 active meetings with another user1. Try to schedule a 3rd meeting with same user
2. Click 'Schedule Meeting' button
Warning message about maximum 2 active meetings limitPASS
8Accept Meeting RequestMANAGEMENTHIGHUser has received a meeting request1. View pending meeting requests
2. Click 'Accept' on a meeting request
3. Confirm acceptance
Meeting accepted, Daily.co room created, other user notifiedPASS
9Reject Meeting RequestMANAGEMENTHIGHUser has received a meeting request1. View pending meeting requests
2. Click 'Decline' on a meeting request
3. Confirm rejection
Meeting rejected, sender notifiedPASS
10Cancel Scheduled MeetingMANAGEMENTHIGHUser has an accepted/scheduled meeting1. View upcoming meetings
2. Click 'Cancel' on a meeting
3. Provide cancellation reason
4. Confirm cancellation
Meeting cancelled with reason, other user notifiedPASS
11Cancel Meeting - Empty ReasonMANAGEMENTMEDIUMUser is in meeting cancellation modal1. Leave reason field empty
2. Try to cancel meeting
Error message requiring cancellation reasonCant continue with empty reasonPASS
12Join Meeting - Valid TimeVIDEOHIGHUser has accepted meeting within 30 minutes of scheduled time1. Navigate to meeting from dashboard
2. Click 'Join Meeting' button
3. Allow camera/microphone access
Daily.co video interface loads, user enters meeting roomPASS
13Join Meeting - Too EarlyVIDEOMEDIUMUser tries to join meeting more than 30 minutes before scheduled time1. Navigate to meeting page
2. Attempt to join meeting
Message shown that meeting cannot be joined yet with countdown timerAs ExpectedPASS
14Join Meeting - Too LateVIDEOMEDIUMUser tries to join meeting more than 30 minutes after scheduled time1. Navigate to meeting page
2. Attempt to join meeting
Message shown that meeting has endedAs ExpectedPASS
15Join Meeting - Unauthorized UserVIDEOHIGHUser who is not participant tries to access meeting1. Navigate to meeting URL of another user's meeting
2. Attempt to access
Access denied message, redirect to dashboardPASS
16Meeting Video ControlsVIDEOHIGHUser is in active video meeting1. Test mute/unmute audio
2. Test enable/disable video
3. Test leave meeting button
All controls work properly, meeting can be left successfully1.works +2.works +3.worksPASS
17Create Meeting NotesNOTESMEDIUMUser is in completed meeting or viewing past meeting1. Access meeting notes section
2. Write meeting notes
3. Save notes
Notes saved successfully and visible to participantsAs ExpectedPASS
18View Meeting NotesNOTESMEDIUMMeeting has existing notes1. Navigate to past meeting
2. Click on notes icon
3. View notes content
Meeting notes displayed correctly with author and timestampAs ExpectedPASS
19Download Meeting NotesNOTESLOWMeeting has saved notes1. Access meeting notes
2. Click download button
3. Check downloaded file
Notes downloaded as text file with proper formattingAs ExpectedPASS
20Meeting Request NotificationNOTIFICATIONSHIGHUser A sends meeting request to User B1. User A creates meeting request
2. Check User B's notifications
3. Verify notification content
User B receives notification: '[Name] sent you a meeting request'As ExpectedPASS
21Meeting Acceptance NotificationNOTIFICATIONSHIGHUser B accepts User A's meeting request1. User B accepts meeting
2. Check User A's notifications
3. Verify notification content
User A receives notification: '[Name] accepted your meeting request'As ExpectedPASS
22Meeting Rejection NotificationNOTIFICATIONSHIGHUser B rejects User A's meeting request1. User B rejects meeting
2. Check User A's notifications
3. Verify notification content
User A receives notification: '[Name] declined your meeting request'As ExpectedPASS
23Meeting Cancellation NotificationNOTIFICATIONSHIGHUser cancels scheduled meeting1. User cancels meeting with reason
2. Check other participant's notifications
3. Verify notification and reason
Other user receives cancellation notification with reasonAs ExpectedPASS
24Meeting States DisplayUIMEDIUMUser has meetings in different states1. View meeting dashboard
2. Check meeting categorization
3. Verify state indicators
Meetings properly categorized: Pending, Upcoming, Past, CancelledAs ExpectedPASS
25Meeting Time DisplayUIMEDIUMUser has scheduled meetings1. View meeting list
2. Check time formatting
3. Verify timezone handling
Meeting times displayed in user's local timezone with proper formattingAs ExpectedPASS
26Meeting Participant InformationUIMEDIUMUser has meetings with different participants1. View meeting list
2. Check participant names and avatars
3. Verify correct information display
Participant names and avatars displayed correctly for each meetingAs ExpectePASS
27Mobile Meeting InterfaceUIHIGHAccess meeting system on mobile device1. Open meeting dashboard on mobile
2. Test meeting creation
3. Test meeting management
4. Test joining meeting
All meeting features work properly on mobile with responsive designPASS
28Meeting Search FunctionalityUILOWUser has multiple meetings1. Access meeting dashboard
2. Use search to find specific meeting
3. Test different search terms
Search returns relevant meetings based on description or participant namePASS
29Meeting Filter OptionsUILOWUser has meetings in different states1. Access meeting dashboard
2. Test filtering by status
3. Test filtering by date range
Filters work correctly and show appropriate meetingsPASS
30Meeting System PerformanceUIMEDIUMUser has many meetings in system1. Load meeting dashboard
2. Measure loading time
3. Test scrolling through meetings
4. Test meeting actions response time
Meeting system loads quickly and responds promptly to user actionsPASS
+ + \ No newline at end of file diff --git a/__tests__/manual/notification_test_results.html b/__tests__/manual/notification_test_results.html new file mode 100644 index 00000000..ae1da8b1 --- /dev/null +++ b/__tests__/manual/notification_test_results.html @@ -0,0 +1,60 @@ + + + + Notification System Test Results (Simplified) + + + +
+

Notification System Test Execution Results

+

Tester: Adeepa K2

+

Version: Not specified

+

Browser: chrome

+

Device: mobile

+

Test Date: 2025-07-17

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#Test NamePriorityPreconditionsTest StepsExpected ResultActual ResultStatus
1View Notification PageHIGHUser is logged in1. Click on notifications in the menu
2. Look at the page that opens
3. Check if your name appears
4. See if notifications are displayed
Page opens showing 'Hi [Your Name], here are your notifications' and any notifications you haveWorking as ExpectedPASS
2No NotificationsMEDIUMUser has no notifications1. Open notification page
2. Look at what is displayed
Shows friendly message like 'You have no notifications yet' with a bell iconShows CorrectlyPASS
3View Notification ListHIGHUser has some notifications1. Open notification page
2. Look at the notifications
3. Check if unread ones look different from read ones
Unread notifications clearly stand out, read notifications look different, easy to tell them apartEasy to DistinguishPASS
4Notification DetailsHIGHUser has notifications1. Look at individual notifications
2. Check the message text
3. Look at the time when received
4. See the notification type
Each notification shows clear message, readable time, and type badge with appropriate colorAll Details VisiblePASS
5Mark as ReadHIGHUser has unread notifications1. Find an unread notification
2. Click 'Mark Read' button
3. See what happens
Notification moves to read section, looks different, 'Mark Read' button disappearsMoved to Read SectionPASS
6Mark All as ReadHIGHUser has multiple unread notifications1. Click 'Mark all as read' button
2. Watch what happens to all notifications
All notifications move to read section, unread count disappears, button disappearsAll Marked as ReadPASS
7View Notification LinkMEDIUMNotification has a 'View' button1. Find notification with 'View' button
2. Click the 'View' button
3. See where it takes you
Takes you to the related page or content, navigation works smoothlyNavigated CorrectlyPASS
8Receiving New NotificationsHIGHUser is on notification page1. Stay on notification page
2. Have someone trigger a notification for you
3. Watch for new notification to appear
New notification appears at top of unread list, unread count increasesNew Notification AppearedPASS
9Default OrderMEDIUMUser has multiple notifications1. Open notification page
2. Look at notification order
3. Check if newest are at top
Newest notifications appear at top, sort dropdown shows 'Newest First'Newest at TopPASS
10Change Sort OrderMEDIUMUser has multiple notifications1. Click sort dropdown
2. Select 'Oldest First'
3. Watch notifications reorder
Notifications reorder with oldest first, change is clear and immediateReordered SuccessfullyPASS
11Mobile Phone UseHIGHMobile phone1. Open notification page on mobile
2. Try tapping buttons
3. Check if text is readable
4. Test scrolling
Everything fits on screen, buttons easy to tap, text readable, scrolling smoothMobile ResponsivePASS
12Tablet UseMEDIUMTablet device1. Open notification page on tablet
2. Test touch interactions
3. Check layout
Layout looks good, touch interactions work well, good use of spaceTablet CompatiblePASS
13Dark ModeMEDIUMDark mode available1. Enable dark mode
2. Look at notification page
3. Check if everything is visible
All text and elements clearly visible in dark mode, good contrast, looks professionalDark Mode WorkingPASS
14Page SpeedMEDIUMUser with notifications1. Go to notification page
2. See how long it takes to load
3. Test scrolling and clicking
Page loads quickly, scrolling is smooth, buttons respond immediatelyFast LoadingPASS
+ + diff --git a/__tests__/manual/profileSettings.html b/__tests__/manual/profileSettings.html new file mode 100644 index 00000000..dff556f9 --- /dev/null +++ b/__tests__/manual/profileSettings.html @@ -0,0 +1,68 @@ + + + + Profile Settings Test Results + + + + +
+

Profile Settings - Test Execution Results

+

Tester: Fathima Samha

+

Version: Not specified

+

Browser: Chrome

+

Device: Desktop

+

Test Date: 2025-07-17

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#Test NamePriorityPreconditionsTest StepsExpected ResultActual ResultStatus
1Profile Loads for Authenticated UserHIGHUser is logged in1. Navigate to Profile SettingsProfile form loads with user dataForm loaded, data shownPASS
2Edit Profile Button WorksHIGHProfile loaded1. Click "Edit Profile"Fields become editable, Save/Discard buttons appearFields editablePASS
3Cancel Edit Discards ChangesHIGHIn edit mode1. Change a field
2. Click "Cancel"
Changes are not saved, view mode restoredChanges discardedPASS
4Discard Changes ButtonHIGHIn edit mode1. Change a field
2. Click "Discard Changes"
Changes are not saved, view mode restoredChanges discardedPASS
5Save Changes ButtonHIGHIn edit mode1. Change a field
2. Click "Save Changes"
Changes are saved, success message shownChanges saved, message shownPASS
6First Name RequiredHIGHIn edit mode1. Clear First Name
2. Try to save
Browser shows required field errorError shown, cannot savePASS
7Last Name RequiredHIGHIn edit mode1. Clear Last Name
2. Try to save
Browser shows required field errorError shown, cannot savePASS
8Email RequiredHIGHIn edit mode1. Clear Email
2. Try to save
Browser shows required field errorError shown, cannot savePASS
9Email Format ValidationHIGHIn edit mode1. Enter "notanemail" in Email
2. Try to save
Browser shows invalid email errorError shown, cannot savePASS
10Phone OptionalMEDIUMIn edit mode1. Clear Phone
2. Save
Profile saves without phoneSaved, no errorPASS
11Title OptionalMEDIUMIn edit mode1. Clear Title
2. Save
Profile saves without titleSaved, no errorPASS
12Avatar Upload Accepts ImageHIGHIn edit mode1. Click avatar
2. Upload valid image file
Avatar preview updates, can savePreview updates, savedPASS
13Avatar Upload Rejects Non-ImageHIGHIn edit mode1. Try to upload .txt or .pdf fileFile not accepted, no previewFile not acceptedPASS
14Avatar Upload CancelMEDIUMIn edit mode1. Click avatar
2. Cancel file dialog
No change to avatarNo changePASS
15Large Image UploadMEDIUMIn edit mode1. Upload very large imagePreview updates, very slowNot testedNOT EXECUTED
16Save With All Fields ChangedHIGHIn edit mode1. Change all fields
2. Save
All changes saved, message shownAll changes savedPASS
17Save With No ChangesLOWIn edit mode1. Click Save without changing anythingNo error, message shownNo error, message shownPASS
18Network Error on SaveMEDIUMIn edit mode1. Disconnect network
2. Try to save
Error message shownError shownPASS
20Profile Loads With Missing DataLOWUser has missing fields1. Navigate to Profile SettingsFields show "Not provided""Not provided" shownPASS
21Avatar Loads Default If NoneLOWUser has no avatar1. Navigate to Profile SettingsDefault avatar shownDefault shownPASS
+ + + \ No newline at end of file diff --git a/__tests__/manual/session-system-testing-form.html b/__tests__/manual/session-system-testing-form.html deleted file mode 100644 index 7ccda53f..00000000 --- a/__tests__/manual/session-system-testing-form.html +++ /dev/null @@ -1,1349 +0,0 @@ - - - - - - Session System Test Case Execution Form - - - -
-
-

Session System Test Execution

-

Comprehensive manual testing form for Skill Swap Hub session system

-
- -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
- - - - -
- -
-
- -
-
- -
-

Test Execution Summary

-
-
-

Total Tests

-
0
-
-
-

Passed

-
0
-
-
-

Failed

-
0
-
-
-

Blocked

-
0
-
-
-

Not Executed

-
0
-
-
-

Pass Rate

-
0%
-
-
-
-
- - - - diff --git a/__tests__/manual/session_test_results_2024 7 17.html b/__tests__/manual/session_test_results_2024 7 17.html new file mode 100644 index 00000000..28f57704 --- /dev/null +++ b/__tests__/manual/session_test_results_2024 7 17.html @@ -0,0 +1,421 @@ + + + + Session System Test Results - 2025-07-17 + + + +
+

Session System Test Execution Results

+

Tester: Adeepa

+

Version: Not specified

+

Browser: chrome

+

Device: desktop

+

Test Date: 2025-07-17

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#Test NamePriorityPreconditionsTest StepsExpected ResultActual ResultStatus
1Create New Session RequestHIGHUser logged in, has skills available, target user exists1. Navigate to session creation
2. Select skill to offer
3. Select skill to receive
4. Fill session details
5. Submit request
Session created as 'pending', notifications sent, appears in both user listsAs ExpectedPASS
2Session Creation ValidationHIGHUser on session creation form1. Try submitting empty form
2. Enter invalid data
3. Test field validations
Proper error messages, form blocks invalid submissionsAs ExpectedPASS
3Session List DisplayMEDIUMUser has existing sessions1. Navigate to sessions page
2. Check session grouping
3. Verify displayed information
Sessions grouped by status, correct info displayed, proper buttonsAs ExpectedPASS
4Accept Session RequestHIGHPending session request exists1. Open pending session
2. Click accept button
3. Confirm acceptance
Status → 'active', progress created, notifications sentAs ExpectedPASS
5Reject Session RequestHIGHPending session request exists1. Open pending session
2. Click reject button
3. Provide reason
4. Confirm rejection
Status → 'rejected', timestamp recorded, notifications sentReject SuccessfullyPASS
6Edit Session Before AcceptanceMEDIUMPending session exists, user is session creator1. Open pending session
2. Click edit button
3. Modify details
4. Save changes
Session updated, timestamp updated, User B sees changesExpectedPASS
7Create Counter OfferMEDIUMPending session exists, user is recipient1. Open pending session
2. Click counter offer
3. Modify terms
4. Submit counter offer
Counter offer created, linked to session, notifications sentAs ExpectedPASS
8Accept Counter OfferMEDIUMCounter offer exists1. Open counter offer
2. Review terms
3. Click accept
4. Confirm acceptance
Session updated with new terms, counter offer marked acceptedCanPASS
9Reject Counter OfferMEDIUMCounter offer exists1. Open counter offer
2. Review terms
3. Click reject
4. Provide reason
Counter offer rejected, original terms remain, user notifiedAs ExpectedPASS
10Update Session ProgressHIGHActive session exists1. Open active session
2. Go to progress tab
3. Update progress percentage
4. Add notes
5. Save
Progress saved, other user sees updates, timeline updatedAs ExpectedPASS
11View Progress TimelineMEDIUMSession with progress updates exists1. Open session
2. View progress timeline
3. Check chronological order
Chronological timeline, both users shown, clear timestampsNot executedPASS
12Progress NotificationsMEDIUMActive session exists1. Update progress
2. Check other user's notifications
3. Verify notification content
Notification sent with progress percentageWorksPASS
13Submit WorkHIGHActive session exists1. Go to work tab
2. Add work title/description
3. Upload files
4. Submit work
Work created, files uploaded, other user notifiedAs ExpectedPASS
14File Upload ValidationHIGHOn work submission form1. Try uploading large files
2. Try unsupported formats
3. Upload multiple files
4. Test file limits
Only allowed types accepted, size limits enforced100MB Max Up to 5 FilesPASS
15Review Submitted WorkHIGHWork has been submitted1. Open submitted work
2. Download files
3. Review content
4. Accept/reject work
Work displayed correctly, files download, review recordedCan ReviewPASS
16Work Rejection WorkflowMEDIUMWork submitted and reviewed1. Open work item
2. Click reject
3. Provide feedback
4. Submit rejection
Work rejected, reason stored, submitter notifiedAs ExpectedPASS
17Request Session CompletionHIGHActive session with sufficient progress1. Open session overview
2. Click request completion
3. Review work summary
4. Confirm request
Completion request created, other user notifiedAs ExpectedPASS
18Approve Session CompletionHIGHCompletion request exists1. Open completion request
2. Review session work
3. Click approve
4. Submit review/rating
Status → 'completed', notifications sent, rating availableAs ExpectedPASS
19Reject Completion RequestHIGHCompletion request exists1. Open completion request
2. Click reject
3. Provide reason
4. Submit rejection
Request rejected, session remains active, reason providedAs ExpectedPASS
20Post-Completion RatingMEDIUMSession completed1. Open completed session
2. Click review button
3. Rate experience (1-5 stars)
4. Add comments
5. Submit
Rating recorded, affects user's overall ratingAs ExpectedPASS
21Cancel Active SessionHIGHActive session exists1. Open session
2. Click cancel session
3. Select reason
4. Confirm cancellation
Status → 'canceled', other user notified, reason storedAs ExpectedPASS
22Cancel Request WorkflowMEDIUMActive session exists1. Request cancellation
2. Other user responds
3. Check communication flow
Request system works, both users involved, clear communicationAs ExpectedPASS
23Report Session IssueMEDIUMSession exists (any status)1. Open session
2. Click report issue
3. Select category
4. Describe issue
5. Submit
Report created, admin notified, ID generatedAs ExpectedPASS
24Report CategoriesLOWOn report form1. Check available categories
2. Test sub-options
3. Verify guidance text
All categories selectable, sub-options available, guidance shownAs ExpectedPASS
25Session Box ComponentMEDIUMUser has sessions1. Open session box
2. Test all buttons
3. Check responsiveness
4. Verify session limit display
Box loads, buttons work, limit shown, responsiveAs ExpectedPASS
26Session Workspace TabsMEDIUMActive session open1. Navigate between tabs
2. Check content loading
3. Test tab switching
All tabs work, content loads, navigation smoothSmoothPASS
27Modal ComponentsMEDIUMVarious modals available1. Open different modals
2. Test form validation
3. Check data persistence
4. Test close/cancel
Modals open/close properly, validation works, data persistsWorksPASS
28Alert and Confirmation DialogsLOWActions that trigger alerts1. Perform actions
2. Check alert display
3. Test auto-close
4. Verify message clarity
Alerts display correctly, auto-close works, clear messagesAlerts are WorkingPass
29Network Connectivity IssuesMEDIUMStable connection initially1. Simulate network loss
2. Test data recovery
3. Check error handling
Graceful error handling, data recovery worksCould not tryBLOCKED
30Concurrent User ActionsMEDIUMTwo users in same session1. Both users perform same action
2. Check conflict resolution
3. Verify data integrity
First action wins, clear error for second, no corruptionUp to 2 users triedBLOCKED
31Data Validation Edge CasesMEDIUMForms available for testing1. Test input limits
2. Try special characters
3. Test security measures
4. Check date validation
Limits enforced, special chars handled, security protectedDate Validation, Backdate preventionPASS
32Session Limit Edge CasesMEDIUMUser near session limit1. Create sessions up to limit
2. Try creating beyond limit
3. Check error handling
4. Verify counter updates
Limit enforced, clear error, counter updates correctlyCannot Create 4thPASS
33User Permission Edge CasesHIGHVarious user states available1. Test suspended user actions
2. Test deleted user handling
3. Check unauthorized access
Suspended users blocked, deleted handled gracefully, unauthorized preventedHandled in AuthPASS
+ +
+

Test Execution Summary

+

Total Test Cases: 33

+

Passed: 30

+

Failed: 0

+

Blocked: 2

+

Not Executed: 0

+

Pass Rate: 91%

+
+ + diff --git a/__tests__/manual/suspendedUserManual.html b/__tests__/manual/suspendedUserManual.html new file mode 100644 index 00000000..ce16bcd8 --- /dev/null +++ b/__tests__/manual/suspendedUserManual.html @@ -0,0 +1,129 @@ + + + + + Suspended Users Test Results + + + +

Suspended Users Test Results

+

Tester: P.Renlucshmi

+

Date: 2025-07-17

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#Test NamePriorityPreconditionsStepsExpected ResultExec DateActual ResultStatus
SU01Suspend a UserHighUser exists; Admin logged in + 1. Go to Users
+ 2. Click “Suspend”
+ 3. Enter reason
+ 4. Confirm +
User moves to Suspended list2025‑07‑17User moved from Users to Suspended UsersPass
SU02Search Suspended UsersMedium≥1 suspended user + 1. Open Suspended Users
+ 2. Type search +
Table filters to matching rows2025‑07‑17Search worksPass
SU03Prevent Suspended LoginHighUser is suspended1. Attempt loginLogin blocked with suspend message2025‑07‑17User blocked from loginPass
SU04Prevent Re‑registrationMediumEmail suspended1. Sign up with same emailRegistration rejected: Email in use2025‑07‑17Cannot create account with same emailPass
SU05Unsuspend a UserHighUser in Suspended list + 1. Click ✓
+ 2. Confirm +
User moves back to Users list2025‑07‑17User unsuspended and can log in againPass
SU06Reason ValidationMediumSuspend dialog open1. Click Confirm without reasonError: Reason is required2025‑07‑17User isn’t suspended without a reasonPass
+ + diff --git a/__tests__/manual/userDashoard.html b/__tests__/manual/userDashoard.html new file mode 100644 index 00000000..f64a5a6b --- /dev/null +++ b/__tests__/manual/userDashoard.html @@ -0,0 +1,178 @@ + + + + User Dashboard Test Results + + + + +
+

User Dashboard - Test Execution Results

+

Tester: Fathima Samha

+

Version: Not specified

+

Browser: Chrome

+

Device: Desktop

+

Test Date: 2025-07-17

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#Test NamePriorityPreconditionsTest StepsExpected ResultActual ResultStatus
1Dashboard Loads for Authenticated UserHIGHUser is logged in1. Navigate to /dashboardDashboard greets user by name and loads contentLoaded with "Hi Fathima Samhanpm run , Welcome back!"PASS
2ProfileCard Component RendersHIGHUser has valid userId1. Check right sidebar
2. Confirm profile card is visible
Profile card with user data appearsProfile shownPASS
3SkillsRequested Section RendersHIGHUser is logged in1. Scroll to main column
2. Confirm "Skills Requested" section shows
SkillsRequested component renders with dataSection displayedPASS
4SkillsOffered Section RendersHIGHUser is logged in1. Locate "Skills Offered" sectionSkillsOffered component is visible and styledSection rendered as expectedPASS
5UserSkills Component View MoreMEDIUMUser on dashboard1. Click "View More" in UserSkills component`onNavigateToMySkills` handler is triggeredNavigation triggeredPASS
6ReviewSummary Shows When User ExistsHIGHUser is logged in1. Scroll to Review section
2. Check if ReviewSummary is rendered
ReviewSummary visible with review statsComponent visiblePASS
7EarnedBadges Shows When User ExistsMEDIUMUser is logged in1. Scroll down to "Badges"Badges with earned info should be visibleBadges loadedPASS
8TimeSpentChart Component LoadsHIGHUser is logged in1. Locate "Time Spent" box
2. Confirm chart loads
Chart rendered with user statsChart loadedPASS
9SkillMatchOverview WorksMEDIUMUser is on dashboard1. Scroll to Skill Matches
2. Verify component renders
Component renders with "View All" hookRendered with no crashPASS
10Session Timer Hook Runs Without CrashMEDIUMUser has valid _id1. Load dashboard
2. Open dev tools console
No hook errors, timer starts silentlyNo errorsPASS
11“View All Reviews” Button AppearsMEDIUMUser has more than 3 reviews + 1. Navigate to Dashboard
+ 2. Scroll to Reviews section
+ 3. Observe review count
+ 4. Check if “View all reviews” button appears +
Button appears only if reviews > 3“View all 4 reviews →” button shownPASS
12Navigate to All Reviews PageMEDIUM“View all reviews” button is visible + 1. Click “View all 4 reviews →”
+ 2. Observe navigation
+ 3. Confirm all reviews are visible on target page +
User is taken to full reviews pageNavigated to `/reviews` and saw all reviewsPASS
+ + + \ No newline at end of file diff --git a/__tests__/manual/userSuggestions.html b/__tests__/manual/userSuggestions.html new file mode 100644 index 00000000..7f807c17 --- /dev/null +++ b/__tests__/manual/userSuggestions.html @@ -0,0 +1,341 @@ + + + + User Suggestions Test Results + + + + +
+

User Suggestions - Test Execution Results

+

Tester: Fathima Samha

+

Version: Not specified

+

Browser: Chrome

+

Device: Desktop

+

Test Date: 2025-07-17

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#Test NamePriorityPreconditionsTest StepsExpected ResultActual ResultStatus
1Suggestions Tab LoadsHIGHUser is logged in1. Navigate to Dashboard
2. Go to Suggestions section/tab
Suggestions UI loads with "Submit Suggestion" and "Your History" tabsTabs loaded as expectedPASS
2Suggestion Form ValidationHIGHUser is on Suggestions tab1. Leave all fields empty
2. Click Submit
Validation errors for all fieldsAll validation errors shownPASS
3Title ValidationHIGHUser is on Suggestions tab1. Enter less than 3 letters in Title
2. Fill other fields validly
3. Submit
Error: "Title must be at least 3 characters after trimming"Error message shownPASS
4Description ValidationHIGHUser is on Suggestions tab1. Enter less than 10 letters in Description
2. Fill other fields validly
3. Submit
Error: "Description must be at least 10 characters after trimming"Error message shownPASS
5Category ValidationHIGHUser is on Suggestions tab1. Leave Category unselected
2. Fill other fields validly
3. Submit
Error: "Please select a category"Error message shownPASS
6aAll Fields EmptyHIGHOn Suggestions tab1. Leave all fields empty
2. Click Submit
Errors for Title, Description, CategoryAll validation errors shownPASS
6bTitle Too ShortHIGHOn Suggestions tab1. Enter "Hi" in Title
2. Fill other fields validly
3. Submit
Error: "Title must be at least 3 characters after trimming"Error message shownPASS
6cTitle Not Enough LettersHIGHOn Suggestions tab1. Enter "12@" in Title
2. Fill other fields validly
3. Submit
Error: "Title must contain at least 3 letters"Error message shownPASS
6dDescription Too ShortHIGHOn Suggestions tab1. Enter "Short" in Description
2. Fill other fields validly
3. Submit
Error: "Description must be at least 10 characters after trimming"Error message shownPASS
6eDescription Not Enough LettersHIGHOn Suggestions tab1. Enter "1234567890" in Description
2. Fill other fields validly
3. Submit
Error: "Description must contain at least 10 letters"Error message shownPASS
6fCategory Not SelectedHIGHOn Suggestions tab1. Fill Title and Description validly
2. Leave Category blank
3. Submit
Error: "Please select a category"Error message shownPASS
6gValid Input - IssueHIGHOn Suggestions tab1. Enter valid Title and Description
2. Select "Issue" as Category
3. Submit
Suggestion submitted, form clears, no errorsSuggestion submitted, form clearedPASS
6hValid Input - SuggestionHIGHOn Suggestions tab1. Enter valid Title and Description
2. Select "Suggestion" as Category
3. Submit
Suggestion submitted, form clears, no errorsSuggestion submitted, form clearedPASS
6iValid Input - Feature RequestHIGHOn Suggestions tab1. Enter valid Title and Description
2. Select "Feature Request" as Category
3. Submit
Suggestion submitted, form clears, no errorsSuggestion submitted, form clearedPASS
6jValid Input - OtherHIGHOn Suggestions tab1. Enter valid Title and Description
2. Select "Other" as Category
3. Submit
Suggestion submitted, form clears, no errorsSuggestion submitted, form clearedPASS
6kLeading/Trailing SpacesMEDIUMOn Suggestions tab1. Enter " Valid Title " and " Valid Description "
2. Select any Category
3. Submit
Suggestion submitted, form clears, no errorsSuggestion submitted, form clearedPASS
6lSpecial Characters in TitleMEDIUMOn Suggestions tab1. Enter "Hello!@#" in Title
2. Valid Description and Category
3. Submit
Suggestion submitted if at least 3 lettersSuggestion submittedPASS
6mSpecial Characters in DescriptionMEDIUMOn Suggestions tab1. Enter valid Title
2. Enter "This is a test!@#" in Description
3. Valid Category
4. Submit
Suggestion submitted if at least 10 lettersSuggestion submittedPASS
6nTitle: 123@gh (Not Enough Letters)HIGHOn Suggestions tab1. Enter "123@gh" in Title
2. Valid Description and Category
3. Submit
Error: "Title must contain at least 3 letters"Error message shownPASS
6oTitle: 123@bug (Enough Letters)HIGHOn Suggestions tab1. Enter "123@bug" in Title
2. Valid Description and Category
3. Submit
No error, suggestion submittedSuggestion submittedPASS
6pDescription: 1234567@gh (Not Enough Letters)HIGHOn Suggestions tab1. Enter valid Title
2. Enter "1234567@gh" in Description
3. Valid Category
4. Submit
Error: "Description must contain at least 10 letters"Error message shownPASS
6qDescription: 1234567@ghijklmnopqrst (Enough Letters)HIGHOn Suggestions tab1. Enter valid Title
2. Enter "1234567@ghijkl" in Description
3. Valid Category
4. Submit
No error, suggestion submittedSuggestion submittedPASS
7Submit Valid SuggestionHIGHUser is on Suggestions tab1. Fill all fields validly
2. Submit
Suggestion is submitted, form clears, history tab updatesSuggestion submitted, history updatedPASS
8Suggestion Appears in HistoryHIGHUser has submitted a suggestion1. Switch to "Your History" tabSubmitted suggestion appears as a card with correct title, description, category, and statusCard shown with correct infoPASS
9Category & Status Badges RenderMEDIUMUser has suggestions in history1. View suggestion cards in historyEach card shows colored badges for category and statusBadges rendered as expectedPASS
10Filter Suggestions by StatusMEDIUMUser has multiple suggestions with different statuses1. Use status filter dropdown
2. Select "Pending", "Approved", "Rejected"
Only suggestions with selected status are shownFilter works for all statusesPASS
11Filter Suggestions by CategoryMEDIUMUser has suggestions in multiple categories1. Use category filter dropdown
2. Select a category
Only suggestions in selected category are shownCategory filter worksPASS
12Feedback Prompt AppearsLOWUser is on Suggestions tab1. Observe top of Suggestions sectionFeedback prompt with "Give Feedback" button is visiblePrompt shownPASS
13Feedback Prompt DismissLOWFeedback prompt is visible1. Click "×" on feedback promptPrompt disappearsPrompt dismissedPASS
+ + + \ No newline at end of file diff --git a/__tests__/pages/SessionPage.test..tsx b/__tests__/pages/SessionPage.test..tsx deleted file mode 100644 index bfd96483..00000000 --- a/__tests__/pages/SessionPage.test..tsx +++ /dev/null @@ -1,1655 +0,0 @@ -/** - * Session Workspace Page Tests - * Tests the session workspace functionality including work submission, progress tracking, and reviews - */ - -import React from 'react'; -import { render, screen, fireEvent, waitFor, act } from '@testing-library/react'; -import '@testing-library/jest-dom'; -import SessionWorkspace from '@/app/session/[sessionId]/page'; - -// Mock Next.js hooks -const mockPush = jest.fn(); -const mockParams = { sessionId: 'test-session-id' }; - -jest.mock('next/navigation', () => ({ - useParams: () => mockParams, - useRouter: () => ({ - push: mockPush, - refresh: jest.fn() - }) -})); - -// Mock auth context -const mockUser = { - _id: 'test-user-id', - firstName: 'John', - lastName: 'Doe', - email: 'john@example.com' -}; - -jest.mock('@/lib/context/AuthContext', () => ({ - useAuth: () => ({ - user: mockUser, - loading: false, - error: null - }) -})); - -// Mock completion status utility -jest.mock('@/utils/sessionCompletion', () => ({ - getSessionCompletionStatus: jest.fn(() => Promise.resolve({ - canRequestCompletion: true, - hasRequestedCompletion: false, - needsToApprove: false, - wasRejected: false, - isCompleted: false, - pendingRequests: [] - })) -})); - -// Mock Alert component -jest.mock('@/components/ui/Alert', () => { - return function MockAlert({ type, title, message, isOpen, onClose }: any) { - if (!isOpen) return null; - return ( -
- {title &&
{title}
} - {message &&
{message}
} - -
- ); - }; -}); - -// Mock ConfirmationDialog component -jest.mock('@/components/ui/ConfirmationDialog', () => { - return function MockConfirmationDialog({ - isOpen, - onClose, - onConfirm, - title, - message, - type, - confirmText, - loading - }: any) { - if (!isOpen) return null; - return ( -
-
{title}
-
{message}
-
{type}
- - -
- ); - }; -}); - -// Mock tab components -jest.mock('@/components/sessionTabs/OverviewTab', () => { - return function MockOverviewTab({ session, myProgress, otherProgress, otherUser }: any) { - return ( -
-
Session: {session?.descriptionOfService1}
-
My Progress: {myProgress?.completionPercentage}%
-
Other Progress: {otherProgress?.completionPercentage}%
-
Other User: {otherUser?.firstName}
-
- ); - }; -}); - -jest.mock('@/components/sessionTabs/SubmitWorkTab', () => { - return function MockSubmitWorkTab({ onSubmit, loading }: any) { - const handleSubmit = (e: any) => { - e.preventDefault(); - if (onSubmit) { - onSubmit(e); - } - }; - - return ( -
-
- {}} - /> - -
-
- ); - }; -}); - -jest.mock('@/components/sessionTabs/ViewWorksTab', () => { - return function MockViewWorksTab({ works, onReview, onDownload }: any) { - const handleReview = (workId: string, action: string) => { - if (onReview) { - onReview(workId, action, 'Test review message'); - } - }; - - return ( -
- {works?.map((work: any) => ( -
-
{work.workDescription}
- - - {work.workFiles?.map((file: any, index: number) => ( - - ))} -
- )) ||
No works
} -
- ); - }; -}); - -jest.mock('@/components/sessionTabs/ProgressTab', () => { - return function MockProgressTab({ - myProgress, - otherProgress, - onUpdate, - onComplete, - completionStatus - }: any) { - return ( -
-
My Progress: {myProgress?.completionPercentage}%
- - {completionStatus?.canRequestCompletion && ( - - )} - {completionStatus?.needsToApprove && ( -
Approval Needed
- )} -
- ); - }; -}); - -jest.mock('@/components/sessionTabs/ReportTab', () => { - return function MockReportTab({ onSubmit, loading, existingReports }: any) { - return ( -
-
- -