Skip to content

Commit b66da4d

Browse files
authored
Merge branch 'main' into ark/api-extend-v0
2 parents 1340ef5 + 8b2c811 commit b66da4d

File tree

98 files changed

+2423
-2329
lines changed

Some content is hidden

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

98 files changed

+2423
-2329
lines changed

frontend/__tests__/unit/components/ProgramActions.test.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { fireEvent, screen } from '@testing-library/react'
22
import '@testing-library/jest-dom'
33
import { useSession as mockUseSession } from 'next-auth/react'
44
import { render } from 'wrappers/testUtil'
5+
import { ProgramStatusEnum } from 'types/__generated__/graphql'
56
import ProgramActions from 'components/ProgramActions'
67

78
const mockPush = jest.fn()
@@ -65,7 +66,7 @@ describe('ProgramActions', () => {
6566
const button = screen.getByTestId('program-actions-button')
6667
fireEvent.click(button)
6768
fireEvent.click(screen.getByRole('menuitem', { name: /publish program/i }))
68-
expect(setStatus).toHaveBeenCalledWith('PUBLISHED')
69+
expect(setStatus).toHaveBeenCalledWith(ProgramStatusEnum.Published)
6970
expect(mockPush).not.toHaveBeenCalled()
7071
})
7172

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

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

8889
test('dropdown closes on outside click', () => {

frontend/__tests__/unit/components/ProgramCard.test.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { faEye } from '@fortawesome/free-regular-svg-icons'
22
import { faEdit } from '@fortawesome/free-solid-svg-icons'
33
import { fireEvent, render, screen } from '@testing-library/react'
44
import React from 'react'
5+
import { ProgramStatusEnum } from 'types/__generated__/graphql'
56
import type { Program } from 'types/mentorship'
6-
import { ProgramStatusEnum } from 'types/mentorship'
77
import ProgramCard from 'components/ProgramCard'
88

99
jest.mock('@fortawesome/react-fontawesome', () => ({
@@ -33,7 +33,7 @@ describe('ProgramCard', () => {
3333
key: 'test-program',
3434
name: 'Test Program',
3535
description: 'This is a test program description',
36-
status: ProgramStatusEnum.PUBLISHED,
36+
status: ProgramStatusEnum.Published,
3737
startedAt: '2024-01-01T00:00:00Z',
3838
endedAt: '2024-12-31T23:59:59Z',
3939
userRole: 'admin',
@@ -295,7 +295,7 @@ describe('ProgramCard', () => {
295295
key: 'minimal',
296296
name: 'Minimal Program',
297297
description: '',
298-
status: ProgramStatusEnum.DRAFT,
298+
status: ProgramStatusEnum.Draft,
299299
startedAt: '',
300300
endedAt: '',
301301
}

frontend/__tests__/unit/components/SingleModuleCard.test.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import { useRouter } from 'next/navigation'
44
import { useSession } from 'next-auth/react'
55
import React from 'react'
66
import { render } from 'wrappers/testUtil'
7+
import { ExperienceLevelEnum, ProgramStatusEnum } from 'types/__generated__/graphql'
78
import type { ExtendedSession } from 'types/auth'
89
import type { Module } from 'types/mentorship'
9-
import { ExperienceLevelEnum, ProgramStatusEnum } from 'types/mentorship'
1010
import SingleModuleCard from 'components/SingleModuleCard'
1111

1212
// Mock dependencies
@@ -89,8 +89,8 @@ const mockModule: Module = {
8989
key: 'test-module',
9090
name: 'Test Module',
9191
description: 'This is a test module description',
92-
status: ProgramStatusEnum.PUBLISHED,
93-
experienceLevel: ExperienceLevelEnum.INTERMEDIATE,
92+
status: ProgramStatusEnum.Published,
93+
experienceLevel: ExperienceLevelEnum.Intermediate,
9494
mentors: [
9595
{
9696
name: 'user1',

frontend/__tests__/unit/data/mockProgramData.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
import { ProgramStatusEnum } from 'types/mentorship'
1+
import { ProgramStatusEnum } from 'types/__generated__/graphql'
2+
23
export const mockPrograms = [
34
{
45
key: 'program_1',
56
name: 'Program 1',
67
description: 'This is a summary of Program 1.',
78
startedAt: '2025-01-01',
89
endedAt: '2025-12-31',
9-
status: 'published',
10+
status: ProgramStatusEnum.Published,
1011
modules: ['Module A', 'Module B'],
1112
},
1213
]
@@ -16,7 +17,7 @@ export const mockProgramDetailsData = {
1617
key: 'test-program',
1718
name: 'Test Program',
1819
description: 'Sample summary',
19-
status: ProgramStatusEnum.DRAFT,
20+
status: ProgramStatusEnum.Draft,
2021
startedAt: '2025-01-01',
2122
endedAt: '2025-12-31',
2223
menteesLimit: 20,

frontend/__tests__/unit/pages/About.test.tsx

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1-
import { useQuery } from '@apollo/client'
1+
import { useQuery } from '@apollo/client/react'
22
import { addToast } from '@heroui/toast'
33
import { fireEvent, screen, waitFor, within } from '@testing-library/react'
44
import { mockAboutData } from '@unit/data/mockAboutData'
55
import { useRouter } from 'next/navigation'
66
import { act } from 'react'
77
import { render } from 'wrappers/testUtil'
88
import About from 'app/about/page'
9-
import { GET_PROJECT_METADATA, GET_TOP_CONTRIBUTORS } from 'server/queries/projectQueries'
10-
import { GET_LEADER_DATA } from 'server/queries/userQueries'
11-
12-
jest.mock('@apollo/client', () => ({
13-
...jest.requireActual('@apollo/client'),
9+
import {
10+
GetProjectMetadataDocument,
11+
GetTopContributorsDocument,
12+
} from 'types/__generated__/projectQueries.generated'
13+
import { GetLeaderDataDocument } from 'types/__generated__/userQueries.generated'
14+
15+
jest.mock('@apollo/client/react', () => ({
16+
...jest.requireActual('@apollo/client/react'),
1417
useQuery: jest.fn(),
1518
}))
1619

@@ -127,18 +130,18 @@ const mockError = {
127130
describe('About Component', () => {
128131
let mockRouter: { push: jest.Mock }
129132
beforeEach(() => {
130-
;(useQuery as jest.Mock).mockImplementation((query, options) => {
133+
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
131134
const key = options?.variables?.key
132135

133-
if (query === GET_PROJECT_METADATA) {
136+
if (query === GetProjectMetadataDocument) {
134137
if (key === 'nest') {
135138
return mockProjectData
136139
}
137-
} else if (query === GET_TOP_CONTRIBUTORS) {
140+
} else if (query === GetTopContributorsDocument) {
138141
if (key === 'nest') {
139142
return mockTopContributorsData
140143
}
141-
} else if (query === GET_LEADER_DATA) {
144+
} else if (query === GetLeaderDataDocument) {
142145
return mockUserData(key)
143146
}
144147

@@ -214,7 +217,7 @@ describe('About Component', () => {
214217
})
215218

216219
test('handles leader data loading error gracefully', async () => {
217-
;(useQuery as jest.Mock).mockImplementation((query, options) => {
220+
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
218221
if (options?.variables?.key === 'nest') {
219222
return mockProjectData
220223
} else if (options?.variables?.key === 'arkid15r') {
@@ -347,7 +350,7 @@ describe('About Component', () => {
347350
})
348351

349352
test('LeaderData component shows loading state correctly', async () => {
350-
;(useQuery as jest.Mock).mockImplementation((query, options) => {
353+
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
351354
if (options?.variables?.key === 'nest') {
352355
return mockProjectData
353356
} else if (options?.variables?.key === 'arkid15r') {
@@ -378,7 +381,7 @@ describe('About Component', () => {
378381
})
379382

380383
test('LeaderData component handles null user data correctly', async () => {
381-
;(useQuery as jest.Mock).mockImplementation((query, options) => {
384+
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
382385
if (options?.variables?.key === 'nest') {
383386
return mockProjectData
384387
} else if (options?.variables?.key === 'arkid15r') {
@@ -409,7 +412,7 @@ describe('About Component', () => {
409412
})
410413

411414
test('handles null project in data response gracefully', async () => {
412-
;(useQuery as jest.Mock).mockImplementation((query, options) => {
415+
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
413416
if (options?.variables?.key === 'nest') {
414417
return { data: { project: null }, loading: false, error: null }
415418
} else if (['arkid15r', 'kasya', 'mamicidal'].includes(options?.variables?.key)) {
@@ -431,7 +434,7 @@ describe('About Component', () => {
431434
})
432435

433436
test('handles undefined user data in leader response', async () => {
434-
;(useQuery as jest.Mock).mockImplementation((query, options) => {
437+
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
435438
if (options?.variables?.key === 'nest') {
436439
return mockProjectData
437440
} else if (options?.variables?.key === 'arkid15r') {
@@ -481,7 +484,7 @@ describe('About Component', () => {
481484
error: null,
482485
}
483486

484-
;(useQuery as jest.Mock).mockImplementation((query, options) => {
487+
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
485488
if (options?.variables?.key === 'nest') {
486489
return mockProjectData
487490
} else if (options?.variables?.key === 'arkid15r') {
@@ -504,7 +507,7 @@ describe('About Component', () => {
504507
})
505508

506509
test('shows fallback when user data is missing', async () => {
507-
;(useQuery as jest.Mock).mockImplementation((query, options) => {
510+
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
508511
if (options?.variables?.key === 'nest') {
509512
return mockProjectData
510513
} else if (options?.variables?.key === 'arkid15r') {
@@ -527,7 +530,7 @@ describe('About Component', () => {
527530
})
528531

529532
test('renders LoadingSpinner when project data is loading', async () => {
530-
;(useQuery as jest.Mock).mockImplementation((query, options) => {
533+
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
531534
if (options?.variables?.key === 'nest') {
532535
return { loading: true, data: null, error: null }
533536
}
@@ -549,7 +552,7 @@ describe('About Component', () => {
549552
})
550553

551554
test('renders ErrorDisplay when project is null', async () => {
552-
;(useQuery as jest.Mock).mockImplementation((query, options) => {
555+
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
553556
if (options?.variables?.key === 'nest') {
554557
return { loading: false, data: { project: null }, error: null }
555558
}
@@ -571,8 +574,8 @@ describe('About Component', () => {
571574
})
572575

573576
test('triggers toaster error when GraphQL request fails for project', async () => {
574-
;(useQuery as jest.Mock).mockImplementation((query, options) => {
575-
if (query === GET_PROJECT_METADATA && options?.variables?.key === 'nest') {
577+
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
578+
if (query === GetProjectMetadataDocument && options?.variables?.key === 'nest') {
576579
return { loading: false, data: null, error: new Error('GraphQL error') }
577580
}
578581
return {
@@ -597,8 +600,8 @@ describe('About Component', () => {
597600
})
598601

599602
test('triggers toaster error when GraphQL request fails for topContributors', async () => {
600-
;(useQuery as jest.Mock).mockImplementation((query, options) => {
601-
if (query === GET_TOP_CONTRIBUTORS && options?.variables?.key === 'nest') {
603+
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
604+
if (query === GetTopContributorsDocument && options?.variables?.key === 'nest') {
602605
return { loading: false, data: null, error: new Error('GraphQL error') }
603606
}
604607
return {

frontend/__tests__/unit/pages/ApiKeysPage.test.tsx

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
/* eslint-disable @typescript-eslint/naming-convention */
2-
import { useQuery, useMutation } from '@apollo/client'
2+
import { useQuery, useMutation } from '@apollo/client/react'
33
import { screen, waitFor, fireEvent, within } from '@testing-library/react'
44
import { mockApiKeys, mockCreateApiKeyResult } from '@unit/data/mockApiKeysData'
55
import { format, addDays } from 'date-fns'
66
import React from 'react'
77
import { render } from 'wrappers/testUtil'
88
import ApiKeysPage from 'app/settings/api-keys/page'
9-
import { CREATE_API_KEY, REVOKE_API_KEY } from 'server/queries/apiKeyQueries'
9+
import {
10+
CreateApiKeyDocument,
11+
RevokeApiKeyDocument,
12+
} from 'types/__generated__/apiKeyQueries.generated'
1013

11-
jest.mock('@apollo/client', () => ({
12-
...jest.requireActual('@apollo/client'),
14+
jest.mock('@apollo/client/react', () => ({
15+
...jest.requireActual('@apollo/client/react'),
1316
useQuery: jest.fn(),
1417
useMutation: jest.fn(),
1518
}))
@@ -48,8 +51,8 @@ jest.mock('next/navigation', () => ({
4851
}))
4952

5053
describe('ApiKeysPage Component', () => {
51-
const mockUseQuery = useQuery as jest.Mock
52-
const mockUseMutation = useMutation as jest.Mock
54+
const mockUseQuery = useQuery as unknown as jest.Mock
55+
const mockUseMutation = useMutation as unknown as jest.Mock
5356
const mockRefetch = jest.fn()
5457
const mockCreateMutation = jest.fn().mockResolvedValue(mockCreateApiKeyResult)
5558
const mockRevokeMutation = jest
@@ -65,10 +68,10 @@ describe('ApiKeysPage Component', () => {
6568
})
6669

6770
mockUseMutation.mockImplementation((mutation) => {
68-
if (mutation === CREATE_API_KEY) {
71+
if (mutation === CreateApiKeyDocument) {
6972
return [mockCreateMutation, { loading: false }]
7073
}
71-
if (mutation === REVOKE_API_KEY) {
74+
if (mutation === RevokeApiKeyDocument) {
7275
return [mockRevokeMutation, { loading: false }]
7376
}
7477
return [jest.fn(), { loading: false }]
@@ -169,7 +172,7 @@ describe('ApiKeysPage Component', () => {
169172
expect(mockCreateMutation).toHaveBeenCalledWith({
170173
variables: expect.objectContaining({
171174
name: expectedVariables.name,
172-
expiresAt: expect.any(Date),
175+
expiresAt: expect.any(String),
173176
}),
174177
})
175178
})
@@ -196,7 +199,7 @@ describe('ApiKeysPage Component', () => {
196199
expect(mockCreateMutation).toHaveBeenCalledWith({
197200
variables: {
198201
name: 'Test Key with Expiry',
199-
expiresAt: new Date('2025-12-31'),
202+
expiresAt: new Date('2025-12-31T00:00:00.000Z').toISOString(),
200203
},
201204
})
202205
})

frontend/__tests__/unit/pages/ChapterDetails.test.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { useQuery } from '@apollo/client'
1+
import { useQuery } from '@apollo/client/react'
22
import { screen, waitFor } from '@testing-library/react'
33
import { mockChapterDetailsData } from '@unit/data/mockChapterDetailsData'
44
import { render } from 'wrappers/testUtil'
55
import ChapterDetailsPage from 'app/chapters/[chapterKey]/page'
66

7-
jest.mock('@apollo/client', () => ({
8-
...jest.requireActual('@apollo/client'),
7+
jest.mock('@apollo/client/react', () => ({
8+
...jest.requireActual('@apollo/client/react'),
99
useQuery: jest.fn(),
1010
}))
1111

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

3333
describe('chapterDetailsPage Component', () => {
3434
beforeEach(() => {
35-
;(useQuery as jest.Mock).mockReturnValue({
35+
;(useQuery as unknown as jest.Mock).mockReturnValue({
3636
data: mockChapterDetailsData,
3737
error: null,
3838
})
@@ -43,7 +43,7 @@ describe('chapterDetailsPage Component', () => {
4343
})
4444

4545
test('renders loading spinner initially', async () => {
46-
;(useQuery as jest.Mock).mockReturnValue({
46+
;(useQuery as unknown as jest.Mock).mockReturnValue({
4747
data: null,
4848
error: null,
4949
})
@@ -55,7 +55,7 @@ describe('chapterDetailsPage Component', () => {
5555
})
5656

5757
test('renders chapter data correctly', async () => {
58-
;(useQuery as jest.Mock).mockReturnValue({
58+
;(useQuery as unknown as jest.Mock).mockReturnValue({
5959
data: mockChapterDetailsData,
6060
error: null,
6161
})
@@ -69,7 +69,7 @@ describe('chapterDetailsPage Component', () => {
6969
})
7070

7171
test('displays "No chapters found" when there are no chapters', async () => {
72-
;(useQuery as jest.Mock).mockReturnValue({
72+
;(useQuery as unknown as jest.Mock).mockReturnValue({
7373
data: { chapter: null },
7474
error: true,
7575
})
@@ -109,7 +109,7 @@ describe('chapterDetailsPage Component', () => {
109109
},
110110
],
111111
}
112-
;(useQuery as jest.Mock).mockReturnValue({
112+
;(useQuery as unknown as jest.Mock).mockReturnValue({
113113
data: chapterDataWithIncompleteContributors,
114114
error: null,
115115
})
@@ -120,7 +120,7 @@ describe('chapterDetailsPage Component', () => {
120120
})
121121
})
122122
test('renders chapter sponsor block correctly', async () => {
123-
;(useQuery as jest.Mock).mockReturnValue({
123+
;(useQuery as unknown as jest.Mock).mockReturnValue({
124124
data: mockChapterDetailsData,
125125
error: null,
126126
})

0 commit comments

Comments
 (0)