Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/(main)/league/[leagueId]/entry/Entries.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { ILeague, INFLTeam, IUser } from '@/api/apiFunctions.interface';
export interface IEntry {
$id: string;
name: string;
user: IUser;
league: ILeague;
user: IUser['id'];
league: ILeague['leagueId'];
selectedTeams: INFLTeam[];
eliminated: boolean;
}
Expand Down
169 changes: 142 additions & 27 deletions app/(main)/league/all/page.test.tsx
Original file line number Diff line number Diff line change
@@ -1,68 +1,183 @@
import { render, screen, waitFor } from '@testing-library/react';
import Leagues from './page';
import { useDataStore } from '@/store/dataStore';
import { getUserLeagues } from '@/utils/utils';
import { getGameWeek } from '@/api/apiFunctions';
import { getUserLeagues, cn } from '@/utils/utils';
import { getGameWeek, getCurrentUserEntries } from '@/api/apiFunctions';

jest.mock('@/store/dataStore', () => ({
useDataStore: jest.fn(() => ({ user: { id: '123', leagues: [] } })),
useDataStore: jest.fn(),
}));

jest.mock('@/utils/utils', () => ({
getUserLeagues: jest.fn(() => Promise.resolve([])),
getUserLeagues: jest.fn(),
cn: jest.fn(),
}));

jest.mock('@/api/apiFunctions', () => ({
getGameWeek: jest.fn(() =>
Promise.resolve({
week: 1,
}),
),
getGameWeek: jest.fn(),
getCurrentUserEntries: jest.fn(),
}));

const mockLeagues = [
{
leagueId: '123',
leagueName: 'Test League',
logo: 'https://findmylogo.com/logo.png',
participants: ['123456', '78'],
survivors: ['123456', '78', '9'],
},
];

const mockEntries = [
{
$id: '123',
name: 'Test Entry',
user: '123',
league: '123',
selectedTeams: [],
eliminated: false,
},
];

const mockGameWeek = {
id: '123',
week: 1,
};

const mockUseDataStore = useDataStore as jest.MockedFunction<
typeof useDataStore
>;
const mockGetUserLeagues = getUserLeagues as jest.MockedFunction<
typeof getUserLeagues
>;
const mockGetGameWeek = getGameWeek as jest.MockedFunction<typeof getGameWeek>;
const mockGetCurrentUserEntries = getCurrentUserEntries as jest.MockedFunction<
typeof getCurrentUserEntries
>;

describe('Leagues Component', () => {
const mockUseDataStore = useDataStore as unknown as jest.Mock;
const mockGetUserLeagues = getUserLeagues as jest.Mock;
const mockGetGameWeek = getGameWeek as jest.Mock;
const mockUpdateLeagues = jest.fn();
const mockUpdateGameWeek = jest.fn();
const mockUpdateEntries = jest.fn();
const mockCn = cn as jest.MockedFunction<typeof cn>;

beforeEach(() => {
jest.clearAllMocks();
mockUseDataStore.mockReturnValue({
user: { id: '123', leagues: [] },
leagues: [],
updateLeagues: mockUpdateLeagues,
updateGameWeek: mockUpdateGameWeek,
updateEntries: mockUpdateEntries,
});
});

test('should display GlobalSpinner while loading data', async () => {
render(<Leagues />);

expect(screen.getByTestId('global-spinner')).toBeInTheDocument();

await waitFor(() => {
expect(mockGetUserLeagues).toHaveBeenCalled();
});
});

test('should render "You are not enrolled in any leagues" message when no leagues are found', async () => {
mockUseDataStore.mockReturnValueOnce({ user: { id: '123', leagues: [] } });
mockGetUserLeagues.mockResolvedValueOnce([]);
mockGetGameWeek.mockResolvedValueOnce({ week: 1 });
mockGetUserLeagues.mockResolvedValue([]);

render(<Leagues />);

await waitFor(() => {
expect(
screen.getByText('You are not enrolled in any leagues'),
).toBeInTheDocument();
expect(mockGetUserLeagues).toHaveBeenCalled();
});

expect(
screen.getByText('You are not enrolled in any leagues'),
).toBeInTheDocument();
});

test('should display GlobalSpinner while loading data', async () => {
mockUseDataStore.mockReturnValueOnce({ user: { id: '123', leagues: [] } });
mockGetUserLeagues.mockResolvedValueOnce([]);
mockGetGameWeek.mockResolvedValueOnce({ week: 1 });
test('should not call getGameWeek or getCurrentUserEntries if no leagues are found', async () => {
mockGetUserLeagues.mockResolvedValue([]);

render(<Leagues />);

await waitFor(() => {
expect(screen.getByTestId('global-spinner')).toBeInTheDocument();
expect(mockGetUserLeagues).toHaveBeenCalled();
expect(mockGetGameWeek).not.toHaveBeenCalled();
expect(mockGetCurrentUserEntries).not.toHaveBeenCalled();
});
});

test('should not display GlobalSpinner after loading data', async () => {
mockUseDataStore.mockReturnValueOnce({ user: { id: '123', leagues: [] } });
mockGetUserLeagues.mockResolvedValueOnce([]);
mockGetGameWeek.mockResolvedValueOnce({ week: 1 });
mockUseDataStore.mockReturnValue({
user: { id: '123', leagues: ['123'] },
leagues: mockLeagues,
updateLeagues: mockUpdateLeagues,
updateGameWeek: mockUpdateGameWeek,
updateEntries: mockUpdateEntries,
});
mockGetUserLeagues.mockResolvedValue(mockLeagues);
mockGetGameWeek.mockResolvedValue(mockGameWeek);
mockGetCurrentUserEntries.mockResolvedValue(mockEntries);

render(<Leagues />);

expect(screen.getByTestId('global-spinner')).toBeInTheDocument();

await waitFor(() => {
expect(screen.queryByTestId('global-spinner')).not.toBeInTheDocument();
expect(mockGetUserLeagues).toHaveBeenCalled();
expect(mockGetGameWeek).toHaveBeenCalled();
expect(mockGetCurrentUserEntries).toHaveBeenCalled();
});

expect(screen.queryByTestId('global-spinner')).not.toBeInTheDocument();
});
test('should display "Test League" when leagues are found', async () => {
mockUseDataStore.mockReturnValue({
user: { id: '123', leagues: ['123'] },
leagues: mockLeagues,
updateLeagues: mockUpdateLeagues,
updateGameWeek: mockUpdateGameWeek,
updateEntries: mockUpdateEntries,
});
mockGetUserLeagues.mockResolvedValue(mockLeagues);
mockGetGameWeek.mockResolvedValue(mockGameWeek);
mockGetCurrentUserEntries.mockResolvedValue(mockEntries);

render(<Leagues />);

await waitFor(() => {
expect(mockGetUserLeagues).toHaveBeenCalled();
expect(mockGetGameWeek).toHaveBeenCalled();
expect(mockGetCurrentUserEntries).toHaveBeenCalled();
});

expect(mockUpdateGameWeek).toHaveBeenCalledWith(mockGameWeek);
expect(mockUpdateEntries).toHaveBeenCalledWith(mockEntries);

expect(screen.getByText('Test League')).toBeInTheDocument();
});
test('should call getGameWeek and getCurrentUserEntries if leagues are found', async () => {
mockUseDataStore.mockReturnValue({
user: { id: '123', leagues: ['123'] },
leagues: mockLeagues,
updateLeagues: mockUpdateLeagues,
updateGameWeek: mockUpdateGameWeek,
updateEntries: mockUpdateEntries,
});
mockGetUserLeagues.mockResolvedValue(mockLeagues);
mockGetGameWeek.mockResolvedValue(mockGameWeek);
mockGetCurrentUserEntries.mockResolvedValue(mockEntries);

render(<Leagues />);

await waitFor(() => {
expect(mockGetUserLeagues).toHaveBeenCalled();
expect(mockGetGameWeek).toHaveBeenCalled();
expect(mockGetCurrentUserEntries).toHaveBeenCalled();
});

expect(mockUpdateGameWeek).toHaveBeenCalledWith(mockGameWeek);
expect(mockUpdateEntries).toHaveBeenCalledWith(mockEntries);
});
});
37 changes: 33 additions & 4 deletions app/(main)/league/all/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@

import { ENTRY_URL, LEAGUE_URL } from '@/const/global';
import { getUserLeagues } from '@/utils/utils';
import { ILeague } from '@/api/apiFunctions.interface';
import { LeagueCard } from '@/components/LeagueCard/LeagueCard';
import { useDataStore } from '@/store/dataStore';
import GlobalSpinner from '@/components/GlobalSpinner/GlobalSpinner';
import React, { JSX, useEffect, useState } from 'react';
import { getCurrentUserEntries, getGameWeek } from '@/api/apiFunctions';

/**
* Renders the leagues component.
* @returns {JSX.Element} The rendered leagues component.
*/
const Leagues = (): JSX.Element => {
const [leagues, setLeagues] = useState<ILeague[]>([]);
const [loadingData, setLoadingData] = useState<boolean>(true);
const { user } = useDataStore((state) => state);
const { user, leagues, updateLeagues, updateGameWeek, updateEntries } =
useDataStore((state) => state);

/**
* Fetches the user's leagues.
Expand All @@ -27,14 +27,37 @@ const Leagues = (): JSX.Element => {
const getLeagues = async (): Promise<void> => {
try {
const userLeagues = await getUserLeagues(user.leagues);
setLeagues(userLeagues);
updateLeagues(userLeagues);
} catch (error) {
throw new Error('Error fetching user leagues');
} finally {
setLoadingData(false);
}
};

/**
* Fetches entries per league and the current week.
* @returns {Promise<void>}
*/
const fetchAdditionalUserData = async (): Promise<void> => {
try {
const entryPromises = leagues.map((league) =>
getCurrentUserEntries(user.id, league.leagueId),
);
const gameWeekPromise = getGameWeek();

const [entries, currentWeek] = await Promise.all([
Promise.all(entryPromises),
gameWeekPromise,
]);

updateEntries(entries.flat());
updateGameWeek(currentWeek);
} catch (error) {
throw new Error('Error fetching entries and game week');
}
};

useEffect(() => {
if (!user.id || user.id === '') {
return;
Expand All @@ -43,6 +66,12 @@ const Leagues = (): JSX.Element => {
getLeagues();
}, [user]);

useEffect(() => {
if (leagues.length > 0) {
fetchAdditionalUserData();
}
}, [leagues]);

return (
<div className="Leagues mx-auto max-w-3xl pt-10">
{loadingData ? (
Expand Down
63 changes: 45 additions & 18 deletions store/dataStore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,26 @@ const NFLTeam = [
},
];

const league = {
leagueId: '123',
leagueName: 'Test League',
logo: 'https://findmylogo.com/logo.png',
participants: ['123456', '78'],
survivors: ['123456', '78', '9'],
};
const league = [
{
leagueId: '123',
leagueName: 'Test League',
logo: 'https://findmylogo.com/logo.png',
participants: ['123456', '78'],
survivors: ['123456', '78', '9'],
},
];

const entries = [
{
$id: '123',
name: 'Test Entry',
user: '123',
league: '123',
selectedTeams: [],
eliminated: false,
},
];

const gameCurrentWeek = {
id: '1234567890',
Expand Down Expand Up @@ -130,24 +143,38 @@ describe('Data Store', () => {
describe('League Test', () => {
it('Check the default league state', () => {
const { result } = renderHook(() => useDataStore());
expect(result.current.league.leagueId).toBe('');
expect(result.current.league.leagueName).toBe('');
expect(result.current.league.logo).toBe('');
expect(result.current.league.participants).toStrictEqual([]);
expect(result.current.league.survivors).toStrictEqual([]);
expect(result.current.leagues).toStrictEqual([]);
});
it('Check the updated league state', () => {
const { result } = renderHook(() => useDataStore());

act(() => {
result.current.updateLeague(league);
result.current.updateLeagues(league);
});

expect(result.current.leagues[0].leagueId).toBe(league[0].leagueId);
expect(result.current.leagues[0].leagueName).toBe(league[0].leagueName);
expect(result.current.leagues[0].logo).toBe(league[0].logo);
expect(result.current.leagues[0].participants).toBe(
league[0].participants,
);
expect(result.current.leagues[0].survivors).toBe(league[0].survivors);
});
});

describe('Entries Test', () => {
it('Check the default entries state', () => {
const { result } = renderHook(() => useDataStore());
expect(result.current.entries).toStrictEqual([]);
});
it('Check the updated entries state', () => {
const { result } = renderHook(() => useDataStore());

act(() => {
result.current.updateEntries(entries);
});

expect(result.current.league.leagueId).toBe(league.leagueId);
expect(result.current.league.leagueName).toBe(league.leagueName);
expect(result.current.league.logo).toBe(league.logo);
expect(result.current.league.participants).toBe(league.participants);
expect(result.current.league.survivors).toBe(league.survivors);
expect(result.current.entries).toStrictEqual(entries);
});
});

Expand Down
Loading