Skip to content
Open
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
2 changes: 1 addition & 1 deletion frontends/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"ol-test-utilities": "0.0.0"
},
"dependencies": {
"@mitodl/mitxonline-api-axios": "2026.5.1",
"@mitodl/mitxonline-api-axios": "2026.5.21",
"@tanstack/react-query": "^5.66.0",
"axios": "^1.12.2",
"tiny-invariant": "^1.3.3"
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/styled": "^11.11.0",
"@floating-ui/react": "^0.27.16",
"@mitodl/course-search-utils": "^3.5.2",
"@mitodl/mitxonline-api-axios": "2026.5.1",
"@mitodl/mitxonline-api-axios": "2026.5.21",
"@mitodl/smoot-design": "^6.27.0",
"@mui/material": "^6.4.5",
"@mui/material-nextjs": "^6.4.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1910,4 +1910,30 @@ describe("ContractContent", () => {
const coursewareButton = within(card).getByTestId("courseware-button")
expect(coursewareButton).toHaveAttribute("href", enrolledRun.courseware_url)
})

it("renders without crashing when program.page is null", async () => {
const { orgX, programA, programB } = setupProgramsAndCourses()
const contract = orgX.contracts[0]

setMockResponse.get(
urls.programs.programsList({
org_id: orgX.id,
contract_id: contract.id,
page_size: 30,
}),
{
results: [
{ ...programA, page: null },
{ ...programB, page: null },
],
},
)

renderWithProviders(
<ContractContent orgSlug={orgX.slug} contractSlug={contract.slug} />,
)

await screen.findByText(programA.title)
await screen.findByText(programB.title)
})
})
9 changes: 9 additions & 0 deletions frontends/main/src/app-pages/ProductPages/CoursePage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -483,4 +483,13 @@ describe("CoursePage", () => {
).not.toBeInTheDocument()
})
})

test("Renders without crashing when course_details.page is null", async () => {
const course = makeCourse({ page: null })
const page = makePage({ course_details: course })
setupApis({ course, page })
renderWithProviders(<CoursePage readableId={course.readable_id} />)

await screen.findByRole("heading", { name: page.title })
})
})
4 changes: 2 additions & 2 deletions frontends/main/src/app-pages/ProductPages/CoursePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,13 @@ const CoursePage: React.FC<CoursePageProps> = ({ readableId }) => {
}

const imageSrc =
page.course_details.page.feature_image_src || DEFAULT_RESOURCE_IMG
page.course_details.page?.feature_image_src || DEFAULT_RESOURCE_IMG

return (
<ProductPageTemplate
currentBreadcrumbLabel="Course"
title={page.title}
shortDescription={page.course_details.page.description}
shortDescription={page.course_details.page?.description}
imageSrc={imageSrc}
videoUrl={page.video_url}
infoBox={<CourseInfoBox course={course} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,13 @@ describe("ProgramSummary", () => {
}
},
)

test("Does not crash and hides duration row when program page is null", () => {
const program = factories.programs.program({ page: null })
renderWithProviders(<ProgramSummary program={program} />)

expect(screen.queryByTestId(TestIds.DurationRow)).toBeNull()
})
})

describe("Pacing Row", () => {
Expand Down
10 changes: 6 additions & 4 deletions frontends/main/src/app-pages/ProductPages/ProductSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -694,8 +694,8 @@ const ProgramDurationRow: React.FC<ProgramInfoRowProps> = ({
program,
...others
}) => {
const duration = program.page.length ?? ""
const effort = program.page.effort ?? ""
const duration = program.page?.length ?? ""
const effort = program.page?.effort ?? ""
if (!duration) return null
const display = [duration, effort].filter(Boolean).join(", ")

Expand Down Expand Up @@ -780,10 +780,12 @@ const ProgramCertificateBox: React.FC<{ program: V2ProgramDetail }> = ({
: {formatPrice(price, { avoidCents: true })}
</span>
</InfoRowInner>
{program.page.financial_assistance_form_url ? (
{program.page?.financial_assistance_form_url ? (
<UnderlinedLink
color="black"
href={mitxonlineLegacyUrl(program.page.financial_assistance_form_url)}
href={mitxonlineLegacyUrl(
program.page?.financial_assistance_form_url,
)}
target="_blank"
rel="noopener noreferrer"
style={{ minWidth: "fit-content" }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,4 +382,15 @@ describe("ProgramAsCoursePage", () => {
).not.toBeInTheDocument()
})
})

test("Renders without crashing when program_details.page is null", async () => {
const program = makeProgramAsCourse({ page: null })
const page = makePage({ program_details: program })
setupApis({ program, page })
renderWithProviders(
<ProgramAsCoursePage readableId={program.readable_id} />,
)

await screen.findByRole("heading", { name: page.title })
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ const ProgramAsCoursePage: React.FC<ProgramAsCoursePageProps> = ({
}

const imageSrc =
page.program_details.page.feature_image_src || DEFAULT_RESOURCE_IMG
page.program_details.page?.feature_image_src || DEFAULT_RESOURCE_IMG

const dataLoading =
(courseIds.length > 0 && !courses.isSuccess) ||
Expand All @@ -271,7 +271,7 @@ const ProgramAsCoursePage: React.FC<ProgramAsCoursePageProps> = ({
shortDescription={
<DescriptionHTML
Component="span"
html={page.program_details.page.description}
html={page.program_details.page?.description ?? ""}
/>
}
imageSrc={imageSrc}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -798,4 +798,13 @@ describe("ProgramPage", () => {
).not.toBeInTheDocument()
})
})

test("Renders without crashing when program_details.page is null", async () => {
const program = makeProgram({ ...makeReqs(), page: null })
const page = makePage({ program_details: program })
setupApis({ program, page })
renderWithProviders(<ProgramPage readableId={program.readable_id} />)

await screen.findByRole("heading", { name: page.title })
})
})
4 changes: 2 additions & 2 deletions frontends/main/src/app-pages/ProductPages/ProgramPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ const ProgramPage: React.FC<ProgramPageProps> = ({ readableId }) => {
}

const imageSrc =
page.program_details.page.feature_image_src || DEFAULT_RESOURCE_IMG
page.program_details.page?.feature_image_src || DEFAULT_RESOURCE_IMG

const dataLoading =
(courseIds.length > 0 && !courses.isSuccess) ||
Expand All @@ -289,7 +289,7 @@ const ProgramPage: React.FC<ProgramPageProps> = ({ readableId }) => {
shortDescription={
<DescriptionHTML
Component="span"
html={page.program_details.page.description}
html={page.program_details.page?.description ?? ""}
/>
}
imageSrc={imageSrc}
Expand Down
12 changes: 6 additions & 6 deletions yarn.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading