diff --git a/src/screens/EventManagement/EventManagement.spec.tsx b/src/screens/EventManagement/EventManagement.spec.tsx new file mode 100644 index 0000000000..fdc8b42ee2 --- /dev/null +++ b/src/screens/EventManagement/EventManagement.spec.tsx @@ -0,0 +1,252 @@ +import React, { act } from 'react'; +import type { RenderResult } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; +import i18nForTest from 'utils/i18nForTest'; +import { MemoryRouter, Route, Routes, useParams } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import EventManagement from './EventManagement'; +import userEvent from '@testing-library/user-event'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { MOCKS_WITH_TIME } from 'components/EventManagement/Dashboard/EventDashboard.mocks'; +import useLocalStorage from 'utils/useLocalstorage'; +import { vi } from 'vitest'; +const { setItem } = useLocalStorage(); + +const mockWithTime = new StaticMockLink(MOCKS_WITH_TIME, true); + +const renderEventManagement = (): RenderResult => { + return render( + + + + + + } + /> + paramsError} + /> + eventsScreen} + /> + userEventsScreen + } + /> + + + + + , + ); +}; + +describe('Event Management', () => { + beforeAll(() => { + vi.mock('react-router-dom', async () => { + const actual = await vi.importActual('react-router-dom'); + return { + ...actual, + useParams: vi.fn(), + }; + }); + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('Navigation Tests', () => { + beforeEach(() => { + vi.mocked(useParams).mockReturnValue({ + orgId: 'orgId', + eventId: 'eventId', + }); + }); + + it('Testing back button navigation when userType is SuperAdmin', async () => { + setItem('SuperAdmin', true); + renderEventManagement(); + + const backButton = screen.getByTestId('backBtn'); + userEvent.click(backButton); + await waitFor(() => { + const eventsScreen = screen.getByTestId('eventsScreen'); + expect(eventsScreen).toBeInTheDocument(); + }); + }); + + it('Testing back button navigation when userType is USER', async () => { + setItem('SuperAdmin', false); + setItem('AdminFor', []); + + renderEventManagement(); + + const backButton = screen.getByTestId('backBtn'); + userEvent.click(backButton); + + await waitFor(() => { + const userEventsScreen = screen.getByTestId('userEventsScreen'); + expect(userEventsScreen).toBeInTheDocument(); + }); + }); + + it('Testing back button navigation when userType is ADMIN', async () => { + setItem('SuperAdmin', false); + setItem('AdminFor', ['someOrg']); + + renderEventManagement(); + + const backButton = screen.getByTestId('backBtn'); + userEvent.click(backButton); + + await waitFor(() => { + const eventsScreen = screen.getByTestId('eventsScreen'); + expect(eventsScreen).toBeInTheDocument(); + }); + }); + it('redirects to orglist when params are missing', async () => { + vi.mocked(useParams).mockReturnValue({}); + + renderEventManagement(); + + await waitFor(() => { + const paramsError = screen.getByTestId('paramsError'); + expect(paramsError).toBeInTheDocument(); + }); + }); + }); + + describe('Tab Management Tests', () => { + beforeEach(() => { + vi.mocked(useParams).mockReturnValue({ + orgId: 'orgId', + eventId: 'event123', + }); + }); + + it('renders dashboard tab by default', async () => { + renderEventManagement(); + expect(screen.getByTestId('eventDashboardTab')).toBeInTheDocument(); + }); + + it('switches between all available tabs', async () => { + renderEventManagement(); + + const tabsToTest = [ + { button: 'registrantsBtn', tab: 'eventRegistrantsTab' }, + { button: 'attendanceBtn', tab: 'eventAttendanceTab' }, + { button: 'actionsBtn', tab: 'eventActionsTab' }, + { button: 'agendasBtn', tab: 'eventAgendasTab' }, + { button: 'statisticsBtn', tab: 'eventStatsTab' }, + { button: 'volunteersBtn', tab: 'eventVolunteersTab' }, + ]; + + for (const { button, tab } of tabsToTest) { + userEvent.click(screen.getByTestId(button)); + expect(screen.getByTestId(tab)).toBeInTheDocument(); + } + }); + + it('returns null for an invalid tab', async () => { + const setTab = vi.fn(); + const useStateSpy = vi.spyOn(React, 'useState'); + useStateSpy.mockReturnValueOnce(['invalid', setTab]); + await act(async () => { + renderEventManagement(); + }); + + expect(screen.queryByTestId('eventDashboardTab')).toBeInTheDocument(); + expect( + screen.queryByTestId('eventRegistrantsTab'), + ).not.toBeInTheDocument(); + expect( + screen.queryByTestId('eventAttendanceTab'), + ).not.toBeInTheDocument(); + expect(screen.queryByTestId('eventActionsTab')).not.toBeInTheDocument(); + expect( + screen.queryByTestId('eventVolunteersTab'), + ).not.toBeInTheDocument(); + expect(screen.queryByTestId('eventAgendasTab')).not.toBeInTheDocument(); + expect(screen.queryByTestId('eventStatsTab')).not.toBeInTheDocument(); + }); + }); + + describe('Responsive Dropdown Tests', () => { + beforeEach(() => { + vi.mocked(useParams).mockReturnValue({ + orgId: 'orgId', + eventId: 'event123', + }); + }); + + it('renders dropdown with all options', async () => { + await act(async () => { + renderEventManagement(); + }); + + const dropdownContainer = screen.getByTestId('tabsDropdownContainer'); + expect(dropdownContainer).toBeInTheDocument(); + + await act(async () => { + userEvent.click(screen.getByTestId('tabsDropdownToggle')); + }); + + const tabOptions = [ + 'dashboard', + 'registrants', + 'attendance', + 'agendas', + 'actions', + 'volunteers', + 'statistics', + ]; + + tabOptions.forEach((option) => { + expect(screen.getByTestId(`${option}DropdownItem`)).toBeInTheDocument(); + }); + }); + + it('switches tabs through dropdown selection', async () => { + await act(async () => { + renderEventManagement(); + }); + await act(async () => { + userEvent.click(screen.getByTestId('tabsDropdownToggle')); + }); + + const tabOptions = [ + 'dashboard', + 'registrants', + 'attendance', + 'agendas', + 'actions', + 'volunteers', + 'statistics', + ]; + + for (const option of tabOptions) { + act(() => { + userEvent.click(screen.getByTestId(`${option}DropdownItem`)); + }); + + expect(screen.getByTestId(`${option}DropdownItem`)).toHaveClass( + 'text-secondary', + ); + } + }); + }); +}); diff --git a/src/screens/EventManagement/EventManagement.test.tsx b/src/screens/EventManagement/EventManagement.test.tsx deleted file mode 100644 index a119caad42..0000000000 --- a/src/screens/EventManagement/EventManagement.test.tsx +++ /dev/null @@ -1,143 +0,0 @@ -import React from 'react'; -import type { RenderResult } from '@testing-library/react'; -import { render, screen, waitFor } from '@testing-library/react'; -import { MockedProvider } from '@apollo/react-testing'; -import { I18nextProvider } from 'react-i18next'; -import i18nForTest from 'utils/i18nForTest'; -import { MemoryRouter, Route, Routes } from 'react-router-dom'; -import { Provider } from 'react-redux'; -import { store } from 'state/store'; -import EventManagement from './EventManagement'; -import userEvent from '@testing-library/user-event'; -import { StaticMockLink } from 'utils/StaticMockLink'; -import { MOCKS_WITH_TIME } from 'components/EventManagement/Dashboard/EventDashboard.mocks'; -import useLocalStorage from 'utils/useLocalstorage'; -const { setItem } = useLocalStorage(); - -const mockWithTime = new StaticMockLink(MOCKS_WITH_TIME, true); - -const renderEventManagement = (): RenderResult => { - return render( - - - - - - } - /> - paramsError} - /> - eventsScreen} - /> - userEventsScreen - } - /> - - - - - , - ); -}; - -describe('Event Management', () => { - beforeAll(() => { - jest.mock('react-router-dom', () => ({ - ...jest.requireActual('react-router-dom'), - useParams: () => ({ orgId: 'orgId', eventId: 'eventId' }), - })); - }); - - afterAll(() => { - jest.clearAllMocks(); - }); - - test('Testing back button navigation when userType is SuperAdmin', async () => { - setItem('SuperAdmin', true); - renderEventManagement(); - - const backButton = screen.getByTestId('backBtn'); - userEvent.click(backButton); - await waitFor(() => { - const eventsScreen = screen.getByTestId('eventsScreen'); - expect(eventsScreen).toBeInTheDocument(); - }); - }); - - test('Testing event management tab switching', async () => { - renderEventManagement(); - - const registrantsButton = screen.getByTestId('registrantsBtn'); - userEvent.click(registrantsButton); - - const registrantsTab = screen.getByTestId('eventRegistrantsTab'); - expect(registrantsTab).toBeInTheDocument(); - const eventAttendanceButton = screen.getByTestId('attendanceBtn'); - userEvent.click(eventAttendanceButton); - const eventAttendanceTab = screen.getByTestId('eventAttendanceTab'); - expect(eventAttendanceTab).toBeInTheDocument(); - const eventActionsButton = screen.getByTestId('actionsBtn'); - userEvent.click(eventActionsButton); - - const eventActionsTab = screen.getByTestId('eventActionsTab'); - expect(eventActionsTab).toBeInTheDocument(); - - const eventAgendasButton = screen.getByTestId('agendasBtn'); - userEvent.click(eventAgendasButton); - - const eventAgendasTab = screen.getByTestId('eventAgendasTab'); - expect(eventAgendasTab).toBeInTheDocument(); - - const eventStatsButton = screen.getByTestId('statisticsBtn'); - userEvent.click(eventStatsButton); - - const eventStatsTab = screen.getByTestId('eventStatsTab'); - expect(eventStatsTab).toBeInTheDocument(); - - const volunteerButton = screen.getByTestId('volunteersBtn'); - userEvent.click(volunteerButton); - - const eventVolunteersTab = screen.getByTestId('eventVolunteersTab'); - expect(eventVolunteersTab).toBeInTheDocument(); - }); - test('renders nothing when invalid tab is selected', () => { - render( - - - - - - } - /> - - - - - , - ); - - // Force an invalid tab state - const setTab = jest.fn(); - React.useState = jest.fn().mockReturnValue(['invalidTab', setTab]); - - // Verify nothing is rendered - expect(screen.queryByTestId('eventDashboardTab')).toBeInTheDocument(); - expect(screen.queryByTestId('eventRegistrantsTab')).not.toBeInTheDocument(); - expect(screen.queryByTestId('eventAttendanceTab')).not.toBeInTheDocument(); - expect(screen.queryByTestId('eventActionsTab')).not.toBeInTheDocument(); - expect(screen.queryByTestId('eventVolunteersTab')).not.toBeInTheDocument(); - expect(screen.queryByTestId('eventAgendasTab')).not.toBeInTheDocument(); - expect(screen.queryByTestId('eventStatsTab')).not.toBeInTheDocument(); - }); -}); diff --git a/src/screens/EventManagement/EventManagement.tsx b/src/screens/EventManagement/EventManagement.tsx index e355ac1acc..84707071bf 100644 --- a/src/screens/EventManagement/EventManagement.tsx +++ b/src/screens/EventManagement/EventManagement.tsx @@ -100,7 +100,6 @@ const EventManagement = (): JSX.Element => { // Determine user role based on local storage const superAdmin = getItem('SuperAdmin'); const adminFor = getItem('AdminFor'); - /*istanbul ignore next*/ const userRole = superAdmin ? 'SUPERADMIN' : adminFor?.length > 0 @@ -109,7 +108,6 @@ const EventManagement = (): JSX.Element => { // Extract event and organization IDs from URL parameters const { eventId, orgId } = useParams(); - /*istanbul ignore next*/ if (!eventId || !orgId) { // Redirect if event ID or organization ID is missing return ; @@ -159,7 +157,6 @@ const EventManagement = (): JSX.Element => { }; const handleBack = (): void => { - /*istanbul ignore next*/ if (userRole === 'USER') { navigate(`/user/events/${orgId}`); } else { @@ -203,11 +200,9 @@ const EventManagement = (): JSX.Element => { {eventDashboardTabs.map(({ value, icon }, index) => ( setTab(value) - } + onClick={() => setTab(value)} className={`d-flex gap-2 ${tab === value ? 'text-secondary' : ''}`} + data-testid={`${value}DropdownItem`} > {icon} {t(value)} @@ -272,10 +267,9 @@ const EventManagement = (): JSX.Element => {

Statistics

); - /*istanbul ignore next*/ - default: - /*istanbul ignore next*/ - return null; + // no use of default here as the default tab is the dashboard selected in useState + // default: + // return null; } })()}