From 777d3aa45c1a3eb88c254ab395a843436910b043 Mon Sep 17 00:00:00 2001 From: Maxwell Frank <92897870+MaxFrank13@users.noreply.github.com> Date: Mon, 13 Jan 2025 13:50:50 -0500 Subject: [PATCH 1/4] feat!: remove UpgradeButton (#536) --- .../BeginCourseButton.test.jsx | 2 +- .../CourseCardActions/ResumeButton.test.jsx | 2 +- .../CourseCardActions/UpgradeButton.test.jsx | 49 ------------------- .../ViewCourseButton.test.jsx | 2 +- .../BeginCourseButton.test.jsx.snap | 4 +- .../__snapshots__/ResumeButton.test.jsx.snap | 4 +- .../__snapshots__/UpgradeButton.test.jsx.snap | 32 ------------ .../ViewCourseButton.test.jsx.snap | 4 +- .../components/CourseCardActions/messages.js | 5 -- .../components/CourseCardImage.test.jsx | 4 +- .../components/CourseCardTitle.test.jsx | 4 +- .../CourseCardImage.test.jsx.snap | 2 +- .../CourseCardTitle.test.jsx.snap | 2 +- src/containers/CourseCard/components/hooks.js | 6 +-- .../CourseCard/components/hooks.test.js | 21 -------- src/data/redux/app/selectors/courseCard.js | 1 - .../redux/app/selectors/courseCard.test.js | 4 +- src/data/services/lms/api.js | 7 --- src/data/services/lms/api.test.js | 7 --- src/data/services/lms/fakeData/courses.js | 3 -- .../CourseCardActionSlot/index.jsx | 29 +++-------- src/tracking/constants.js | 7 --- src/tracking/trackers/course.js | 24 --------- src/tracking/trackers/course.test.js | 45 ----------------- 24 files changed, 26 insertions(+), 244 deletions(-) delete mode 100644 src/containers/CourseCard/components/CourseCardActions/UpgradeButton.test.jsx delete mode 100644 src/containers/CourseCard/components/CourseCardActions/__snapshots__/UpgradeButton.test.jsx.snap diff --git a/src/containers/CourseCard/components/CourseCardActions/BeginCourseButton.test.jsx b/src/containers/CourseCard/components/CourseCardActions/BeginCourseButton.test.jsx index f34a534c3..1559d4edf 100644 --- a/src/containers/CourseCard/components/CourseCardActions/BeginCourseButton.test.jsx +++ b/src/containers/CourseCard/components/CourseCardActions/BeginCourseButton.test.jsx @@ -27,7 +27,7 @@ reduxHooks.useCardCourseRunData.mockReturnValue({ homeUrl }); const execEdPath = (cardId) => `exec-ed-tracking-path=${cardId}`; reduxHooks.useCardExecEdTrackingParam.mockImplementation(execEdPath); reduxHooks.useTrackCourseEvent.mockImplementation( - (eventName, cardId, upgradeUrl) => ({ trackCourseEvent: { eventName, cardId, upgradeUrl } }), + (eventName, cardId, url) => ({ trackCourseEvent: { eventName, cardId, url } }), ); describe('BeginCourseButton', () => { diff --git a/src/containers/CourseCard/components/CourseCardActions/ResumeButton.test.jsx b/src/containers/CourseCard/components/CourseCardActions/ResumeButton.test.jsx index c4ca41e57..a96fc1aa2 100644 --- a/src/containers/CourseCard/components/CourseCardActions/ResumeButton.test.jsx +++ b/src/containers/CourseCard/components/CourseCardActions/ResumeButton.test.jsx @@ -26,7 +26,7 @@ reduxHooks.useCardCourseRunData.mockReturnValue({ resumeUrl }); const execEdPath = (cardId) => `exec-ed-tracking-path=${cardId}`; reduxHooks.useCardExecEdTrackingParam.mockImplementation(execEdPath); reduxHooks.useTrackCourseEvent.mockImplementation( - (eventName, cardId, upgradeUrl) => ({ trackCourseEvent: { eventName, cardId, upgradeUrl } }), + (eventName, cardId, url) => ({ trackCourseEvent: { eventName, cardId, url } }), ); let wrapper; diff --git a/src/containers/CourseCard/components/CourseCardActions/UpgradeButton.test.jsx b/src/containers/CourseCard/components/CourseCardActions/UpgradeButton.test.jsx deleted file mode 100644 index a539278cc..000000000 --- a/src/containers/CourseCard/components/CourseCardActions/UpgradeButton.test.jsx +++ /dev/null @@ -1,49 +0,0 @@ -import { shallow } from '@edx/react-unit-test-utils'; - -import track from 'tracking'; -import { reduxHooks } from 'hooks'; -import useActionDisabledState from '../hooks'; -import UpgradeButton from './UpgradeButton'; - -jest.mock('tracking', () => ({ - course: { - upgradeClicked: jest.fn().mockName('segment.trackUpgradeClicked'), - }, -})); - -jest.mock('hooks', () => ({ - reduxHooks: { - useCardCourseRunData: jest.fn(), - useTrackCourseEvent: jest.fn( - (eventName, cardId, upgradeUrl) => ({ trackCourseEvent: { eventName, cardId, upgradeUrl } }), - ), - }, -})); -jest.mock('../hooks', () => jest.fn(() => ({ disableUpgradeCourse: false }))); -jest.mock('./ActionButton', () => 'ActionButton'); - -describe('UpgradeButton', () => { - const props = { - cardId: 'cardId', - }; - const upgradeUrl = 'upgradeUrl'; - reduxHooks.useCardCourseRunData.mockReturnValue({ upgradeUrl }); - describe('snapshot', () => { - test('can upgrade', () => { - const wrapper = shallow(); - expect(wrapper.snapshot).toMatchSnapshot(); - expect(wrapper.instance.props.disabled).toEqual(false); - expect(wrapper.instance.props.onClick).toEqual(reduxHooks.useTrackCourseEvent( - track.course.upgradeClicked, - props.cardId, - upgradeUrl, - )); - }); - test('cannot upgrade', () => { - useActionDisabledState.mockReturnValueOnce({ disableUpgradeCourse: true }); - const wrapper = shallow(); - expect(wrapper.snapshot).toMatchSnapshot(); - expect(wrapper.instance.props.disabled).toEqual(true); - }); - }); -}); diff --git a/src/containers/CourseCard/components/CourseCardActions/ViewCourseButton.test.jsx b/src/containers/CourseCard/components/CourseCardActions/ViewCourseButton.test.jsx index 712f81032..186f40bde 100644 --- a/src/containers/CourseCard/components/CourseCardActions/ViewCourseButton.test.jsx +++ b/src/containers/CourseCard/components/CourseCardActions/ViewCourseButton.test.jsx @@ -15,7 +15,7 @@ jest.mock('hooks', () => ({ reduxHooks: { useCardCourseRunData: jest.fn(() => ({ homeUrl: 'homeUrl' })), useTrackCourseEvent: jest.fn( - (eventName, cardId, upgradeUrl) => ({ trackCourseEvent: { eventName, cardId, upgradeUrl } }), + (eventName, cardId, url) => ({ trackCourseEvent: { eventName, cardId, url } }), ), }, })); diff --git a/src/containers/CourseCard/components/CourseCardActions/__snapshots__/BeginCourseButton.test.jsx.snap b/src/containers/CourseCard/components/CourseCardActions/__snapshots__/BeginCourseButton.test.jsx.snap index 4604ab60b..0cbfdb62e 100644 --- a/src/containers/CourseCard/components/CourseCardActions/__snapshots__/BeginCourseButton.test.jsx.snap +++ b/src/containers/CourseCard/components/CourseCardActions/__snapshots__/BeginCourseButton.test.jsx.snap @@ -10,7 +10,7 @@ exports[`BeginCourseButton snapshot disabled snapshot 1`] = ` "trackCourseEvent": { "cardId": "cardId", "eventName": [MockFunction segment.enterCourseClicked], - "upgradeUrl": "home-urlexec-ed-tracking-path=cardId", + "url": "home-urlexec-ed-tracking-path=cardId", }, } } @@ -29,7 +29,7 @@ exports[`BeginCourseButton snapshot enabled snapshot 1`] = ` "trackCourseEvent": { "cardId": "cardId", "eventName": [MockFunction segment.enterCourseClicked], - "upgradeUrl": "home-urlexec-ed-tracking-path=cardId", + "url": "home-urlexec-ed-tracking-path=cardId", }, } } diff --git a/src/containers/CourseCard/components/CourseCardActions/__snapshots__/ResumeButton.test.jsx.snap b/src/containers/CourseCard/components/CourseCardActions/__snapshots__/ResumeButton.test.jsx.snap index e0c348400..c9c7e5e60 100644 --- a/src/containers/CourseCard/components/CourseCardActions/__snapshots__/ResumeButton.test.jsx.snap +++ b/src/containers/CourseCard/components/CourseCardActions/__snapshots__/ResumeButton.test.jsx.snap @@ -10,7 +10,7 @@ exports[`ResumeButton snapshot disabled snapshot 1`] = ` "trackCourseEvent": { "cardId": "cardId", "eventName": [MockFunction segment.enterCourseClicked], - "upgradeUrl": "resume-urlexec-ed-tracking-path=cardId", + "url": "resume-urlexec-ed-tracking-path=cardId", }, } } @@ -29,7 +29,7 @@ exports[`ResumeButton snapshot enabled snapshot 1`] = ` "trackCourseEvent": { "cardId": "cardId", "eventName": [MockFunction segment.enterCourseClicked], - "upgradeUrl": "resume-urlexec-ed-tracking-path=cardId", + "url": "resume-urlexec-ed-tracking-path=cardId", }, } } diff --git a/src/containers/CourseCard/components/CourseCardActions/__snapshots__/UpgradeButton.test.jsx.snap b/src/containers/CourseCard/components/CourseCardActions/__snapshots__/UpgradeButton.test.jsx.snap deleted file mode 100644 index d6718302a..000000000 --- a/src/containers/CourseCard/components/CourseCardActions/__snapshots__/UpgradeButton.test.jsx.snap +++ /dev/null @@ -1,32 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`UpgradeButton snapshot can upgrade 1`] = ` - - Upgrade - -`; - -exports[`UpgradeButton snapshot cannot upgrade 1`] = ` - - Upgrade - -`; diff --git a/src/containers/CourseCard/components/CourseCardActions/__snapshots__/ViewCourseButton.test.jsx.snap b/src/containers/CourseCard/components/CourseCardActions/__snapshots__/ViewCourseButton.test.jsx.snap index d777595e4..3274270fc 100644 --- a/src/containers/CourseCard/components/CourseCardActions/__snapshots__/ViewCourseButton.test.jsx.snap +++ b/src/containers/CourseCard/components/CourseCardActions/__snapshots__/ViewCourseButton.test.jsx.snap @@ -10,7 +10,7 @@ exports[`ViewCourseButton learner can view course 1`] = ` "trackCourseEvent": { "cardId": "cardId", "eventName": [MockFunction segment.enterCourseClicked], - "upgradeUrl": "homeUrl", + "url": "homeUrl", }, } } @@ -29,7 +29,7 @@ exports[`ViewCourseButton learner cannot view course 1`] = ` "trackCourseEvent": { "cardId": "cardId", "eventName": [MockFunction segment.enterCourseClicked], - "upgradeUrl": "homeUrl", + "url": "homeUrl", }, } } diff --git a/src/containers/CourseCard/components/CourseCardActions/messages.js b/src/containers/CourseCard/components/CourseCardActions/messages.js index 6c14f9b0c..309842977 100644 --- a/src/containers/CourseCard/components/CourseCardActions/messages.js +++ b/src/containers/CourseCard/components/CourseCardActions/messages.js @@ -1,11 +1,6 @@ import { defineMessages } from '@edx/frontend-platform/i18n'; const messages = defineMessages({ - upgrade: { - id: 'learner-dash.courseCard.actions.upgrade', - description: 'Course card upgrade button text', - defaultMessage: 'Upgrade', - }, beginCourse: { id: 'learner-dash.courseCard.actions.beginCourse', description: 'Course card begin-course button text', diff --git a/src/containers/CourseCard/components/CourseCardImage.test.jsx b/src/containers/CourseCard/components/CourseCardImage.test.jsx index 278b20d08..05d0636e2 100644 --- a/src/containers/CourseCard/components/CourseCardImage.test.jsx +++ b/src/containers/CourseCard/components/CourseCardImage.test.jsx @@ -18,8 +18,8 @@ jest.mock('hooks', () => ({ useCardCourseData: jest.fn(() => ({ bannerImgSrc: 'banner-img-src' })), useCardCourseRunData: jest.fn(() => ({ homeUrl })), useCardEnrollmentData: jest.fn(() => ({ isVerified: true })), - useTrackCourseEvent: jest.fn((eventName, cardId, upgradeUrl) => ({ - trackCourseEvent: { eventName, cardId, upgradeUrl }, + useTrackCourseEvent: jest.fn((eventName, cardId, url) => ({ + trackCourseEvent: { eventName, cardId, url }, })), }, })); diff --git a/src/containers/CourseCard/components/CourseCardTitle.test.jsx b/src/containers/CourseCard/components/CourseCardTitle.test.jsx index a71dd7e74..aa3dcdd30 100644 --- a/src/containers/CourseCard/components/CourseCardTitle.test.jsx +++ b/src/containers/CourseCard/components/CourseCardTitle.test.jsx @@ -17,8 +17,8 @@ jest.mock('hooks', () => ({ reduxHooks: { useCardCourseData: jest.fn(() => ({ courseName: 'course-name' })), useCardCourseRunData: jest.fn(() => ({ homeUrl })), - useTrackCourseEvent: jest.fn((eventName, cardId, upgradeUrl) => ({ - trackCourseEvent: { eventName, cardId, upgradeUrl }, + useTrackCourseEvent: jest.fn((eventName, cardId, url) => ({ + trackCourseEvent: { eventName, cardId, url }, })), }, })); diff --git a/src/containers/CourseCard/components/__snapshots__/CourseCardImage.test.jsx.snap b/src/containers/CourseCard/components/__snapshots__/CourseCardImage.test.jsx.snap index 2a0bc9258..a0d357c7c 100644 --- a/src/containers/CourseCard/components/__snapshots__/CourseCardImage.test.jsx.snap +++ b/src/containers/CourseCard/components/__snapshots__/CourseCardImage.test.jsx.snap @@ -9,7 +9,7 @@ exports[`CourseCardImage snapshot renders clickable link course Image 1`] = ` "trackCourseEvent": { "cardId": "cardId", "eventName": [MockFunction segment.courseImageClicked], - "upgradeUrl": "home-url", + "url": "home-url", }, } } diff --git a/src/containers/CourseCard/components/__snapshots__/CourseCardTitle.test.jsx.snap b/src/containers/CourseCard/components/__snapshots__/CourseCardTitle.test.jsx.snap index c35f852c1..34446ade0 100644 --- a/src/containers/CourseCard/components/__snapshots__/CourseCardTitle.test.jsx.snap +++ b/src/containers/CourseCard/components/__snapshots__/CourseCardTitle.test.jsx.snap @@ -11,7 +11,7 @@ exports[`CourseCardTitle snapshot renders clickable link course title 1`] = ` "trackCourseEvent": { "cardId": "cardId", "eventName": [MockFunction segment.courseTitleClicked], - "upgradeUrl": "home-url", + "url": "home-url", }, } } diff --git a/src/containers/CourseCard/components/hooks.js b/src/containers/CourseCard/components/hooks.js index 2a3020142..9d80c0ae9 100644 --- a/src/containers/CourseCard/components/hooks.js +++ b/src/containers/CourseCard/components/hooks.js @@ -3,19 +3,18 @@ import { reduxHooks } from 'hooks'; export const useActionDisabledState = (cardId) => { const { isMasquerading } = reduxHooks.useMasqueradeData(); const { - canUpgrade, hasAccess, isAudit, isAuditAccessExpired, + hasAccess, isAudit, isAuditAccessExpired, } = reduxHooks.useCardEnrollmentData(cardId); const { isEntitlement, isFulfilled, canChange, hasSessions, } = reduxHooks.useCardEntitlementData(cardId); - const { resumeUrl, homeUrl, upgradeUrl } = reduxHooks.useCardCourseRunData(cardId); + const { resumeUrl, homeUrl } = reduxHooks.useCardCourseRunData(cardId); const disableBeginCourse = !homeUrl || (isMasquerading || !hasAccess || (isAudit && isAuditAccessExpired)); const disableResumeCourse = !resumeUrl || (isMasquerading || !hasAccess || (isAudit && isAuditAccessExpired)); const disableViewCourse = !hasAccess || (isAudit && isAuditAccessExpired); const disableSelectSession = !isEntitlement || isMasquerading || !hasAccess || (!canChange || !hasSessions); - const disableUpgradeCourse = !upgradeUrl || (isMasquerading && !canUpgrade); const disableCourseTitle = (isEntitlement && !isFulfilled) || disableViewCourse; @@ -23,7 +22,6 @@ export const useActionDisabledState = (cardId) => { disableBeginCourse, disableResumeCourse, disableViewCourse, - disableUpgradeCourse, disableSelectSession, disableCourseTitle, }; diff --git a/src/containers/CourseCard/components/hooks.test.js b/src/containers/CourseCard/components/hooks.test.js index f389ef40e..50d2ccc25 100644 --- a/src/containers/CourseCard/components/hooks.test.js +++ b/src/containers/CourseCard/components/hooks.test.js @@ -16,7 +16,6 @@ const cardId = 'my-test-course-number'; describe('useActionDisabledState', () => { const defaultData = { isMasquerading: false, - canUpgrade: false, isEntitlement: false, isFulfilled: false, canChange: false, @@ -26,12 +25,10 @@ describe('useActionDisabledState', () => { isAuditAccessExpired: false, resumeUrl: 'resume.url', homeUrl: 'home.url', - upgradeUrl: 'upgrade.url', }; const mockHooksData = (args) => { const { isMasquerading, - canUpgrade, isEntitlement, isFulfilled, canChange, @@ -41,11 +38,9 @@ describe('useActionDisabledState', () => { isAuditAccessExpired, resumeUrl, homeUrl, - upgradeUrl, } = { ...defaultData, ...args }; reduxHooks.useMasqueradeData.mockReturnValueOnce({ isMasquerading }); reduxHooks.useCardEnrollmentData.mockReturnValueOnce({ - canUpgrade, hasAccess, isAudit, isAuditAccessExpired, @@ -59,7 +54,6 @@ describe('useActionDisabledState', () => { reduxHooks.useCardCourseRunData.mockReturnValueOnce({ resumeUrl, homeUrl, - upgradeUrl, }); }; @@ -121,21 +115,6 @@ describe('useActionDisabledState', () => { testDisabled({ hasAccess: true }, false); }); }); - describe('disableUpgradeCourse', () => { - const testDisabled = (data, expected) => { - mockHooksData(data); - expect(runHook().disableUpgradeCourse).toBe(expected); - }; - it('disable when upgradeUrl is invalid', () => { - testDisabled({ upgradeUrl: null }, true); - }); - it('disable when isMasquerading is true and canUpgrade is false', () => { - testDisabled({ isMasquerading: true, canUpgrade: false }, true); - }); - it('enable when all conditions are met', () => { - testDisabled({ canUpgrade: true }, false); - }); - }); describe('disableSelectSession', () => { const testDisabled = (data, expected) => { mockHooksData(data); diff --git a/src/data/redux/app/selectors/courseCard.js b/src/data/redux/app/selectors/courseCard.js index 742c5f000..080ad37ef 100644 --- a/src/data/redux/app/selectors/courseCard.js +++ b/src/data/redux/app/selectors/courseCard.js @@ -52,7 +52,6 @@ export const courseCard = StrictDict({ homeUrl: courseRun.homeUrl, marketingUrl: courseRun.marketingUrl, - upgradeUrl: courseRun.upgradeUrl, progressUrl: baseAppUrl(courseRun.progressUrl), resumeUrl: baseAppUrl(courseRun.resumeUrl), // resume will route this to learning mfe. diff --git a/src/data/redux/app/selectors/courseCard.test.js b/src/data/redux/app/selectors/courseCard.test.js index 5f042c53c..84c6da654 100644 --- a/src/data/redux/app/selectors/courseCard.test.js +++ b/src/data/redux/app/selectors/courseCard.test.js @@ -156,7 +156,6 @@ describe('courseCard selectors module', () => { homeUrl: 'test-home-url', marketingUrl: 'test-marketing-url', - upgradeUrl: 'test-upgrade-url', progressUrl: 'test-progress-url', resumeUrl: 'test-resume-url', @@ -181,10 +180,9 @@ describe('courseCard selectors module', () => { it('passes minPassingGrade floored from float to a percentage value', () => { expect(selected.minPassingGrade).toEqual(93); }); - it('passes [homeUrl, marketingUrl, upgradeUrl]', () => { + it('passes [homeUrl, marketingUrl]', () => { expect(selected.homeUrl).toEqual(testData.homeUrl); expect(selected.marketingUrl).toEqual(testData.marketingUrl); - expect(selected.upgradeUrl).toEqual(testData.upgradeUrl); }); it('passes [progressUrl, unenrollUrl, resumeUrl], converted to baseAppUrl', () => { expect(selected.progressUrl).toEqual(baseAppUrl(testData.progressUrl)); diff --git a/src/data/services/lms/api.js b/src/data/services/lms/api.js index 6f9acd560..e2d477181 100644 --- a/src/data/services/lms/api.js +++ b/src/data/services/lms/api.js @@ -50,12 +50,6 @@ export const logEvent = ({ eventName, data, courseId }) => post(urls.event(), { event: JSON.stringify(data), }); -export const logUpgrade = ({ courseId }) => module.logEvent({ - eventName: eventNames.upgradeButtonClickedEnrollment, - courseId, - data: { location: 'learner-dashboard' }, -}); - export const logShare = ({ courseId, site }) => module.logEvent({ eventName: eventNames.shareClicked, courseId, @@ -78,7 +72,6 @@ export default { updateEntitlementEnrollment, deleteEntitlementEnrollment, logEvent, - logUpgrade, logShare, createCreditRequest, }; diff --git a/src/data/services/lms/api.test.js b/src/data/services/lms/api.test.js index 8f83a3791..af24aad9f 100644 --- a/src/data/services/lms/api.test.js +++ b/src/data/services/lms/api.test.js @@ -130,13 +130,6 @@ describe('lms api methods', () => { beforeEach(() => { jest.spyOn(api, moduleKeys.logEvent).mockImplementation(logEvent); }); - test('logUpgrade sends enrollment upgrade click event with learner dashboard location', () => { - expect(api.logUpgrade({ courseId })).toEqual(logEvent({ - eventName: eventNames.upgradeButtonClickedEnrollment, - courseId, - data: { location: 'learner-dashboard' }, - })); - }); test('logShare sends share clicke vent with course id, side and location', () => { const site = 'test-site'; expect(api.logShare({ courseId, site })).toEqual(logEvent({ diff --git a/src/data/services/lms/fakeData/courses.js b/src/data/services/lms/fakeData/courses.js index 0fec065b2..31911a969 100644 --- a/src/data/services/lms/fakeData/courses.js +++ b/src/data/services/lms/fakeData/courses.js @@ -779,9 +779,6 @@ export const compileCourseRunData = ({ courseName, ...data }, index) => { courseProvider: getOption(providerOptions, index), programs: getOption(programsOptions, index), }; - if (out.enrollment.canUpgrade) { - out.courseRun.upgradeUrl = 'test-upgrade-url'; - } return out; }; diff --git a/src/plugin-slots/CourseCardActionSlot/index.jsx b/src/plugin-slots/CourseCardActionSlot/index.jsx index 6747ee185..7a95b675b 100644 --- a/src/plugin-slots/CourseCardActionSlot/index.jsx +++ b/src/plugin-slots/CourseCardActionSlot/index.jsx @@ -2,27 +2,14 @@ import React from 'react'; import PropTypes from 'prop-types'; import { PluginSlot } from '@openedx/frontend-plugin-framework'; -import { reduxHooks } from 'hooks'; -import UpgradeButton from 'containers/CourseCard/components/CourseCardActions/UpgradeButton'; - -const CourseCardActionSlot = ({ cardId }) => { - const { isEntitlement } = reduxHooks.useCardEntitlementData(cardId); - const { - isVerified, - isExecEd2UCourse, - } = reduxHooks.useCardEnrollmentData(cardId); - - return ( - - {!(isEntitlement || isVerified || isExecEd2UCourse) && } - - ); -}; +const CourseCardActionSlot = ({ cardId }) => ( + +); CourseCardActionSlot.propTypes = { cardId: PropTypes.string.isRequired, diff --git a/src/tracking/constants.js b/src/tracking/constants.js index 8c439a9bb..4683019cc 100644 --- a/src/tracking/constants.js +++ b/src/tracking/constants.js @@ -2,7 +2,6 @@ import { StrictDict } from 'utils'; export const categories = StrictDict({ dashboard: 'dashboard', - upgrade: 'upgrade', userEngagement: 'user-engagement', searchButton: 'search_button', credit: 'credit', @@ -14,9 +13,6 @@ export const events = StrictDict({ courseImageClicked: 'courseImageClicked', courseTitleClicked: 'courseTitleClicked', courseOptionsDropdownClicked: 'courseOptionsDropdownClicked', - upgradeButtonClicked: 'upgradeButtonClicked', - upgradeButtonClickedEnrollment: 'upgradeButtonClickedEnrollment', - upgradeButtonClickedUpsell: 'upgradeButtonClickedUpsell', shareClicked: 'shareClicked', userSettingsChanged: 'userSettingsChanged', newSession: 'newSession', @@ -36,9 +32,6 @@ export const eventNames = StrictDict({ courseImageClicked: 'edx.bi.dashboard.course_image.clicked', courseTitleClicked: 'edx.bi.dashboard.course_title.clicked', courseOptionsDropdownClicked: 'edx.bi.dashboard.course_options_dropdown.clicked', - upgradeButtonClicked: 'edx.bi.dashboard.upgrade_button.clicked', - upgradeButtonClickedEnrollment: 'edx.course.enrollment.upgrade.clicked', - upgradeButtonClickedUpsell: 'edx.bi.ecommerce.upsell_links_clicked', shareClicked: 'edx.course.share_clicked', userSettingsChanged: 'edx.user.settings.changed', newSession: 'course-dashboard.new-session', diff --git a/src/tracking/trackers/course.js b/src/tracking/trackers/course.js index aa5262c54..1edba2678 100644 --- a/src/tracking/trackers/course.js +++ b/src/tracking/trackers/course.js @@ -1,4 +1,3 @@ -import api from 'data/services/lms/api'; import { createEventTracker, createLinkTracker } from 'data/services/segment/utils'; import { categories, eventNames } from '../constants'; import * as module from './course'; @@ -31,20 +30,6 @@ export const courseLinkTracker = (eventName) => (courseId, href) => ( createLinkTracker(module.courseEventTracker(eventName, courseId), href) ); -// Upgrade Events -/** - * There are currently multiple tracked api events for the upgrade event, with different targets. - * Goal here is to split out the tracked events for easier testing. - */ -export const upgradeButtonClicked = (courseId) => createEventTracker( - eventNames.upgradeButtonClicked, - { category: categories.upgrade, label: courseId }, -); -export const upgradeButtonClickedUpsell = (courseId) => createEventTracker( - eventNames.upgradeButtonClickedUpsell, - { ...upsellOptions, courseId }, -); - // Non-Link events export const courseOptionsDropdownClicked = (courseId) => ( module.courseEventTracker(eventNames.courseOptionsDropdownClicked, courseId) @@ -57,19 +42,10 @@ export const courseTitleClicked = (...args) => ( module.courseLinkTracker(eventNames.courseTitleClicked)(...args)); export const enterCourseClicked = (...args) => ( module.courseLinkTracker(eventNames.enterCourseClicked)(...args)); -export const upgradeClicked = (courseId, href) => createLinkTracker( - () => { - module.upgradeButtonClicked(courseId)(); - module.upgradeButtonClickedUpsell(courseId)(); - api.logUpgrade({ courseId }); - }, - href, -); export default { courseImageClicked, courseOptionsDropdownClicked, courseTitleClicked, enterCourseClicked, - upgradeClicked, }; diff --git a/src/tracking/trackers/course.test.js b/src/tracking/trackers/course.test.js index a8c8c391b..7715b1133 100644 --- a/src/tracking/trackers/course.test.js +++ b/src/tracking/trackers/course.test.js @@ -1,13 +1,8 @@ import { keyStore } from 'utils'; -import api from 'data/services/lms/api'; import { createEventTracker, createLinkTracker } from 'data/services/segment/utils'; import { categories, eventNames } from '../constants'; import * as trackers from './course'; -jest.mock('data/services/lms/api', () => ({ - logUpgrade: jest.fn(), -})); - jest.mock('data/services/segment/utils', () => ({ createEventTracker: jest.fn(args => ({ createEventTracker: args })), createLinkTracker: jest.fn((cb, href) => ({ createLinkTracker: { cb, href } })), @@ -44,26 +39,6 @@ describe('course trackers', () => { }); }); }); - describe('Upgrade Events', () => { - describe('upgradeButtonClicked', () => { - it('creates an event tracker for upgradeButtonClicked event with category and label', () => { - expect(trackers.upgradeButtonClicked(courseId)).toEqual(createEventTracker( - eventNames.upgradeButtonClicked, - { category: categories.upgrade, label: courseId }, - )); - }); - }); - describe('upgradeButtonClickedUpsell', () => { - it('creates an event tracker for upgradeButtonClickedUpsell eventwith upsellOptions', () => { - expect(trackers.upgradeButtonClickedUpsell(courseId)).toEqual( - createEventTracker( - eventNames.upgradeButtonClickedUpsell, - { ...trackers.upsellOptions, courseId }, - ), - ); - }); - }); - }); describe('Non-link events', () => { describe('courseOptionsDropdownClicked', () => { it('creates course event tracker for courseOptionsDropdownClicked event', () => { @@ -101,25 +76,5 @@ describe('course trackers', () => { ); }); }); - describe('upgradeClicked', () => { - it('triggers upgrade actions and api.logUpgrade with courseId', () => { - const upgradeButtonClicked = jest.fn(); - const upgradeButtonClickedUpsell = jest.fn(); - const trackUpgradeButtonClicked = jest.fn(() => upgradeButtonClicked); - const trackUpgradeButtonClickedUpsell = jest.fn(() => upgradeButtonClickedUpsell); - jest.spyOn(trackers, moduleKeys.upgradeButtonClicked) - .mockImplementationOnce(trackUpgradeButtonClicked); - jest.spyOn(trackers, moduleKeys.upgradeButtonClickedUpsell) - .mockImplementationOnce(trackUpgradeButtonClickedUpsell); - const out = trackers.upgradeClicked(courseId, href).createLinkTracker; - expect(out.href).toEqual(href); - out.cb(); - expect(trackUpgradeButtonClicked).toHaveBeenCalledWith(courseId); - expect(trackUpgradeButtonClickedUpsell).toHaveBeenCalledWith(courseId); - expect(upgradeButtonClicked).toHaveBeenCalledWith(); - expect(upgradeButtonClickedUpsell).toHaveBeenCalledWith(); - expect(api.logUpgrade).toHaveBeenCalledWith({ courseId }); - }); - }); }); }); From abae82b507c5204915f72ec5d62f2f4a7de8545a Mon Sep 17 00:00:00 2001 From: Maxwell Frank <92897870+MaxFrank13@users.noreply.github.com> Date: Tue, 14 Jan 2025 14:36:38 -0500 Subject: [PATCH 2/4] fix: remove remaining UpgradeButton definition and tests (#548) --- .../CourseCardActions/UpgradeButton.jsx | 45 ------------------- .../CourseCardActions/index.test.jsx | 27 ++--------- src/tracking/trackers/course.js | 7 --- 3 files changed, 3 insertions(+), 76 deletions(-) delete mode 100644 src/containers/CourseCard/components/CourseCardActions/UpgradeButton.jsx diff --git a/src/containers/CourseCard/components/CourseCardActions/UpgradeButton.jsx b/src/containers/CourseCard/components/CourseCardActions/UpgradeButton.jsx deleted file mode 100644 index ca55ec9a4..000000000 --- a/src/containers/CourseCard/components/CourseCardActions/UpgradeButton.jsx +++ /dev/null @@ -1,45 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -import { Locked } from '@openedx/paragon/icons'; -import { useIntl } from '@edx/frontend-platform/i18n'; - -import track from 'tracking'; -import { reduxHooks } from 'hooks'; -import useActionDisabledState from '../hooks'; - -import ActionButton from './ActionButton'; -import messages from './messages'; - -export const UpgradeButton = ({ cardId }) => { - const { formatMessage } = useIntl(); - - const { upgradeUrl } = reduxHooks.useCardCourseRunData(cardId); - const { disableUpgradeCourse } = useActionDisabledState(cardId); - - const trackUpgradeClick = reduxHooks.useTrackCourseEvent( - track.course.upgradeClicked, - cardId, - upgradeUrl, - ); - - const enabledProps = { - as: 'a', - href: upgradeUrl, - onClick: trackUpgradeClick, - }; - return ( - - {formatMessage(messages.upgrade)} - - ); -}; -UpgradeButton.propTypes = { - cardId: PropTypes.string.isRequired, -}; -export default UpgradeButton; diff --git a/src/containers/CourseCard/components/CourseCardActions/index.test.jsx b/src/containers/CourseCard/components/CourseCardActions/index.test.jsx index 5819a9b6e..329467238 100644 --- a/src/containers/CourseCard/components/CourseCardActions/index.test.jsx +++ b/src/containers/CourseCard/components/CourseCardActions/index.test.jsx @@ -3,7 +3,6 @@ import { shallow } from '@edx/react-unit-test-utils'; import { reduxHooks } from 'hooks'; import CourseCardActionSlot from 'plugin-slots/CourseCardActionSlot'; -import UpgradeButton from './UpgradeButton'; import SelectSessionButton from './SelectSessionButton'; import BeginCourseButton from './BeginCourseButton'; import ResumeButton from './ResumeButton'; @@ -21,7 +20,6 @@ jest.mock('hooks', () => ({ })); jest.mock('plugin-slots/CourseCardActionSlot', () => 'CustomActionButton'); -jest.mock('./UpgradeButton', () => 'UpgradeButton'); jest.mock('./SelectSessionButton', () => 'SelectSessionButton'); jest.mock('./ViewCourseButton', () => 'ViewCourseButton'); jest.mock('./BeginCourseButton', () => 'BeginCourseButton'); @@ -59,19 +57,7 @@ describe('CourseCardActions', () => { }); }); describe('output', () => { - describe('Exec Ed course', () => { - it('does not render upgrade button', () => { - mockHooks({ isExecEd2UCourse: true }); - render(); - expect(el.instance.findByType(UpgradeButton).length).toEqual(0); - }); - }); describe('entitlement course', () => { - it('does not render upgrade button', () => { - mockHooks({ isEntitlement: true }); - render(); - expect(el.instance.findByType(UpgradeButton).length).toEqual(0); - }); it('renders ViewCourseButton if fulfilled', () => { mockHooks({ isEntitlement: true, isFulfilled: true }); render(); @@ -83,22 +69,15 @@ describe('CourseCardActions', () => { expect(el.instance.findByType(SelectSessionButton)[0].props.cardId).toEqual(cardId); }); }); - describe('verified course', () => { - it('does not render upgrade button', () => { - mockHooks({ isVerified: true }); - render(); - expect(el.instance.findByType(UpgradeButton).length).toEqual(0); - }); - }); describe('not entitlement, verified, or exec ed', () => { - it('renders UpgradeButton and ViewCourseButton for archived courses', () => { + it('renders CourseCardActionSlot and ViewCourseButton for archived courses', () => { mockHooks({ isArchived: true }); render(); expect(el.instance.findByType(CourseCardActionSlot)[0].props.cardId).toEqual(cardId); expect(el.instance.findByType(ViewCourseButton)[0].props.cardId).toEqual(cardId); }); describe('unstarted courses', () => { - it('renders UpgradeButton and BeginCourseButton', () => { + it('renders CourseCardActionSlot and BeginCourseButton', () => { mockHooks(); render(); expect(el.instance.findByType(CourseCardActionSlot)[0].props.cardId).toEqual(cardId); @@ -106,7 +85,7 @@ describe('CourseCardActions', () => { }); }); describe('active courses (started, and not archived)', () => { - it('renders UpgradeButton and ResumeButton', () => { + it('renders CourseCardActionSlot and ResumeButton', () => { mockHooks({ hasStarted: true }); render(); expect(el.instance.findByType(CourseCardActionSlot)[0].props.cardId).toEqual(cardId); diff --git a/src/tracking/trackers/course.js b/src/tracking/trackers/course.js index 1edba2678..8513692ae 100644 --- a/src/tracking/trackers/course.js +++ b/src/tracking/trackers/course.js @@ -2,13 +2,6 @@ import { createEventTracker, createLinkTracker } from 'data/services/segment/uti import { categories, eventNames } from '../constants'; import * as module from './course'; -export const upsellOptions = { - linkName: 'course_dashboard_green', - linkType: 'button', - pageName: 'course_dashboard', - linkCategory: 'green_update', -}; - // Utils/Helpers /** * Generate a segement event tracker for a given course event. From 8b67abd304e49faf4cc69e5916bb52fcb485a9dc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 05:03:34 +0000 Subject: [PATCH 3/4] fix(deps): update dependency react-router-dom to v6.28.2 (#551) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 26 +++++++++++++------------- package.json | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7ce1ea1a9..61a118d02 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,7 +38,7 @@ "react-helmet": "^6.1.0", "react-intl": "6.8.9", "react-redux": "^7.2.4", - "react-router-dom": "6.28.1", + "react-router-dom": "6.28.2", "react-share": "^4.4.0", "redux": "4.2.1", "redux-logger": "3.0.6", @@ -3982,9 +3982,9 @@ "license": "MIT" }, "node_modules/@remix-run/router": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.21.0.tgz", - "integrity": "sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==", + "version": "1.21.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.21.1.tgz", + "integrity": "sha512-KeBYSwohb8g4/wCcnksvKTYlg69O62sQeLynn2YE+5z7JWEj95if27kclW9QqbrlsQ2DINI8fjbV3zyuKfwjKg==", "license": "MIT", "engines": { "node": ">=14.0.0" @@ -15106,12 +15106,12 @@ } }, "node_modules/react-router": { - "version": "6.28.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.28.1.tgz", - "integrity": "sha512-2omQTA3rkMljmrvvo6WtewGdVh45SpL9hGiCI9uUrwGGfNFDIvGK4gYJsKlJoNVi6AQZcopSCballL+QGOm7fA==", + "version": "6.28.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.28.2.tgz", + "integrity": "sha512-BgFY7+wEGVjHCiqaj2XiUBQ1kkzfg6UoKYwEe0wv+FF+HNPCxtS/MVPvLAPH++EsuCMReZl9RYVGqcHLk5ms3A==", "license": "MIT", "dependencies": { - "@remix-run/router": "1.21.0" + "@remix-run/router": "1.21.1" }, "engines": { "node": ">=14.0.0" @@ -15121,13 +15121,13 @@ } }, "node_modules/react-router-dom": { - "version": "6.28.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.28.1.tgz", - "integrity": "sha512-YraE27C/RdjcZwl5UCqF/ffXnZDxpJdk9Q6jw38SZHjXs7NNdpViq2l2c7fO7+4uWaEfcwfGCv3RSg4e1By/fQ==", + "version": "6.28.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.28.2.tgz", + "integrity": "sha512-O81EWqNJWqvlN/a7eTudAdQm0TbI7hw+WIi7OwwMcTn5JMyZ0ibTFNGz+t+Lju0df4LcqowCegcrK22lB1q9Kw==", "license": "MIT", "dependencies": { - "@remix-run/router": "1.21.0", - "react-router": "6.28.1" + "@remix-run/router": "1.21.1", + "react-router": "6.28.2" }, "engines": { "node": ">=14.0.0" diff --git a/package.json b/package.json index b95180369..b608fa9e4 100755 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "react-helmet": "^6.1.0", "react-intl": "6.8.9", "react-redux": "^7.2.4", - "react-router-dom": "6.28.1", + "react-router-dom": "6.28.2", "react-share": "^4.4.0", "redux": "4.2.1", "redux-logger": "3.0.6", From 2b287c63327546e9867c4173853ed02ce73e7a62 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 09:40:34 +0000 Subject: [PATCH 4/4] chore(deps): update dependency @edx/browserslist-config to v1.5.0 (#552) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 61a118d02..d2ce3cd7f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2039,9 +2039,9 @@ "integrity": "sha512-Dn9CtpC8fovh++Xi4NF5NJoeR9yU2yXZnV9IujxIyGd/dn0Phq5t6dzJVfupwq09mpDnzJv7egA8Znz/3ljO+w==" }, "node_modules/@edx/browserslist-config": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@edx/browserslist-config/-/browserslist-config-1.4.0.tgz", - "integrity": "sha512-/nUVlFuri0N6R9jaU6ah39FGosUcGhJyH+7a6Sg9fkjzqDHIRpS6PB7OFM91i8UvHJQs4iQ3qZ8yHw7ianzPCw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@edx/browserslist-config/-/browserslist-config-1.5.0.tgz", + "integrity": "sha512-d2ggwi5j4DOBJOwhWZxBWQSDR0DhT4ke/1PbzRauICdFkuOyax+PsFjK8GUh443K2OaQpy9PGfiCzZ1Yg37AUA==", "license": "AGPL-3.0" }, "node_modules/@edx/eslint-config": {