Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
11 changes: 11 additions & 0 deletions RELEASE.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
Release Notes
=============

Version 0.47.11
---------------

- set h5 on the welcome message (#2682)
- Avoid errors caused by None tags (#2680)
- org contract welcome message display (#2677)
- Add periodic topic collection sync task (#2673)
- Resource card headings for screen reader navigation (#2658)
- fix CTA text logic (#2675)
- Fix OpenAPI Client Generation for multivalue query params (#2669)

Version 0.47.9 (Released November 05, 2025)
--------------

Expand Down
2 changes: 1 addition & 1 deletion frontends/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"ol-test-utilities": "0.0.0"
},
"dependencies": {
"@mitodl/mitxonline-api-axios": "^2025.10.21",
"@mitodl/mitxonline-api-axios": "^2025.11.5",
"@tanstack/react-query": "^5.66.0",
"axios": "^1.12.2",
"tiny-invariant": "^1.3.3"
Expand Down
493 changes: 212 additions & 281 deletions frontends/api/src/generated/v1/api.ts

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ const contract = (overrides: Partial<ContractPage> = {}): ContractPage => ({
organization: faker.number.int(),
slug: faker.lorem.slug(),
membership_type: faker.helpers.arrayElement(["managed", "unmanaged"]),
welcome_message: faker.lorem.sentence(),
welcome_message_extra: `<p>${faker.lorem.paragraph()}</p>`,
...overrides,
})

Expand Down
2 changes: 0 additions & 2 deletions frontends/api/src/mitxonline/test-utils/factories/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import { UniqueEnforcer } from "enforce-unique"
const enforcerId = new UniqueEnforcer()

const legalAddress = (): LegalAddress => ({
first_name: faker.person.firstName(),
last_name: faker.person.lastName(),
country: faker.location.countryCode(),
state: faker.datatype.boolean() ? faker.location.state() : null,
})
Expand Down
2 changes: 1 addition & 1 deletion frontends/main/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"@emotion/cache": "^11.13.1",
"@emotion/styled": "^11.11.0",
"@mitodl/course-search-utils": "^3.5.0",
"@mitodl/mitxonline-api-axios": "^2025.10.21",
"@mitodl/mitxonline-api-axios": "^2025.11.5",
"@mitodl/smoot-design": "^6.17.1",
"@next/bundle-analyzer": "^14.2.15",
"@react-pdf/renderer": "^4.3.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,17 +176,23 @@ describe.each([

test.each([
{
course: pastDashboardCourse(),
course: pastDashboardCourse({
enrollment: { status: EnrollmentStatus.Enrolled },
}),
expected: { labelPrefix: "View" },
case: "past",
},
{
course: currentDashboardCourse(),
course: currentDashboardCourse({
enrollment: { status: EnrollmentStatus.Enrolled },
}),
expected: { labelPrefix: "Continue" },
case: "current",
},
{
course: futureDashboardCourse(),
course: futureDashboardCourse({
enrollment: { status: EnrollmentStatus.Enrolled },
}),
expected: { labelPrefix: "Continue" },
label: "future",
},
Expand Down Expand Up @@ -515,12 +521,12 @@ describe.each([
)

test.each([
{ status: EnrollmentStatus.Completed },
{ status: EnrollmentStatus.Enrolled },
{ status: EnrollmentStatus.NotEnrolled },
{ status: EnrollmentStatus.Completed, expectedText: "View Course" },
{ status: EnrollmentStatus.Enrolled, expectedText: "Continue Course" },
{ status: EnrollmentStatus.NotEnrolled, expectedText: "Start Course" },
])(
"CoursewareButton switches to Enroll functionality when enrollment status is not enrolled or undefined",
({ status }) => {
"CoursewareButton shows correct text based on enrollment status ($status)",
({ status, expectedText }) => {
setupUserApis()
const course = dashboardCourse()
course.enrollment = {
Expand All @@ -534,18 +540,31 @@ describe.each([
const card = getCard()
const coursewareButton = within(card).getByTestId("courseware-button")

if (
status === EnrollmentStatus.NotEnrolled ||
status === undefined ||
!course.enrollment
) {
expect(coursewareButton).toHaveTextContent("Start Course")
} else {
expect(coursewareButton).toHaveTextContent("Continue Course")
}
expect(coursewareButton).toHaveTextContent(expectedText)
},
)

test("CoursewareButton shows 'View Course' when course has ended even if not completed", () => {
setupUserApis()
const course = dashboardCourse({
run: {
startDate: faker.date.past().toISOString(),
endDate: faker.date.past().toISOString(), // Course has ended
},
enrollment: {
status: EnrollmentStatus.Enrolled, // User is enrolled but not completed
mode: EnrollmentMode.Audit,
},
})
renderWithProviders(
<DashboardCard titleAction="marketing" dashboardResource={course} />,
)
const card = getCard()
const coursewareButton = within(card).getByTestId("courseware-button")

expect(coursewareButton).toHaveTextContent("View Course")
})

const setupEnrollmentApis = (opts: {
user: ReturnType<typeof mitxUser>
course: ReturnType<typeof dashboardCourse>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,10 @@ const getCoursewareText = ({
if (!enrollmentStatus || enrollmentStatus === EnrollmentStatus.NotEnrolled) {
return `Start ${courseNoun}`
}
if (!endDate) return `Continue ${courseNoun}`
if (isInPast(endDate)) {
if (
(endDate && isInPast(endDate)) ||
enrollmentStatus === EnrollmentStatus.Completed
) {
return `View ${courseNoun}`
}
return `Continue ${courseNoun}`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,11 @@ const setupProgramsAndCourses = () => {
results: [programCollection],
})
setMockResponse.get(
urls.programs.programsList({ id: programA.id, org_id: orgX.id }),
urls.programs.programsList({ id: [programA.id], org_id: orgX.id }),
{ results: [programA] },
)
setMockResponse.get(
urls.programs.programsList({ id: programB.id, org_id: orgX.id }),
urls.programs.programsList({ id: [programB.id], org_id: orgX.id }),
{ results: [programB] },
)
setMockResponse.get(
Expand Down Expand Up @@ -310,6 +310,8 @@ const createTestContracts = (
organization: orgId,
slug: faker.lorem.slug(),
membership_type: faker.helpers.arrayElement(["managed", "unmanaged"]),
welcome_message: faker.lorem.sentence(),
welcome_message_extra: faker.lorem.sentence(),
}))
}

Expand Down
Loading
Loading