diff --git a/src/components/course/course-header/CourseImportantDates.jsx b/src/components/course/course-header/CourseImportantDates.jsx index ebdaa81ee..8e1625022 100644 --- a/src/components/course/course-header/CourseImportantDates.jsx +++ b/src/components/course/course-header/CourseImportantDates.jsx @@ -90,10 +90,11 @@ const CourseImportantDates = () => { let soonestExpiringAllocatedAssignmentCourseStartDate = null; if (soonestExpiringAssignment) { const soonestExpiringAllocatedAssignment = courseMetadata.availableCourseRuns.find( - (courseRun) => courseRun.key === soonestExpiringAssignment?.contentKey, + (courseRun) => courseRun.key === soonestExpiringAssignment.contentKey, ); - soonestExpiringAllocatedAssignmentCourseStartDate = soonestExpiringAllocatedAssignment - && getNormalizedStartDate(soonestExpiringAllocatedAssignment); + if (soonestExpiringAllocatedAssignment) { + soonestExpiringAllocatedAssignmentCourseStartDate = getNormalizedStartDate(soonestExpiringAllocatedAssignment); + } } // Parse logic of date existence and labels const enrollByDate = soonestExpirationDate ?? null; diff --git a/src/components/course/data/utils.jsx b/src/components/course/data/utils.jsx index 5f4873d65..c19d769b6 100644 --- a/src/components/course/data/utils.jsx +++ b/src/components/course/data/utils.jsx @@ -60,6 +60,9 @@ export function weeksRemainingUntilEnd(courseRun) { } export function hasTimeToComplete(courseRun) { + if ((!courseRun.weeksToComplete || !courseRun.end) && dayjs(courseRun.start).isAfter(dayjs(), 'minute')) { + return true; + } return courseRun.weeksToComplete <= weeksRemainingUntilEnd(courseRun); } @@ -91,12 +94,11 @@ export const getNormalizedStartDate = ({ return todayToIso; } const startDateIso = dayjs(start).toISOString(); - if (isCourseSelfPaced({ pacingType })) { + if (isCourseSelfPaced(pacingType)) { if (hasTimeToComplete({ end, weeksToComplete }) || isWithinMinimumStartDateThreshold({ start })) { // always today's date (incentives enrollment) return todayToIso; } - return startDateIso; } return startDateIso; }; diff --git a/src/components/dashboard/main-content/course-enrollments/course-cards/BaseCourseCard.jsx b/src/components/dashboard/main-content/course-enrollments/course-cards/BaseCourseCard.jsx index b9f96b924..5996e0550 100644 --- a/src/components/dashboard/main-content/course-enrollments/course-cards/BaseCourseCard.jsx +++ b/src/components/dashboard/main-content/course-enrollments/course-cards/BaseCourseCard.jsx @@ -410,7 +410,7 @@ const BaseCourseCard = ({ weeksToComplete: null, }); const formattedStartDate = dayjs(courseStartDate).format('MMMM Do, YYYY'); - const isCourseStarted = dayjs(courseStartDate).isBefore(dayjs()); + const isCourseStarted = dayjs(startDate).isBefore(dayjs(), 'minute'); if (formattedStartDate && !isCourseStarted) { return Starts {formattedStartDate}; } @@ -419,7 +419,7 @@ const BaseCourseCard = ({ const renderEndDate = () => { const formattedEndDate = endDate ? dayjs(endDate).format('MMMM Do, YYYY') : null; - const isCourseStarted = dayjs(startDate).isBefore(dayjs()); + const isCourseStarted = dayjs(startDate).isBefore(dayjs(), 'minute'); if (formattedEndDate && isCourseStarted && type !== COURSE_STATUSES.completed) { return Ends {formattedEndDate}; } diff --git a/src/components/dashboard/main-content/course-enrollments/course-cards/tests/BaseCourseCard.test.jsx b/src/components/dashboard/main-content/course-enrollments/course-cards/tests/BaseCourseCard.test.jsx index 8f94880b0..a0a1e55e0 100644 --- a/src/components/dashboard/main-content/course-enrollments/course-cards/tests/BaseCourseCard.test.jsx +++ b/src/components/dashboard/main-content/course-enrollments/course-cards/tests/BaseCourseCard.test.jsx @@ -20,6 +20,7 @@ import { } from '../../../../../app/data/services/data/__factories__'; import { COURSE_STATUSES } from '../../data'; import { isCourseEnded } from '../../../../../../utils/common'; +import { getNormalizedStartDate } from '../../../../../course/data'; jest.mock('@edx/frontend-enterprise-utils', () => ({ ...jest.requireActual('@edx/frontend-enterprise-utils'), @@ -129,14 +130,24 @@ describe('', () => { it.each([{ startDate: dayjs().toISOString(), + endDate: dayjs().add(5, 'days').toISOString(), + isStarted: false, }, { startDate: dayjs().subtract(1, 'day').toISOString(), + endDate: dayjs().add(5, 'days').toISOString(), + isStarted: true, }, { startDate: dayjs().add(1, 'day').toISOString(), - }])('renders with different startDate values', ({ startDate }) => { - const formattedStartDate = dayjs(startDate).format('MMMM Do, YYYY'); - const isCourseStarted = dayjs(startDate) <= dayjs(); - + endDate: dayjs().add(5, 'days').toISOString(), + isStarted: false, + }])('renders with different startDate values (%s)', ({ startDate, endDate, isStarted }) => { + const courseStartDate = getNormalizedStartDate({ + start: startDate, + end: endDate, + pacingType: 'self', + weeksToComplete: null, + }); + const formatStartDate = (date) => dayjs(date).format('MMMM Do, YYYY'); renderWithRouter( ', () => { productSource="2u" mode="executive-education" startDate={startDate} + endDate={endDate} orgName="some_name" pacing="self" />, ); - if (!isCourseStarted) { - expect(screen.getByText(`Starts ${formattedStartDate}`)).toBeInTheDocument(); + if (isStarted) { + expect(screen.queryByText(`Starts ${formatStartDate(courseStartDate)}`)).not.toBeInTheDocument(); } else { - expect(screen.queryByText(`Starts ${formattedStartDate}`)).not.toBeInTheDocument(); + expect(screen.getByText(`Starts ${formatStartDate(courseStartDate)}`)).toBeInTheDocument(); } }); @@ -204,9 +216,15 @@ describe('', () => { }); it.each([ - { type: COURSE_STATUSES.inProgress }, - { type: COURSE_STATUSES.completed }, - ])('renders endDate based on the course state', ({ type }) => { + { + type: COURSE_STATUSES.inProgress, + shouldRenderEndDate: true, + }, + { + type: COURSE_STATUSES.completed, + shouldRenderEndDate: false, + }, + ])('renders endDate based on the course state', ({ type, shouldRenderEndDate }) => { const startDate = dayjs().subtract(7, 'days').toISOString(); const endDate = dayjs().add(7, 'days').toISOString(); const formattedEndDate = dayjs(endDate).format('MMMM Do, YYYY'); @@ -221,10 +239,9 @@ describe('', () => { endDate={endDate} mode="executive-education" orgName="some_name" - pacing="self" + pacing="instructor" />, ); - const shouldRenderEndDate = dayjs(startDate) <= dayjs() && type !== 'completed'; if (shouldRenderEndDate) { expect(screen.getByText(`Ends ${formattedEndDate}`)).toBeInTheDocument(); } else {