From 41df13b05908e4ef82580f47dc903c2909c2ef7e Mon Sep 17 00:00:00 2001 From: leangseu-edx <83240113+leangseu-edx@users.noreply.github.com> Date: Wed, 26 Oct 2022 15:22:06 -0400 Subject: [PATCH] lk/resume button url (#56) --- .../__snapshots__/index.test.jsx.snap | 29 +++++----------- .../components/CourseCardMenu/index.jsx | 31 ++++++++++------- .../components/CourseCardMenu/index.test.jsx | 30 ++++++++++------ src/containers/EmailSettingsModal/hooks.js | 3 +- .../EmailSettingsModal/hooks.test.js | 4 +-- src/containers/SelectSessionModal/hooks.js | 4 +-- .../SelectSessionModal/hooks.test.js | 10 +++--- src/data/redux/app/selectors/courseCard.js | 9 +++-- .../redux/app/selectors/courseCard.test.js | 16 ++++----- src/data/redux/app/selectors/currentList.js | 2 +- .../redux/app/selectors/currentList.test.js | 4 +-- src/data/services/lms/fakeData/courses.js | 34 +++++++------------ 12 files changed, 82 insertions(+), 94 deletions(-) diff --git a/src/containers/CourseCard/components/CourseCardMenu/__snapshots__/index.test.jsx.snap b/src/containers/CourseCard/components/CourseCardMenu/__snapshots__/index.test.jsx.snap index 5b01a7f..9a42480 100644 --- a/src/containers/CourseCard/components/CourseCardMenu/__snapshots__/index.test.jsx.snap +++ b/src/containers/CourseCard/components/CourseCardMenu/__snapshots__/index.test.jsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`CourseCardMenu enrolled, share enabled snapshot 1`] = ` +exports[`CourseCardMenu enrolled, share enabled, email setting enable snapshot 1`] = ` Share to Twitter @@ -77,8 +78,9 @@ exports[`CourseCardMenu masquerading snapshot 1`] = ` Share to Twitter @@ -98,7 +100,7 @@ exports[`CourseCardMenu masquerading snapshot 1`] = ` `; -exports[`CourseCardMenu not enrolled, share disabled snapshot 1`] = ` +exports[`CourseCardMenu not enrolled, share disabled, email setting disabled snapshot 1`] = ` - - - Email settings - - + - `; diff --git a/src/containers/CourseCard/components/CourseCardMenu/index.jsx b/src/containers/CourseCard/components/CourseCardMenu/index.jsx index 437c7e4..c21a412 100644 --- a/src/containers/CourseCard/components/CourseCardMenu/index.jsx +++ b/src/containers/CourseCard/components/CourseCardMenu/index.jsx @@ -17,7 +17,7 @@ export const CourseCardMenu = ({ cardId }) => { const emailSettingsModal = useEmailSettings(); const unenrollModal = useUnenrollData(); const { courseName } = appHooks.useCardCourseData(cardId); - const { isEnrolled } = appHooks.useCardEnrollmentData(cardId); + const { isEnrolled, isEmailEnabled } = appHooks.useCardEnrollmentData(cardId); const { // facebook, twitter, @@ -46,13 +46,15 @@ export const CourseCardMenu = ({ cardId }) => { {formatMessage(messages.unenroll)} )} - - {formatMessage(messages.emailSettings)} - + {isEmailEnabled && ( + + {formatMessage(messages.emailSettings)} + + )} {/* Disabled pending PM decision on missing quote param in updated FB api. {facebook.isEnabled && ( @@ -76,6 +78,7 @@ export const CourseCardMenu = ({ cardId }) => { courseName, socialBrand: twitter.socialBrand, })} + className="w-100 text-left" > {formatMessage(messages.shareToTwitter)} @@ -88,11 +91,13 @@ export const CourseCardMenu = ({ cardId }) => { closeModal={unenrollModal.hide} cardId={cardId} /> - + {isEmailEnabled && ( + + )} ); }; diff --git a/src/containers/CourseCard/components/CourseCardMenu/index.test.jsx b/src/containers/CourseCard/components/CourseCardMenu/index.test.jsx index b10e395..b515260 100644 --- a/src/containers/CourseCard/components/CourseCardMenu/index.test.jsx +++ b/src/containers/CourseCard/components/CourseCardMenu/index.test.jsx @@ -42,8 +42,8 @@ const defaultSocialShare = { }, twitter: { isEnabled: true, - shareUrl: 'facebook-share-url', - socialBrand: 'facebook-social-brand', + shareUrl: 'twitter-share-url', + socialBrand: 'twitter-social-brand', }, }; const courseName = 'test-course-name'; @@ -56,10 +56,10 @@ describe('CourseCardMenu', () => { useUnenrollData.mockReturnValue(defaultUnenrollModal); appHooks.useCardSocialSettingsData.mockReturnValue(defaultSocialShare); appHooks.useCardCourseData.mockReturnValue({ courseName }); - appHooks.useCardEnrollmentData.mockReturnValue({ isEnrolled: true }); + appHooks.useCardEnrollmentData.mockReturnValue({ isEnrolled: true, isEmailEnabled: true }); appHooks.useMasqueradeData.mockReturnValue({ isMasquerading: false }); }); - describe('enrolled, share enabled', () => { + describe('enrolled, share enabled, email setting enable', () => { beforeEach(() => { wrapper = shallow(); }); @@ -68,7 +68,9 @@ describe('CourseCardMenu', () => { }); it('renders share buttons', () => { // expect(wrapper.find('FacebookShareButton').length).toEqual(1); - expect(wrapper.find('TwitterShareButton').length).toEqual(1); + el = wrapper.find('TwitterShareButton'); + expect(el.length).toEqual(1); + expect(el.prop('url')).toEqual('twitter-share-url'); }); it('renders enabled unenroll modal toggle', () => { el = wrapper.find({ 'data-testid': 'unenrollModalToggle' }); @@ -78,21 +80,25 @@ describe('CourseCardMenu', () => { el = wrapper.find({ 'data-testid': 'emailSettingsModalToggle' }); expect(el.props().disabled).toEqual(false); }); + it('renders enabled email settings modal toggle', () => { + el = wrapper.find({ 'data-testid': 'emailSettingsModalToggle' }); + expect(el.props().disabled).toEqual(false); + }); }); - describe('not enrolled, share disabled', () => { + describe('not enrolled, share disabled, email setting disabled', () => { beforeEach(() => { appHooks.useCardSocialSettingsData.mockReturnValueOnce({ ...defaultSocialShare, twitter: { ...defaultSocialShare.twitter, isEnabled: false }, // facebook: { ...defaultSocialShare.facebook, isEnabled: false }, }); - appHooks.useCardEnrollmentData.mockReturnValueOnce({ isEnrolled: false }); + appHooks.useCardEnrollmentData.mockReturnValueOnce({ isEnrolled: false, isEmailEnabled: false }); wrapper = shallow(); }); test('snapshot', () => { expect(wrapper).toMatchSnapshot(); }); - it('renders share buttons', () => { + it('does not renders share buttons', () => { // expect(wrapper.find('FacebookShareButton').length).toEqual(0); expect(wrapper.find('TwitterShareButton').length).toEqual(0); }); @@ -100,9 +106,9 @@ describe('CourseCardMenu', () => { el = wrapper.find({ 'data-testid': 'unenrollModalToggle' }); expect(el.length).toEqual(0); }); - it('renders enabled email settings modal toggle', () => { + it('does not render email settings modal toggle', () => { el = wrapper.find({ 'data-testid': 'emailSettingsModalToggle' }); - expect(el.props().disabled).toEqual(false); + expect(el.length).toEqual(0); }); }); describe('masquerading', () => { @@ -115,7 +121,9 @@ describe('CourseCardMenu', () => { }); it('renders share buttons', () => { // expect(wrapper.find('FacebookShareButton').length).toEqual(1); - expect(wrapper.find('TwitterShareButton').length).toEqual(1); + el = wrapper.find('TwitterShareButton'); + expect(el.length).toEqual(1); + expect(el.prop('url')).toEqual('twitter-share-url'); }); it('renders disabled unenroll modal toggle', () => { el = wrapper.find({ 'data-testid': 'unenrollModalToggle' }); diff --git a/src/containers/EmailSettingsModal/hooks.js b/src/containers/EmailSettingsModal/hooks.js index 1d07ce5..2680c58 100644 --- a/src/containers/EmailSettingsModal/hooks.js +++ b/src/containers/EmailSettingsModal/hooks.js @@ -22,7 +22,8 @@ export const useEmailData = ({ ); const save = React.useCallback( () => { - dispatch(thunkActions.app.updateEmailSettings(cardId, isOptedOut)); + // update email settings 2nd arg is true if opting in, false if opting out + dispatch(thunkActions.app.updateEmailSettings(cardId, !isOptedOut)); closeModal(); }, [cardId, closeModal, dispatch, isOptedOut], diff --git a/src/containers/EmailSettingsModal/hooks.test.js b/src/containers/EmailSettingsModal/hooks.test.js index 307e25d..718dd6f 100644 --- a/src/containers/EmailSettingsModal/hooks.test.js +++ b/src/containers/EmailSettingsModal/hooks.test.js @@ -61,8 +61,8 @@ describe('EmailSettingsModal hooks', () => { describe('save', () => { it('calls dispatch with thunkActions.app.updateEmailSettings', () => { out.save.useCallback.cb(); - expect(thunkActions.app.updateEmailSettings).toHaveBeenCalledWith(cardId, out.isOptedOut); - expect(dispatch).toHaveBeenCalledWith(thunkActions.app.updateEmailSettings(cardId, out.isOptedOut)); + expect(thunkActions.app.updateEmailSettings).toHaveBeenCalledWith(cardId, !out.isOptedOut); + expect(dispatch).toHaveBeenCalledWith(thunkActions.app.updateEmailSettings(cardId, !out.isOptedOut)); }); it('calls closeModal', () => { out.save.useCallback.cb(); diff --git a/src/containers/SelectSessionModal/hooks.js b/src/containers/SelectSessionModal/hooks.js index 1e1aaf1..509b045 100644 --- a/src/containers/SelectSessionModal/hooks.js +++ b/src/containers/SelectSessionModal/hooks.js @@ -42,9 +42,9 @@ export const useSelectSessionModalData = () => { const handleSelection = ({ target: { value } }) => setSelectedSession(value); const handleSubmit = () => { if (selectedSession === LEAVE_OPTION) { - return dispatch(thunkActions.requests.leaveEntitlementSession({ uuid })); + return dispatch(thunkActions.app.leaveEntitlementSession({ uuid })); } - return dispatch(thunkActions.requests.updateEntitlementEnrollment({ uuid, courseId: selectedSession })); + return dispatch(thunkActions.app.switchEntitlementEnrollment({ uuid, courseId: selectedSession })); }; return { diff --git a/src/containers/SelectSessionModal/hooks.test.js b/src/containers/SelectSessionModal/hooks.test.js index e211a15..c78af8a 100644 --- a/src/containers/SelectSessionModal/hooks.test.js +++ b/src/containers/SelectSessionModal/hooks.test.js @@ -24,9 +24,9 @@ jest.mock('data/redux', () => ({ }, }, thunkActions: { - requests: { - updateEntitlementEnrollment: jest.fn((...args) => ({ updateEntitlementSession: args })), - leaveEntitlementSession: jest.fn((...args) => ({ leaveEntitlementSession: args })), + app: { + leaveEntitlementSession: jest.fn(), + switchEntitlementEnrollment: jest.fn(), }, }, })); @@ -111,14 +111,14 @@ describe('SelectSessionModal hooks', () => { state.mockVal(state.keys.selectedSession, testValue); runHook({}); expect(out.handleSubmit()).toEqual(dispatch( - thunkActions.requests.updateEntitlementEnrollment({ courseId: testValue, uuid }), + thunkActions.app.switchEntitlementEnrollment({ courseId: testValue, uuid }), )); }); it('dispatches leaveEntitlementSession if LEAVE_OPTION is selected', () => { state.mockVal(state.keys.selectedSession, LEAVE_OPTION); runHook({}); expect(out.handleSubmit()).toEqual(dispatch( - thunkActions.requests.leaveEntitlementSession({ uuid }), + thunkActions.app.leaveEntitlementSession({ uuid }), )); }); }); diff --git a/src/data/redux/app/selectors/courseCard.js b/src/data/redux/app/selectors/courseCard.js index bc01cad..dc13015 100644 --- a/src/data/redux/app/selectors/courseCard.js +++ b/src/data/redux/app/selectors/courseCard.js @@ -1,5 +1,5 @@ import { StrictDict } from 'utils'; -import { baseAppUrl, learningMfeUrl } from 'data/services/lms/urls'; +import { baseAppUrl } from 'data/services/lms/urls'; import * as module from './courseCard'; import * as simpleSelectors from './simpleSelectors'; @@ -56,9 +56,9 @@ export const courseCard = StrictDict({ marketingUrl: courseRun.marketingUrl, upgradeUrl: courseRun.upgradeUrl, - progressUrl: learningMfeUrl(courseRun.progressUrl), - resumeUrl: learningMfeUrl(courseRun.resumeUrl), - unenrollUrl: learningMfeUrl(courseRun.unenrollUrl), + progressUrl: baseAppUrl(courseRun.progressUrl), + resumeUrl: baseAppUrl(courseRun.resumeUrl), // resume will route this to learning mfe. + unenrollUrl: baseAppUrl(courseRun.unenrollUrl), }), ), enrollment: mkCardSelector( @@ -74,7 +74,6 @@ export const courseCard = StrictDict({ isEnrolled: enrollment.isEnrolled, lastEnrolled: enrollment.lastEnrolled, hasStarted: enrollment.hasStarted, - hasFinished: enrollment.hasFinished, accessExpirationDate: module.loadDateVal(enrollment.accessExpirationDate), canUpgrade: enrollment.canUpgrade, diff --git a/src/data/redux/app/selectors/courseCard.test.js b/src/data/redux/app/selectors/courseCard.test.js index b6fcd45..38aa664 100644 --- a/src/data/redux/app/selectors/courseCard.test.js +++ b/src/data/redux/app/selectors/courseCard.test.js @@ -1,12 +1,11 @@ import { keyStore } from 'utils'; -import urls from 'data/services/lms/urls'; +import { baseAppUrl } from 'data/services/lms/urls'; import simpleSelectors from './simpleSelectors'; import * as module from './courseCard'; jest.mock('data/services/lms/urls', () => ({ baseAppUrl: url => ({ baseAppUrl: url }), - learningMfeUrl: url => ({ learningMfeUrl: url }), })); jest.mock('./simpleSelectors', () => ({ @@ -18,7 +17,6 @@ jest.mock('./simpleSelectors', () => ({ const { courseCard } = module; const { cardSimpleSelectors } = simpleSelectors; -const { baseAppUrl, learningMfeUrl } = urls; const moduleKeys = keyStore(module); @@ -181,10 +179,10 @@ describe('courseCard selectors module', () => { expect(selected.marketingUrl).toEqual(testData.marketingUrl); expect(selected.upgradeUrl).toEqual(testData.upgradeUrl); }); - it('passes [progressUrl, unenrollUrl, resumeUrl], converted to learningMfeUrls', () => { - expect(selected.progressUrl).toEqual(learningMfeUrl(testData.progressUrl)); - expect(selected.resumeUrl).toEqual(learningMfeUrl(testData.resumeUrl)); - expect(selected.unenrollUrl).toEqual(learningMfeUrl(testData.unenrollUrl)); + it('passes [progressUrl, unenrollUrl, resumeUrl], converted to baseAppUrl', () => { + expect(selected.progressUrl).toEqual(baseAppUrl(testData.progressUrl)); + expect(selected.resumeUrl).toEqual(baseAppUrl(testData.resumeUrl)); + expect(selected.unenrollUrl).toEqual(baseAppUrl(testData.unenrollUrl)); }); }); describe('enrollment selector', () => { @@ -198,7 +196,6 @@ describe('courseCard selectors module', () => { isEnrolled: 'test-is-enrolled', lastEnrolled: 'test-last-enrolled', hasStarted: 'test-has-started', - hasFinished: 'test-has-finished', accessExpirationDate: '3000-10-20', canUpgrade: 'test-can-upgrade', isAudit: 'test-is-audit', @@ -213,10 +210,9 @@ describe('courseCard selectors module', () => { it('returns { isEnrolled: false } object if null enrollment received', () => { expect(selector(null)).toEqual({ isEnrolled: false }); }); - it('passes [coursewareAccess, hasStarted, hasFinished, isEnrolled, lastEnrolled]', () => { + it('passes [coursewareAccess, hasStarted, isEnrolled, lastEnrolled]', () => { expect(selected.coursewareAccess).toEqual(testData.coursewareAccess); expect(selected.hasStarted).toEqual(testData.hasStarted); - expect(selected.hasFinished).toEqual(testData.hasFinished); expect(selected.isEnrolled).toEqual(testData.isEnrolled); expect(selected.lastEnrolled).toEqual(testData.lastEnrolled); }); diff --git a/src/data/redux/app/selectors/currentList.js b/src/data/redux/app/selectors/currentList.js index 3c9bd50..dbcbd6b 100644 --- a/src/data/redux/app/selectors/currentList.js +++ b/src/data/redux/app/selectors/currentList.js @@ -12,7 +12,7 @@ export const sortFn = (transform, { reverse }) => (v1, v2) => { export const courseFilters = StrictDict({ [FilterKeys.notEnrolled]: (course) => !course.enrollment.isEnrolled, - [FilterKeys.done]: (course) => course.enrollment.hasFinished, + [FilterKeys.done]: (course) => course.courseRun.isArchived, [FilterKeys.upgraded]: (course) => course.enrollment.isVerified, [FilterKeys.inProgress]: (course) => course.enrollment.hasStarted, [FilterKeys.notStarted]: (course) => !course.enrollment.hasStarted, diff --git a/src/data/redux/app/selectors/currentList.test.js b/src/data/redux/app/selectors/currentList.test.js index 49d5c21..4ba714e 100644 --- a/src/data/redux/app/selectors/currentList.test.js +++ b/src/data/redux/app/selectors/currentList.test.js @@ -47,8 +47,8 @@ describe('courseList selector module', () => { }); test('done returns true iff learner has finished course', () => { filterFn = courseFilters[FilterKeys.done]; - expect(filterFn({ enrollment: { hasFinished: true } })).toEqual(true); - expect(filterFn({ enrollment: { hasFinished: false } })).toEqual(false); + expect(filterFn({ courseRun: { isArchived: true } })).toEqual(true); + expect(filterFn({ courseRun: { isArchived: false } })).toEqual(false); }); test('upgraded returns true if learner is verified', () => { filterFn = courseFilters[FilterKeys.upgraded]; diff --git a/src/data/services/lms/fakeData/courses.js b/src/data/services/lms/fakeData/courses.js index 2965a09..44f94e4 100644 --- a/src/data/services/lms/fakeData/courses.js +++ b/src/data/services/lms/fakeData/courses.js @@ -131,7 +131,6 @@ export const genEnrollmentData = (data = {}) => ({ }, accessExpirationDate: ((data.isEnrolled === false) ? null : futureDate), canUpgrade: (data.isVerified ? null : true), - hasFinished: false, hasStarted: false, isAudit: !data.isVerified && (data.isEnrolled !== false), isAuditAccessExpired: data.isVerified ? null : false, @@ -353,11 +352,10 @@ export const courseRuns = [ { courseName: 'Verified Course, Learner finished, cert not earned', enrollment: { - hasFinished: true, hasStarted: true, isVerified: true, }, - courseRun: { isStarted: true }, + courseRun: { isStarted: true, isArchived: true }, gradeData: { isPassing: false }, certificate: { isEarned: false, @@ -367,11 +365,10 @@ export const courseRuns = [ { courseName: 'Verified Course, Learner finished, Cert earned but not available', enrollment: { - hasFinished: true, hasStarted: true, isVerified: true, }, - courseRun: { isStarted: true }, + courseRun: { isStarted: true, isArchived: true }, certificate: { isEarned: true, availableDate: futureDate, @@ -381,22 +378,20 @@ export const courseRuns = [ { courseName: 'Verified Course, Learner finished, Passing, Certificate restricted', enrollment: { - hasFinished: true, hasStarted: true, isVerified: true, }, - courseRun: { isStarted: true }, + courseRun: { isStarted: true, isArchived: true }, certificate: { isRestricted: true }, }, // verified, learner finished, cert earned, downloadable (web + link) { courseName: 'Verified Course, Learner finished, Passing, Certificate downloadable and viewable', enrollment: { - hasFinished: true, hasStarted: true, isVerified: true, }, - courseRun: { isStarted: true }, + courseRun: { isStarted: true, isArchived: true }, certificate: { isEarned: true, isDownloadable: true, @@ -408,12 +403,12 @@ export const courseRuns = [ { courseName: 'Verified Course, Course ended, Learner finished, Passing, Certificate downloadable', enrollment: { - hasFinished: true, hasStarted: true, isVerified: true, }, courseRun: { isStarted: true, + isArchived: true, endDate: pastDate, }, certificate: { @@ -422,11 +417,10 @@ export const courseRuns = [ availableDate: pastDate, }, }, - // verified, course archived, learner finished, cert earned, downloadable (web + link) + // verified, course ended, learner finished, cert earned, downloadable (web + link) { - courseName: 'Verified Course, Course archived, Learner finished, Passing, Certificate downloadable and viewable', + courseName: 'Verified Course, Course ended, Learner finished, Passing, Certificate downloadable and viewable', enrollment: { - hasFinished: true, hasStarted: true, isVerified: true, }, @@ -525,9 +519,8 @@ export const courseRuns = [ courseName: 'Entitlement Course, Learner finished but did not pass', enrollment: { isVerified: true, - hasFinished: false, }, - courseRun: { isStarted: true }, + courseRun: { isStarted: true, isArchived: false }, entitlement: { uuid: genEntitlementUUID(4), availableSessions: null, @@ -544,9 +537,8 @@ export const courseRuns = [ courseName: 'Entitlement course, Learner finished and passed, Cannot refund, Previewable Cert', enrollment: { isVerified: true, - hasFinished: false, }, - courseRun: { isStarted: true }, + courseRun: { isStarted: true, isArchived: false }, entitlement: { uuid: genEntitlementUUID(5), availableSessions: null, @@ -568,10 +560,10 @@ export const courseRuns = [ courseName: 'Entitlement Course, Learner finished and failed, Cannot refund, Course ended', enrollment: { isVerified: true, - hasFinished: false, }, courseRun: { isStarted: true, + isArchived: false, endDate: pastDate, }, entitlement: { @@ -585,12 +577,11 @@ export const courseRuns = [ }, gradeData: { isPassing: false }, }, - // Entitlement - Learner finished and passed. cannot refund. course archived. cert downloadable + // Entitlement - Learner finished and passed. cannot refund. cert downloadable { - courseName: 'Entitlement Course, Learner finished and passed, Cannot refund, Course archived, Cert downloadable', + courseName: 'Entitlement Course, Learner finished and passed, Cannot refund, Cert downloadable', enrollment: { isVerified: true, - hasFinished: false, }, courseRun: { isArchived: true, @@ -729,7 +720,6 @@ export const compileEntitlementData = ({ courseName, ...data }, index) => { lastEnrolled: null, accessExpirationDate: null, canUpgrade: false, - hasFinished: false, hasStarted: false, isAudit: false, isAuditAccessExpired: false,