From 3f6cf6d19c40a6d0df63bd53ce1b8566861029ac Mon Sep 17 00:00:00 2001 From: Adam Stankiewicz Date: Thu, 3 Oct 2024 11:19:33 -0400 Subject: [PATCH] fix: ensure consistency around start dates on course run cards in Course page (#1203) --- .../tests/useCourseRunCardHeading.test.jsx | 42 +++++++++++++++---- .../data/hooks/useCourseRunCardHeading.js | 9 +++- src/components/course/data/utils.jsx | 2 +- 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/components/course/course-header/data/hooks/tests/useCourseRunCardHeading.test.jsx b/src/components/course/course-header/data/hooks/tests/useCourseRunCardHeading.test.jsx index f2ad5cb84c..abbff05375 100644 --- a/src/components/course/course-header/data/hooks/tests/useCourseRunCardHeading.test.jsx +++ b/src/components/course/course-header/data/hooks/tests/useCourseRunCardHeading.test.jsx @@ -1,6 +1,7 @@ import { IntlProvider } from '@edx/frontend-platform/i18n'; import { renderHook } from '@testing-library/react-hooks'; import MockDate from 'mockdate'; +import dayjs from 'dayjs'; import '@testing-library/jest-dom/extend-expect'; import { hasTimeToComplete } from '../../../../data/utils'; @@ -8,6 +9,7 @@ import { hasTimeToComplete } from '../../../../data/utils'; import { MOCK_COURSE_RUN_START } from './constants'; import useCourseRunCardHeading from '../useCourseRunCardHeading'; import { COURSE_PACING_MAP } from '../../../../data/constants'; +import { DATE_FORMAT } from '../../constants'; jest.mock('../../../../data/utils', () => ({ ...jest.requireActual('../../../../data/utils'), @@ -39,13 +41,39 @@ describe('useCourseRunCardHeading', () => { }); it.each([ - { hasTimeToCompleteOverride: true }, - { hasTimeToCompleteOverride: false }, - ])('handles current, self-paced, unenrolled course run (%s)', ({ hasTimeToCompleteOverride }) => { + // test case: really old start date with time to complete + { + hasTimeToCompleteOverride: true, + startDate: dayjs(MOCK_COURSE_RUN_START).toISOString(), + expectedFormattedStartDate: `Starts ${dayjs().format(DATE_FORMAT)}`, + }, + // test case: really old start date without time to complete + { + hasTimeToCompleteOverride: false, + startDate: dayjs(MOCK_COURSE_RUN_START).toISOString(), + expectedFormattedStartDate: `Starts ${dayjs().format(DATE_FORMAT)}`, + }, + // test case: recent start date with time to complete + { + hasTimeToCompleteOverride: true, + startDate: dayjs().subtract(5, 'day').toISOString(), + expectedFormattedStartDate: `Starts ${dayjs().format(DATE_FORMAT)}`, + }, + // test case: recent start date without time to complete + { + hasTimeToCompleteOverride: false, + startDate: dayjs().subtract(5, 'day').toISOString(), + expectedFormattedStartDate: `Started ${dayjs().subtract(5, 'day').format(DATE_FORMAT)}`, + }, + ])('handles current, self-paced, unenrolled course run (%s)', ({ + hasTimeToCompleteOverride, + startDate, + expectedFormattedStartDate, + }) => { hasTimeToComplete.mockReturnValue(hasTimeToCompleteOverride); // mock current date - MockDate.set(new Date('2023-05-20T12:00:00Z')); + MockDate.set(dayjs().toDate()); const { result } = renderHook( () => useCourseRunCardHeading({ @@ -53,7 +81,7 @@ describe('useCourseRunCardHeading', () => { isUserEnrolled: false, courseRun: { pacingType: COURSE_PACING_MAP.SELF_PACED, - start: MOCK_COURSE_RUN_START, + start: startDate, }, }), { wrapper }, @@ -61,10 +89,10 @@ describe('useCourseRunCardHeading', () => { if (hasTimeToCompleteOverride) { // assert shown start date matches the above mocked current date - expect(result.current).toEqual('Starts May 20'); + expect(result.current).toEqual(expectedFormattedStartDate); } else { // assert shown start date matches the start date of the course run - expect(result.current).toEqual('Started Apr 20'); + expect(result.current).toEqual(expectedFormattedStartDate); } }); diff --git a/src/components/course/course-header/data/hooks/useCourseRunCardHeading.js b/src/components/course/course-header/data/hooks/useCourseRunCardHeading.js index 4bc67380b5..725558956c 100644 --- a/src/components/course/course-header/data/hooks/useCourseRunCardHeading.js +++ b/src/components/course/course-header/data/hooks/useCourseRunCardHeading.js @@ -1,7 +1,12 @@ import dayjs from 'dayjs'; import { defineMessages, useIntl } from '@edx/frontend-platform/i18n'; -import { getCourseStartDate, hasTimeToComplete, isCourseSelfPaced } from '../../../data/utils'; +import { + getCourseStartDate, + hasTimeToComplete, + isCourseSelfPaced, + isWithinMinimumStartDateThreshold, +} from '../../../data/utils'; import { DATE_FORMAT } from '../constants'; const messages = defineMessages({ @@ -48,7 +53,7 @@ const useCourseRunCardHeading = ({ return intl.formatMessage(messages.courseStarted); } if (isCourseSelfPaced(courseRun.pacingType)) { - if (hasTimeToComplete(courseRun)) { + if (hasTimeToComplete(courseRun) || isWithinMinimumStartDateThreshold(courseRun)) { // always today's date (incentives enrollment) return intl.formatMessage(messages.courseStartDate, { startDate: dayjs().format(DATE_FORMAT), diff --git a/src/components/course/data/utils.jsx b/src/components/course/data/utils.jsx index c19d769b6c..6093307cfe 100644 --- a/src/components/course/data/utils.jsx +++ b/src/components/course/data/utils.jsx @@ -74,7 +74,7 @@ export function isCourseInstructorPaced(pacingType) { return [COURSE_PACING_MAP.INSTRUCTOR_PACED, COURSE_PACING_MAP.INSTRUCTOR].includes(pacingType); } -const isWithinMinimumStartDateThreshold = ({ start }) => dayjs(start).isBefore(dayjs().subtract(START_DATE_DEFAULT_TO_TODAY_THRESHOLD_DAYS, 'days')); +export const isWithinMinimumStartDateThreshold = ({ start }) => dayjs(start).isBefore(dayjs().subtract(START_DATE_DEFAULT_TO_TODAY_THRESHOLD_DAYS, 'days')); /** * If the start date of the course is before today offset by the START_DATE_DEFAULT_TO_TODAY_THRESHOLD_DAYS