one click upgrade for courses in verified program enrollments - #3671
one click upgrade for courses in verified program enrollments#3671gumaerc wants to merge 3 commits into
Conversation
OpenAPI ChangesNo changes detected Unexpected changes? Ensure your branch is up-to-date with |
There was a problem hiding this comment.
Pull request overview
This PR updates the MIT Learn program dashboard course cards so that when a learner is audit-enrolled in a course run but has a verified program enrollment that includes that course, clicking “Upgrade for certificate” performs the existing one-click verified upgrade flow (no checkout) and then redirects to courseware.
Changes:
- Thread
entry.ancestorContextthroughCoursewareCardinto the enrolled-course card path so enrolled cards have program-enrollment context. - Add a verified-program upgrade branch to
EnrolledCourseCard’s upgrade link behavior (useuseCreateVerifiedProgramEnrollmentand omit the price in the label). - Add test coverage for the verified-program upgrade label, success redirect, and error handling.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/EnrolledCourseCard.tsx | Adds verified-program one-click upgrade handling and threads ancestor program context into the upgrade banner. |
| frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/EnrolledCourseCard.test.tsx | Adds tests for the verified-program one-click upgrade behavior and label formatting. |
| frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/CoursewareCard.tsx | Passes ancestorContext into the enrolled course card for the "course" kind’s enrolled branch. |
Comments suppressed due to low confidence (1)
frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/EnrolledCourseCard.tsx:309
onUpgradeErroralways reports "adding the certificate to your cart", but in the verified-program path this action is a free one-click enrollment upgrade (no cart/checkout). Updating the message makes the error actionable and avoids confusing users when the verified-program upgrade API fails.
onError={() => {
onUpgradeError?.(
"There was a problem adding the certificate to your cart.",
)
}}
…ments in the courseruns in the program, do a free upgrade
bf4ed49 to
8b2e90a
Compare
ChristopherChudzicki
left a comment
There was a problem hiding this comment.
This is working pretty well, code generally looks good 👍 I did notice two issues:
- An enrollment issue
- UI doesn't reflect enrollment error
Issue one
Assume that products + audit & verified enrollment modes exist for all courses/programs/runs below.
Overall Program (e.g., SDS)
Child Program 1
Course x
Course y
Course z1
Child Program 2
Course x
Course y
Course z2
Note: Above, Courses x & y are the same, i.e., same course in both CP1 and CP2. That's how SDS sets up its "tracks". Not important for this bug, though.
Then:
Assume a user has
- Audit Enrollment Overall Program
- Verified enrollment in Child Program 1
- Audit enrollment in x
Then clicking "Upgrade" on Course x within Child Program 1 is an enrollment error. Frontend does POST https://api.learn.mit.dev/mitxonline/api/v2/verified_program_enrollments/COURSERUN_READABLE_ID with body [program-v1:child-program-1, program-v1:overall-program], and backend says "User has no verified enrollment in program-v1:overall-program".
SUGGESTION:
The point of posting to verified_program_enrollments/{RUN_READABLE_ID} with body [p1,p2] is the user has a verified enrollment in p2 but needs verified enrollment in p1.
Can we omit p2 if their p2 enrollment is not verified?
We only have two progarms here, but if we had more, ordered as [p1, p2 parent of p1, p3 parent of p2, p4 parent of p3, ...], we'd just trim any unverified enrollments from END of the array (but not beginning).
Maybe there's a better solution ... ☝️ made sense to me, though.
Issue 2
In the above scenario, the UI does not reflect the error at all.
Could we show an error text or something? Even an alert within the card... might look weird but would be very visible.
|
@ChristopherChudzicki Thanks, this is ready for another look. I implemented the suggestion for fixing the bug and an error is now displayed:
|

What are the relevant tickets?
Closes https://github.com/mitodl/hq/issues/12269
Description (What does it do?)
Learners who audit-enrolled in a course before purchasing a program that includes that course were being sent to checkout when they clicked "Upgrade for certificate" on the program dashboard — even though their program purchase already entitles them to a free verified upgrade for that course.
The mitxonline backend already supported a free, one-click upgrade path for this case (
add_verified_program_course_enrollment/useCreateVerifiedProgramEnrollment, the same endpoint the "Start" button uses for unenrolled courses in a verified program). The gap was entirely on the frontend:EnrolledCourseCard's upgrade link was hard-wired touseReplaceBasketItem, and the card never received the ancestor program-enrollment context thatUnenrolledCourseCardalready had access to.This PR:
entry.ancestorContext(already computed by the program dashboard'sDashboardCourseEntry) fromCoursewareCardintoEnrolledCourseCard, for the"course"kind's enrolled branch.EnrolledCourseCard, when the enrollment is audit and the ancestor program enrollment is verified, the "Upgrade for certificate" link now callsuseCreateVerifiedProgramEnrollment(one-click, free) instead ofuseReplaceBasketItem(checkout), and redirects to courseware on success — matching the "Start" button's behavior, per the issue's suggested fix.No backend changes were required —
add_verified_program_course_enrollmentalready upgrades a pre-existing audit course-run enrollment to verified via a zero-value order when the program enrollment is verified.How can this be tested?
localdev/seed_verified_program_upgrade_repro.py:ProgramEnrollment, and an auditCourseRunEnrollmentin the run for the given user. Idempotent — safe to re-run. Here is the code for the one shot:/dashboard/program/<id>)./cart/.CourseRunEnrollment.enrollment_modefor that run/user should now beverified.Automated coverage:
EnrolledCourseCard.test.tsxadds 3 tests for the verified-program path (label omits price, click one-click-enrolls and redirects, error handling), alongside the existing checkout-path tests (unchanged). Full suite (97 tests),typecheck, andlintall pass.Additional Context
ancestorContext, so a course enrolled outside its program dashboard won't get this one-click behavior even if the learner has a verified enrollment in some other program containing that course. Per team discussion, this is expected to be rare in practice (course-run enrollments for courses in an actively-enrolled program are supposed to be hidden from My Learning), so it's out of scope here.