Skip to content
Draft
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
839f515
upgrade apollo 3.14 -> 4
rudransh-shrivastava Aug 25, 2025
5e68e09
run initial apollo client codemod
rudransh-shrivastava Aug 25, 2025
6b2e8a4
remove @client and @defer codemod codeblocks
rudransh-shrivastava Aug 25, 2025
b175fb9
format and lint code
rudransh-shrivastava Aug 27, 2025
9215da4
Merge branch 'main' into refactor/migrate-apollo-3-to-4t
rudransh-shrivastava Sep 3, 2025
b8a110c
replace queries with typed-document-node
rudransh-shrivastava Sep 3, 2025
8d7ccec
Merge branch 'main' into refactor/migrate-apollo-3-to-4
rudransh-shrivastava Sep 21, 2025
e50807c
revert type changes
rudransh-shrivastava Sep 21, 2025
4706816
revert type changes
rudransh-shrivastava Sep 21, 2025
3e70433
Create and use fragments in About page
rudransh-shrivastava Sep 21, 2025
0637a84
Create and use fragments in Chapter pages
rudransh-shrivastava Sep 21, 2025
ee6352d
Revert "Create and use fragments in Chapter pages"
rudransh-shrivastava Sep 22, 2025
14348ca
Revert "Create and use fragments in About page"
rudransh-shrivastava Sep 22, 2025
98858fc
change types to match generated graphql schema types make types optio…
rudransh-shrivastava Sep 22, 2025
2b52229
revert as string type casts
rudransh-shrivastava Sep 22, 2025
32da88b
fix tests by updating imports
rudransh-shrivastava Sep 23, 2025
04081e9
fix tests by updating queries, dates, imports
rudransh-shrivastava Sep 23, 2025
75ab358
Merge branch 'main' into refactor/migrate-apollo-3-to-4
rudransh-shrivastava Sep 23, 2025
28b7fa8
update enums, address CR comments
rudransh-shrivastava Sep 23, 2025
7c4fbb4
Merge branch 'main' into refactor/migrate-apollo-3-to-4
rudransh-shrivastava Sep 29, 2025
66b6d67
resolve TODO comments
rudransh-shrivastava Sep 29, 2025
99c45bf
update code
rudransh-shrivastava Sep 29, 2025
a728eb2
replace remaining queries with typed-document-node
rudransh-shrivastava Sep 29, 2025
61a817c
Merge branch 'main' into refactor/migrate-apollo-3-to-4
rudransh-shrivastava Sep 30, 2025
f7c05eb
replace upperFirst with capitalize
rudransh-shrivastava Sep 30, 2025
483477b
remove gql imports and cleanup tests
rudransh-shrivastava Oct 1, 2025
5350382
Merge branch 'main' into refactor/migrate-apollo-3-to-4
rudransh-shrivastava Oct 1, 2025
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
7 changes: 4 additions & 3 deletions frontend/__tests__/unit/components/ProgramActions.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { fireEvent, screen } from '@testing-library/react'
import '@testing-library/jest-dom'
import { useSession as mockUseSession } from 'next-auth/react'
import { render } from 'wrappers/testUtil'
import { ProgramStatusEnum } from 'types/__generated__/graphql'
import ProgramActions from 'components/ProgramActions'

const mockPush = jest.fn()
Expand Down Expand Up @@ -65,7 +66,7 @@ describe('ProgramActions', () => {
const button = screen.getByTestId('program-actions-button')
fireEvent.click(button)
fireEvent.click(screen.getByRole('menuitem', { name: /publish program/i }))
expect(setStatus).toHaveBeenCalledWith('PUBLISHED')
expect(setStatus).toHaveBeenCalledWith(ProgramStatusEnum.Published)
expect(mockPush).not.toHaveBeenCalled()
})

Expand All @@ -74,15 +75,15 @@ describe('ProgramActions', () => {
const button = screen.getByTestId('program-actions-button')
fireEvent.click(button)
fireEvent.click(screen.getByRole('menuitem', { name: /move to draft/i }))
expect(setStatus).toHaveBeenCalledWith('DRAFT')
expect(setStatus).toHaveBeenCalledWith(ProgramStatusEnum.Draft)
})

test('handles Mark as Completed action', () => {
render(<ProgramActions status="PUBLISHED" setStatus={setStatus} />)
const button = screen.getByTestId('program-actions-button')
fireEvent.click(button)
fireEvent.click(screen.getByRole('menuitem', { name: /mark as completed/i }))
expect(setStatus).toHaveBeenCalledWith('COMPLETED')
expect(setStatus).toHaveBeenCalledWith(ProgramStatusEnum.Completed)
})

test('dropdown closes on outside click', () => {
Expand Down
6 changes: 3 additions & 3 deletions frontend/__tests__/unit/components/ProgramCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { faEye } from '@fortawesome/free-regular-svg-icons'
import { faEdit } from '@fortawesome/free-solid-svg-icons'
import { fireEvent, render, screen } from '@testing-library/react'
import React from 'react'
import { ProgramStatusEnum } from 'types/__generated__/graphql'
import type { Program } from 'types/mentorship'
import { ProgramStatusEnum } from 'types/mentorship'
import ProgramCard from 'components/ProgramCard'

jest.mock('@fortawesome/react-fontawesome', () => ({
Expand Down Expand Up @@ -33,7 +33,7 @@ describe('ProgramCard', () => {
key: 'test-program',
name: 'Test Program',
description: 'This is a test program description',
status: ProgramStatusEnum.PUBLISHED,
status: ProgramStatusEnum.Published,
startedAt: '2024-01-01T00:00:00Z',
endedAt: '2024-12-31T23:59:59Z',
userRole: 'admin',
Expand Down Expand Up @@ -295,7 +295,7 @@ describe('ProgramCard', () => {
key: 'minimal',
name: 'Minimal Program',
description: '',
status: ProgramStatusEnum.DRAFT,
status: ProgramStatusEnum.Draft,
startedAt: '',
endedAt: '',
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { useRouter } from 'next/navigation'
import { useSession } from 'next-auth/react'
import React from 'react'
import { render } from 'wrappers/testUtil'
import { ExperienceLevelEnum, ProgramStatusEnum } from 'types/__generated__/graphql'
import type { ExtendedSession } from 'types/auth'
import type { Module } from 'types/mentorship'
import { ExperienceLevelEnum, ProgramStatusEnum } from 'types/mentorship'
import SingleModuleCard from 'components/SingleModuleCard'

// Mock dependencies
Expand Down Expand Up @@ -89,8 +89,8 @@ const mockModule: Module = {
key: 'test-module',
name: 'Test Module',
description: 'This is a test module description',
status: ProgramStatusEnum.PUBLISHED,
experienceLevel: ExperienceLevelEnum.INTERMEDIATE,
status: ProgramStatusEnum.Published,
experienceLevel: ExperienceLevelEnum.Intermediate,
mentors: [
{
name: 'user1',
Expand Down
7 changes: 4 additions & 3 deletions frontend/__tests__/unit/data/mockProgramData.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { ProgramStatusEnum } from 'types/mentorship'
import { ProgramStatusEnum } from 'types/__generated__/graphql'

export const mockPrograms = [
{
key: 'program_1',
name: 'Program 1',
description: 'This is a summary of Program 1.',
startedAt: '2025-01-01',
endedAt: '2025-12-31',
status: 'published',
status: ProgramStatusEnum.Published,
modules: ['Module A', 'Module B'],
},
]
Expand All @@ -16,7 +17,7 @@ export const mockProgramDetailsData = {
key: 'test-program',
name: 'Test Program',
description: 'Sample summary',
status: ProgramStatusEnum.DRAFT,
status: ProgramStatusEnum.Draft,
startedAt: '2025-01-01',
endedAt: '2025-12-31',
menteesLimit: 20,
Expand Down
49 changes: 26 additions & 23 deletions frontend/__tests__/unit/pages/About.test.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { useQuery } from '@apollo/client'
import { useQuery } from '@apollo/client/react'
import { addToast } from '@heroui/toast'
import { fireEvent, screen, waitFor, within } from '@testing-library/react'
import { mockAboutData } from '@unit/data/mockAboutData'
import { useRouter } from 'next/navigation'
import { act } from 'react'
import { render } from 'wrappers/testUtil'
import About from 'app/about/page'
import { GET_PROJECT_METADATA, GET_TOP_CONTRIBUTORS } from 'server/queries/projectQueries'
import { GET_LEADER_DATA } from 'server/queries/userQueries'

jest.mock('@apollo/client', () => ({
...jest.requireActual('@apollo/client'),
import {
GetProjectMetadataDocument,
GetTopContributorsDocument,
} from 'types/__generated__/projectQueries.generated'
import { GetLeaderDataDocument } from 'types/__generated__/userQueries.generated'

jest.mock('@apollo/client/react', () => ({
...jest.requireActual('@apollo/client/react'),
useQuery: jest.fn(),
}))

Expand Down Expand Up @@ -113,18 +116,18 @@ const mockError = {
describe('About Component', () => {
let mockRouter: { push: jest.Mock }
beforeEach(() => {
;(useQuery as jest.Mock).mockImplementation((query, options) => {
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
const key = options?.variables?.key

if (query === GET_PROJECT_METADATA) {
if (query === GetProjectMetadataDocument) {
if (key === 'nest') {
return mockProjectData
}
} else if (query === GET_TOP_CONTRIBUTORS) {
} else if (query === GetTopContributorsDocument) {
if (key === 'nest') {
return mockTopContributorsData
}
} else if (query === GET_LEADER_DATA) {
} else if (query === GetLeaderDataDocument) {
return mockUserData(key)
}

Expand Down Expand Up @@ -172,7 +175,7 @@ describe('About Component', () => {
})

test('handles leader data loading error gracefully', async () => {
;(useQuery as jest.Mock).mockImplementation((query, options) => {
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
if (options?.variables?.key === 'nest') {
return mockProjectData
} else if (options?.variables?.key === 'arkid15r') {
Expand Down Expand Up @@ -305,7 +308,7 @@ describe('About Component', () => {
})

test('LeaderData component shows loading state correctly', async () => {
;(useQuery as jest.Mock).mockImplementation((query, options) => {
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
if (options?.variables?.key === 'nest') {
return mockProjectData
} else if (options?.variables?.key === 'arkid15r') {
Expand Down Expand Up @@ -336,7 +339,7 @@ describe('About Component', () => {
})

test('LeaderData component handles null user data correctly', async () => {
;(useQuery as jest.Mock).mockImplementation((query, options) => {
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
if (options?.variables?.key === 'nest') {
return mockProjectData
} else if (options?.variables?.key === 'arkid15r') {
Expand Down Expand Up @@ -367,7 +370,7 @@ describe('About Component', () => {
})

test('handles null project in data response gracefully', async () => {
;(useQuery as jest.Mock).mockImplementation((query, options) => {
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
if (options?.variables?.key === 'nest') {
return { data: { project: null }, loading: false, error: null }
} else if (['arkid15r', 'kasya', 'mamicidal'].includes(options?.variables?.key)) {
Expand All @@ -389,7 +392,7 @@ describe('About Component', () => {
})

test('handles undefined user data in leader response', async () => {
;(useQuery as jest.Mock).mockImplementation((query, options) => {
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
if (options?.variables?.key === 'nest') {
return mockProjectData
} else if (options?.variables?.key === 'arkid15r') {
Expand Down Expand Up @@ -439,7 +442,7 @@ describe('About Component', () => {
error: null,
}

;(useQuery as jest.Mock).mockImplementation((query, options) => {
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
if (options?.variables?.key === 'nest') {
return mockProjectData
} else if (options?.variables?.key === 'arkid15r') {
Expand All @@ -462,7 +465,7 @@ describe('About Component', () => {
})

test('shows fallback when user data is missing', async () => {
;(useQuery as jest.Mock).mockImplementation((query, options) => {
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
if (options?.variables?.key === 'nest') {
return mockProjectData
} else if (options?.variables?.key === 'arkid15r') {
Expand All @@ -485,7 +488,7 @@ describe('About Component', () => {
})

test('renders LoadingSpinner when project data is loading', async () => {
;(useQuery as jest.Mock).mockImplementation((query, options) => {
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
if (options?.variables?.key === 'nest') {
return { loading: true, data: null, error: null }
}
Expand All @@ -507,7 +510,7 @@ describe('About Component', () => {
})

test('renders ErrorDisplay when project is null', async () => {
;(useQuery as jest.Mock).mockImplementation((query, options) => {
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
if (options?.variables?.key === 'nest') {
return { loading: false, data: { project: null }, error: null }
}
Expand All @@ -529,8 +532,8 @@ describe('About Component', () => {
})

test('triggers toaster error when GraphQL request fails for project', async () => {
;(useQuery as jest.Mock).mockImplementation((query, options) => {
if (query === GET_PROJECT_METADATA && options?.variables?.key === 'nest') {
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
if (query === GetProjectMetadataDocument && options?.variables?.key === 'nest') {
return { loading: false, data: null, error: new Error('GraphQL error') }
}
return {
Expand All @@ -555,8 +558,8 @@ describe('About Component', () => {
})

test('triggers toaster error when GraphQL request fails for topContributors', async () => {
;(useQuery as jest.Mock).mockImplementation((query, options) => {
if (query === GET_TOP_CONTRIBUTORS && options?.variables?.key === 'nest') {
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
if (query === GetTopContributorsDocument && options?.variables?.key === 'nest') {
return { loading: false, data: null, error: new Error('GraphQL error') }
}
return {
Expand Down
23 changes: 13 additions & 10 deletions frontend/__tests__/unit/pages/ApiKeysPage.test.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { useQuery, useMutation } from '@apollo/client'
import { useQuery, useMutation } from '@apollo/client/react'
import { screen, waitFor, fireEvent, within } from '@testing-library/react'
import { mockApiKeys, mockCreateApiKeyResult } from '@unit/data/mockApiKeysData'
import { format, addDays } from 'date-fns'
import React from 'react'
import { render } from 'wrappers/testUtil'
import ApiKeysPage from 'app/settings/api-keys/page'
import { CREATE_API_KEY, REVOKE_API_KEY } from 'server/queries/apiKeyQueries'
import {
CreateApiKeyDocument,
RevokeApiKeyDocument,
} from 'types/__generated__/apiKeyQueries.generated'

jest.mock('@apollo/client', () => ({
...jest.requireActual('@apollo/client'),
jest.mock('@apollo/client/react', () => ({
...jest.requireActual('@apollo/client/react'),
useQuery: jest.fn(),
useMutation: jest.fn(),
}))
Expand Down Expand Up @@ -48,8 +51,8 @@ jest.mock('next/navigation', () => ({
}))

describe('ApiKeysPage Component', () => {
const mockUseQuery = useQuery as jest.Mock
const mockUseMutation = useMutation as jest.Mock
const mockUseQuery = useQuery as unknown as jest.Mock
const mockUseMutation = useMutation as unknown as jest.Mock
const mockRefetch = jest.fn()
const mockCreateMutation = jest.fn().mockResolvedValue(mockCreateApiKeyResult)
const mockRevokeMutation = jest
Expand All @@ -65,10 +68,10 @@ describe('ApiKeysPage Component', () => {
})

mockUseMutation.mockImplementation((mutation) => {
if (mutation === CREATE_API_KEY) {
if (mutation === CreateApiKeyDocument) {
return [mockCreateMutation, { loading: false }]
}
if (mutation === REVOKE_API_KEY) {
if (mutation === RevokeApiKeyDocument) {
return [mockRevokeMutation, { loading: false }]
}
return [jest.fn(), { loading: false }]
Expand Down Expand Up @@ -169,7 +172,7 @@ describe('ApiKeysPage Component', () => {
expect(mockCreateMutation).toHaveBeenCalledWith({
variables: expect.objectContaining({
name: expectedVariables.name,
expiresAt: expect.any(Date),
expiresAt: expect.any(String),
}),
})
})
Expand All @@ -196,7 +199,7 @@ describe('ApiKeysPage Component', () => {
expect(mockCreateMutation).toHaveBeenCalledWith({
variables: {
name: 'Test Key with Expiry',
expiresAt: new Date('2025-12-31'),
expiresAt: new Date('2025-12-31T00:00:00.000Z').toISOString(),
},
})
})
Expand Down
18 changes: 9 additions & 9 deletions frontend/__tests__/unit/pages/ChapterDetails.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { useQuery } from '@apollo/client'
import { useQuery } from '@apollo/client/react'
import { screen, waitFor } from '@testing-library/react'
import { mockChapterDetailsData } from '@unit/data/mockChapterDetailsData'
import { render } from 'wrappers/testUtil'
import ChapterDetailsPage from 'app/chapters/[chapterKey]/page'

jest.mock('@apollo/client', () => ({
...jest.requireActual('@apollo/client'),
jest.mock('@apollo/client/react', () => ({
...jest.requireActual('@apollo/client/react'),
useQuery: jest.fn(),
}))

Expand All @@ -32,7 +32,7 @@ jest.mock('next/navigation', () => ({

describe('chapterDetailsPage Component', () => {
beforeEach(() => {
;(useQuery as jest.Mock).mockReturnValue({
;(useQuery as unknown as jest.Mock).mockReturnValue({
data: mockChapterDetailsData,
error: null,
})
Expand All @@ -43,7 +43,7 @@ describe('chapterDetailsPage Component', () => {
})

test('renders loading spinner initially', async () => {
;(useQuery as jest.Mock).mockReturnValue({
;(useQuery as unknown as jest.Mock).mockReturnValue({
data: null,
error: null,
})
Expand All @@ -55,7 +55,7 @@ describe('chapterDetailsPage Component', () => {
})

test('renders chapter data correctly', async () => {
;(useQuery as jest.Mock).mockReturnValue({
;(useQuery as unknown as jest.Mock).mockReturnValue({
data: mockChapterDetailsData,
error: null,
})
Expand All @@ -69,7 +69,7 @@ describe('chapterDetailsPage Component', () => {
})

test('displays "No chapters found" when there are no chapters', async () => {
;(useQuery as jest.Mock).mockReturnValue({
;(useQuery as unknown as jest.Mock).mockReturnValue({
data: { chapter: null },
error: true,
})
Expand Down Expand Up @@ -109,7 +109,7 @@ describe('chapterDetailsPage Component', () => {
},
],
}
;(useQuery as jest.Mock).mockReturnValue({
;(useQuery as unknown as jest.Mock).mockReturnValue({
data: chapterDataWithIncompleteContributors,
error: null,
})
Expand All @@ -120,7 +120,7 @@ describe('chapterDetailsPage Component', () => {
})
})
test('renders chapter sponsor block correctly', async () => {
;(useQuery as jest.Mock).mockReturnValue({
;(useQuery as unknown as jest.Mock).mockReturnValue({
data: mockChapterDetailsData,
error: null,
})
Expand Down
Loading