Skip to content

Commit f2031ef

Browse files
committed
fix existing tests that use enrollments to properly set the enrollment id, and add a new test for the unenroll dialog
1 parent ad6c4a5 commit f2031ef

File tree

12 files changed

+197
-92
lines changed

12 files changed

+197
-92
lines changed

frontends/api/src/mitxonline/test-utils/urls.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ const currentUser = {
1313
}
1414

1515
const enrollment = {
16-
courseEnrollment: (opts?: RawAxiosRequestConfig) =>
17-
`${API_BASE_URL}/api/v1/enrollments/${queryify(opts)}`,
16+
courseEnrollment: (id?: number) =>
17+
`${API_BASE_URL}/api/v1/enrollments/${id ? `${id}/` : ""}`,
1818
}
1919

2020
const programs = {

frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/DashboardCard.test.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ describe.each([
350350
async ({ contextMenuItems }) => {
351351
const course = dashboardCourse()
352352
course.enrollment = {
353+
id: faker.number.int(),
353354
status: EnrollmentStatus.Completed,
354355
mode: EnrollmentMode.Verified,
355356
}
@@ -366,7 +367,7 @@ describe.each([
366367
await user.click(contextMenuButton)
367368
const expectedMenuItems = [
368369
...contextMenuItems,
369-
...getDefaultContextMenuItems("Test Course"),
370+
...getDefaultContextMenuItems("Test Course", course.enrollment.id),
370371
]
371372
const menuItems = screen.getAllByRole("menuitem")
372373
for (let i = 0; i < expectedMenuItems.length; i++) {

frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/DashboardCard.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ const MenuButton = styled(ActionButton)<{
7878
},
7979
])
8080

81-
const getDefaultContextMenuItems = (title: string, id?: number) => {
81+
const getDefaultContextMenuItems = (title: string, enrollmentId: number) => {
8282
return [
8383
{
8484
className: "dashboard-card-menu-item",
@@ -93,7 +93,7 @@ const getDefaultContextMenuItems = (title: string, id?: number) => {
9393
key: "unenroll",
9494
label: "Unenroll",
9595
onClick: () => {
96-
NiceModal.show(UnenrollDialog, { title, id })
96+
NiceModal.show(UnenrollDialog, { title, enrollmentId })
9797
},
9898
},
9999
]
@@ -333,11 +333,11 @@ const DashboardCard: React.FC<DashboardCardProps> = ({
333333
<CourseStartCountdown startDate={run.startDate} />
334334
) : null
335335
const menuItems = contextMenuItems.concat(
336-
getDefaultContextMenuItems(title, enrollment?.id ?? 0),
336+
enrollment?.id ? getDefaultContextMenuItems(title, enrollment?.id) : [],
337337
)
338338
const contextMenu = isLoading ? (
339339
<Skeleton variant="rectangular" width={12} height={24} />
340-
) : (
340+
) : menuItems.length > 0 ? (
341341
<SimpleMenu
342342
items={menuItems}
343343
trigger={
@@ -351,7 +351,7 @@ const DashboardCard: React.FC<DashboardCardProps> = ({
351351
</MenuButton>
352352
}
353353
/>
354-
)
354+
) : null
355355
const desktopLayout = (
356356
<CardRoot
357357
screenSize="desktop"
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import React from "react"
2+
import {
3+
renderWithProviders,
4+
screen,
5+
setMockResponse,
6+
user,
7+
within,
8+
} from "@/test-utils"
9+
import { EnrollmentDisplay } from "./EnrollmentDisplay"
10+
import * as mitxonline from "api/mitxonline-test-utils"
11+
import { useFeatureFlagEnabled } from "posthog-js/react"
12+
import { setupEnrollments } from "./test-utils"
13+
14+
jest.mock("posthog-js/react")
15+
const mockedUseFeatureFlagEnabled = jest
16+
.mocked(useFeatureFlagEnabled)
17+
.mockImplementation(() => false)
18+
19+
describe("DashboardDialogs", () => {
20+
const setupApis = (includeExpired: boolean = true) => {
21+
const { enrollments, completed, expired, started, notStarted } =
22+
setupEnrollments(includeExpired)
23+
24+
mockedUseFeatureFlagEnabled.mockReturnValue(true)
25+
setMockResponse.get(
26+
mitxonline.urls.enrollment.courseEnrollment(),
27+
enrollments,
28+
)
29+
30+
return { enrollments, completed, expired, started, notStarted }
31+
}
32+
33+
test("Opening the unenroll dialog and confirming the unenroll fires the proper API call", async () => {
34+
const { enrollments } = setupApis()
35+
let deleteCalls = 0
36+
for (const enrollment of enrollments) {
37+
setMockResponse.delete(
38+
mitxonline.urls.enrollment.courseEnrollment(enrollment.id),
39+
() => {
40+
deleteCalls++
41+
},
42+
)
43+
}
44+
renderWithProviders(<EnrollmentDisplay />)
45+
46+
await screen.findByRole("heading", { name: "My Learning" })
47+
48+
const cards = await screen.findAllByTestId("enrollment-card-desktop")
49+
expect(cards.length).toBe(enrollments.length)
50+
51+
const contextMenuButton = await within(cards[0]).findByLabelText(
52+
"More options",
53+
)
54+
await user.click(contextMenuButton)
55+
56+
const unenrollButton = await screen.findByRole("menuitem", {
57+
name: "Unenroll",
58+
})
59+
await user.click(unenrollButton)
60+
61+
const confirmButton = await screen.findByRole("button", {
62+
name: "Unenroll",
63+
})
64+
expect(confirmButton).toBeEnabled()
65+
66+
await user.click(confirmButton)
67+
68+
expect(deleteCalls).toBe(1)
69+
})
70+
})

frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/DashboardDialogs.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const BoldText = styled.span(({ theme }) => ({
2424

2525
type DashboardDialogProps = {
2626
title: string
27-
id: number
27+
enrollmentId: number
2828
}
2929
const EmailSettingsDialogInner: React.FC<DashboardDialogProps> = ({
3030
title,
@@ -85,11 +85,14 @@ const EmailSettingsDialogInner: React.FC<DashboardDialogProps> = ({
8585
)
8686
}
8787

88-
const UnenrollDialogInner: React.FC<DashboardDialogProps> = ({ title, id }) => {
88+
const UnenrollDialogInner: React.FC<DashboardDialogProps> = ({
89+
title,
90+
enrollmentId,
91+
}) => {
8992
const modal = NiceModal.useModal()
9093
const queryClient = useQueryClient()
9194
const { mutate, isSuccess } = useMutation(
92-
enrollmentMutations.destroyEnrollment(id),
95+
enrollmentMutations.destroyEnrollment(enrollmentId),
9396
)
9497
const formik = useFormik({
9598
enableReinitialize: true,

frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/EnrollmentDisplay.test.tsx

Lines changed: 37 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -4,109 +4,72 @@ import {
44
screen,
55
setMockResponse,
66
user,
7+
within,
78
} from "@/test-utils"
89
import { EnrollmentDisplay } from "./EnrollmentDisplay"
910
import * as mitxonline from "api/mitxonline-test-utils"
10-
import moment from "moment"
11-
import { faker } from "@faker-js/faker/locale/en"
1211
import { useFeatureFlagEnabled } from "posthog-js/react"
12+
import { setupEnrollments } from "./test-utils"
1313

1414
jest.mock("posthog-js/react")
1515
const mockedUseFeatureFlagEnabled = jest
1616
.mocked(useFeatureFlagEnabled)
1717
.mockImplementation(() => false)
1818

19-
const courseEnrollment = mitxonline.factories.enrollment.courseEnrollment
20-
const grade = mitxonline.factories.enrollment.grade
2119
describe("EnrollmentDisplay", () => {
2220
const setupApis = (includeExpired: boolean = true) => {
23-
const completed = [
24-
courseEnrollment({
25-
run: { title: "C Course Ended" },
26-
grades: [grade({ passed: true })],
27-
}),
28-
]
29-
const expired = includeExpired
30-
? [
31-
courseEnrollment({
32-
run: {
33-
title: "A Course Ended",
34-
end_date: faker.date.past().toISOString(),
35-
},
36-
}),
37-
courseEnrollment({
38-
run: {
39-
title: "B Course Ended",
40-
end_date: faker.date.past().toISOString(),
41-
},
42-
}),
43-
]
44-
: []
45-
const started = [
46-
courseEnrollment({
47-
run: {
48-
title: "A Course Started",
49-
start_date: faker.date.past().toISOString(),
50-
},
51-
}),
52-
courseEnrollment({
53-
run: {
54-
title: "B Course Started",
55-
start_date: faker.date.past().toISOString(),
56-
},
57-
}),
58-
]
59-
const notStarted = [
60-
courseEnrollment({
61-
run: {
62-
start_date: moment().add(1, "day").toISOString(), // Sooner first
63-
},
64-
}),
65-
courseEnrollment({
66-
run: {
67-
start_date: moment().add(5, "day").toISOString(), // Later second
68-
},
69-
}),
70-
]
71-
const mitxonlineCourseEnrollments = faker.helpers.shuffle([
72-
...expired,
73-
...completed,
74-
...started,
75-
...notStarted,
76-
])
21+
const { enrollments, completed, expired, started, notStarted } =
22+
setupEnrollments(includeExpired)
7723

7824
mockedUseFeatureFlagEnabled.mockReturnValue(true)
7925
setMockResponse.get(
8026
mitxonline.urls.enrollment.courseEnrollment(),
81-
mitxonlineCourseEnrollments,
27+
enrollments,
8228
)
8329

84-
return {
85-
mitxonlineCourseEnrollments,
86-
mitxonlineCourses: { completed, expired, started, notStarted },
87-
}
30+
return { enrollments, completed, expired, started, notStarted }
8831
}
8932

9033
test("Renders the expected cards", async () => {
91-
const { mitxonlineCourses } = setupApis()
34+
const { completed, started, notStarted } = setupApis()
9235
renderWithProviders(<EnrollmentDisplay />)
9336

9437
await screen.findByRole("heading", { name: "My Learning" })
9538

9639
const cards = await screen.findAllByTestId("enrollment-card-desktop")
97-
const expectedTitles = [
98-
...mitxonlineCourses.started,
99-
...mitxonlineCourses.notStarted,
100-
...mitxonlineCourses.completed,
101-
].map((e) => e.run.title)
40+
const expectedTitles = [...started, ...notStarted, ...completed].map(
41+
(e) => e.run.title,
42+
)
10243

10344
expectedTitles.forEach((title, i) => {
10445
expect(cards[i]).toHaveTextContent(title)
10546
})
10647
})
10748

49+
test("Renders the proper amount of unenroll and email settings buttons in the context menus", async () => {
50+
const { enrollments } = setupApis()
51+
renderWithProviders(<EnrollmentDisplay />)
52+
53+
const cards = await screen.findAllByTestId("enrollment-card-desktop")
54+
expect(cards.length).toBe(enrollments.length)
55+
for (const card of cards) {
56+
const contextMenuButton =
57+
await within(card).findByLabelText("More options")
58+
await user.click(contextMenuButton)
59+
const emailSettingsButton = await screen.findAllByRole("menuitem", {
60+
name: "Email Settings",
61+
})
62+
const unenrollButton = await screen.findAllByRole("menuitem", {
63+
name: "Unenroll",
64+
})
65+
expect(emailSettingsButton.length).toBe(1)
66+
expect(unenrollButton.length).toBe(1)
67+
await user.click(contextMenuButton)
68+
}
69+
})
70+
10871
test("Clicking show all reveals ended courses", async () => {
109-
const { mitxonlineCourses } = setupApis()
72+
const { completed, expired, started, notStarted } = setupApis()
11073
renderWithProviders(<EnrollmentDisplay />)
11174

11275
const showAllButton = await screen.findByText("Show all")
@@ -116,10 +79,10 @@ describe("EnrollmentDisplay", () => {
11679

11780
const cards = await screen.findAllByTestId("enrollment-card-desktop")
11881
const expectedTitles = [
119-
...mitxonlineCourses.started,
120-
...mitxonlineCourses.notStarted,
121-
...mitxonlineCourses.completed,
122-
...mitxonlineCourses.expired,
82+
...started,
83+
...notStarted,
84+
...completed,
85+
...expired,
12386
].map((e) => e.run.title)
12487

12588
expectedTitles.forEach((title, i) => {

frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/EnrollmentDisplay.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ const EnrollmentExpandCollapse: React.FC<EnrollmentExpandCollapseProps> = ({
175175

176176
const EnrollmentDisplay = () => {
177177
const { data: enrolledCourses, isLoading } = useQuery({
178-
...enrollmentQueries.enrollmentsList({}),
178+
...enrollmentQueries.enrollmentsList(),
179179
select: mitxonlineEnrollments,
180180
throwOnError: (error) => {
181181
const err = error as MaybeHasStatusAndDetail

0 commit comments

Comments
 (0)