From 6aaebbbabd5bc8ee7745dbd8669d781143a96fb8 Mon Sep 17 00:00:00 2001 From: Maham Akif <113524403+mahamakifdar19@users.noreply.github.com> Date: Mon, 21 Oct 2024 12:52:34 +0500 Subject: [PATCH] feat: show expiration modal on dashboard and search page (#1206) Co-authored-by: Maham Akif --- src/components/course/routes/CourseAbout.jsx | 2 +- src/components/dashboard/DashboardPage.jsx | 8 +++ .../index.jsx} | 0 .../tests/ExpiredSubscriptionModal.test.jsx | 71 +++++++++++++++++++ src/components/search/Search.jsx | 2 + 5 files changed, 82 insertions(+), 1 deletion(-) rename src/components/{course/ExpiredSubscriptionModal.jsx => expired-subscription-modal/index.jsx} (100%) create mode 100644 src/components/expired-subscription-modal/tests/ExpiredSubscriptionModal.test.jsx diff --git a/src/components/course/routes/CourseAbout.jsx b/src/components/course/routes/CourseAbout.jsx index a32320135b..1f796cf436 100644 --- a/src/components/course/routes/CourseAbout.jsx +++ b/src/components/course/routes/CourseAbout.jsx @@ -13,7 +13,7 @@ import { useIsAssignmentsOnlyLearner, usePassLearnerCsodParams, } from '../../app/data'; -import ExpiredSubscriptionModal from '../ExpiredSubscriptionModal'; +import ExpiredSubscriptionModal from '../../expired-subscription-modal'; const CourseAbout = () => { const { data: canOnlyViewHighlightSets } = useCanOnlyViewHighlights(); diff --git a/src/components/dashboard/DashboardPage.jsx b/src/components/dashboard/DashboardPage.jsx index 94ddb4e4e3..35174dd85a 100644 --- a/src/components/dashboard/DashboardPage.jsx +++ b/src/components/dashboard/DashboardPage.jsx @@ -16,6 +16,7 @@ import { useSubscriptions, } from '../app/data'; import BudgetExpiryNotification from '../budget-expiry-notification'; +import ExpiredSubscriptionModal from '../expired-subscription-modal'; const DashboardPage = () => { const intl = useIntl(); @@ -95,6 +96,13 @@ const DashboardPage = () => { {tabs.map((tab) => React.cloneElement(tab, { key: tab.props.eventKey }))} + {/* ExpiredSubscriptionModal is specifically tailored for learners with an expired license and is + triggered when the learner has hasCustomLicenseExpirationMessaging enabled. + Ideally, the existing SubscriptionExpirationModal should be extended or repurposed to incorporate + this logic and support the custom messaging. + This is noted as a TO-DO, and a ticket will be created to address this enhancement. + Ticket: https://2u-internal.atlassian.net/browse/ENT-9512 */} + {subscriptions.subscriptionPlan && subscriptions.showExpirationNotifications && } ); diff --git a/src/components/course/ExpiredSubscriptionModal.jsx b/src/components/expired-subscription-modal/index.jsx similarity index 100% rename from src/components/course/ExpiredSubscriptionModal.jsx rename to src/components/expired-subscription-modal/index.jsx diff --git a/src/components/expired-subscription-modal/tests/ExpiredSubscriptionModal.test.jsx b/src/components/expired-subscription-modal/tests/ExpiredSubscriptionModal.test.jsx new file mode 100644 index 0000000000..af6ab748af --- /dev/null +++ b/src/components/expired-subscription-modal/tests/ExpiredSubscriptionModal.test.jsx @@ -0,0 +1,71 @@ +import { screen } from '@testing-library/react'; +import '@testing-library/jest-dom/extend-expect'; +import ExpiredSubscriptionModal from '../index'; +import { useSubscriptions } from '../../app/data'; +import { renderWithRouter } from '../../../utils/tests'; + +jest.mock('../../app/data', () => ({ + ...jest.requireActual('../../app/data'), + useSubscriptions: jest.fn(), +})); + +describe('', () => { + beforeEach(() => { + useSubscriptions.mockReturnValue({ + data: { + customerAgreement: { + hasCustomLicenseExpirationMessaging: false, + expiredSubscriptionModalMessaging: null, + urlForExpiredModal: null, + hyperLinkTextForExpiredModal: null, + }, + }, + }); + }); + + test('does not renderwithrouter if `hasCustomLicenseExpirationMessaging` is false', () => { + const { container } = renderWithRouter(); + expect(container).toBeEmptyDOMElement(); + }); + + test('renderwithrouters modal with messaging when `hasCustomLicenseExpirationMessaging` is true', () => { + useSubscriptions.mockReturnValue({ + data: { + customerAgreement: { + hasCustomLicenseExpirationMessaging: true, + expiredSubscriptionModalMessaging: 'Your subscription has expired.', + urlForExpiredModal: '/renew', + hyperLinkTextForExpiredModal: 'Click here to renew', + }, + }, + }); + + renderWithRouter(); + + expect(screen.getByText('Your subscription has expired.')).toBeInTheDocument(); + expect(screen.getByText('Click here to renew')).toBeInTheDocument(); + expect(screen.getByRole('link', { name: 'Click here to renew' })).toHaveAttribute('href', '/renew'); + }); + + test('does not renderwithrouter modal if no customer agreement data is present', () => { + useSubscriptions.mockReturnValue({ data: { customerAgreement: null } }); + const { container } = renderWithRouter(); + expect(container).toBeEmptyDOMElement(); + }); + + test('renderwithrouters close button in modal', () => { + useSubscriptions.mockReturnValue({ + data: { + customerAgreement: { + hasCustomLicenseExpirationMessaging: true, + expiredSubscriptionModalMessaging: 'Subscription expired', + urlForExpiredModal: '/renew', + hyperLinkTextForExpiredModal: 'Renew', + }, + }, + }); + + renderWithRouter(); + expect(screen.getByRole('button', { name: /close/i })).toBeInTheDocument(); + }); +}); diff --git a/src/components/search/Search.jsx b/src/components/search/Search.jsx index c5885c3ed6..cb2fd426df 100644 --- a/src/components/search/Search.jsx +++ b/src/components/search/Search.jsx @@ -32,6 +32,7 @@ import ContentTypeSearchResultsContainer from './ContentTypeSearchResultsContain import SearchVideo from './SearchVideo'; import { hasActivatedAndCurrentSubscription } from './utils'; import VideoBanner from '../microlearning/VideoBanner'; +import ExpiredSubscriptionModal from '../expired-subscription-modal'; function useSearchPathwayModal() { const [isLearnerPathwayModalOpen, openLearnerPathwayModal, close] = useToggle(false); @@ -113,6 +114,7 @@ const Search = () => { return ( <> +