Skip to content

Commit

Permalink
feat: add alert modal and conditional text for expired subscriptions (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
jajjibhai008 authored Oct 4, 2024
1 parent 3f6cf6d commit beca20e
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 12 deletions.
28 changes: 28 additions & 0 deletions src/components/course/ExpiredSubscriptionModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {
StandardModal, useToggle,
} from '@openedx/paragon';
import { Link } from 'react-router-dom';
import { useSubscriptions } from '../app/data';

const ExpiredSubscriptionModal = () => {
const { data: { customerAgreement } } = useSubscriptions();
const [isOpen, ,close] = useToggle(true);
if (!customerAgreement?.hasCustomLicenseExpirationMessaging) {
return null;
}
return (
<StandardModal
isOpen={isOpen}
className="d-flex justify-content-center align-items-center text-wrap text-right "
hasCloseButton
onClose={close}
>
<p className="text-center">
{customerAgreement?.expiredSubscriptionModalMessaging}
<Link className="text-decoration-none" to={customerAgreement?.urlForExpiredModal}> {customerAgreement?.hyperLinkTextForExpiredModal}</Link>
</p>
</StandardModal>
);
};

export default ExpiredSubscriptionModal;
31 changes: 20 additions & 11 deletions src/components/course/course-header/CourseRunCardStatus.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Card } from '@openedx/paragon';
import { Lock } from '@openedx/paragon/icons';

import { DISABLED_ENROLL_REASON_TYPES } from '../data/constants';
import { useSubscriptions } from '../../app/data';

/**
* Display under these situations:
Expand All @@ -28,25 +29,33 @@ const CourseRunCardStatus = ({
isUserEnrolled,
userCanRequestSubsidyForCourse,
}) => {
const { data: { customerAgreement } } = useSubscriptions();
const missingUserSubsidyReasonType = missingUserSubsidyReason?.reason;
const missingUserSubsidyReasonUserMessage = missingUserSubsidyReason?.userMessage;
const missingUserSubsidyReasonActions = missingUserSubsidyReason?.actions;

const hasValidReason = !!(missingUserSubsidyReasonType && missingUserSubsidyReasonUserMessage);
if (isUserEnrolled || !hasValidReason || userCanRequestSubsidyForCourse) {
return null;
}

return (
<Card.Status
variant="primary"
icon={Lock}
actions={missingUserSubsidyReasonActions}
>
<p className="font-weight-bold">
{missingUserSubsidyReasonUserMessage}
</p>
</Card.Status>
customerAgreement?.hasCustomLicenseExpirationMessaging ? (
<Card.Status
data-testid="custom-license-expiration-message-id"
variant="primary"
className="d-flex justify-content-center align-items-center"
icon={Lock}
/>
) : (
<Card.Status
variant="primary"
icon={Lock}
actions={missingUserSubsidyReasonActions}
>
<p className="font-weight-bold">
{missingUserSubsidyReasonUserMessage}
</p>
</Card.Status>
)
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ import '@testing-library/jest-dom/extend-expect';

import CourseRunCardStatus from '../CourseRunCardStatus';

import {
useSubscriptions,
} from '../../../app/data';

jest.mock('../../../app/data', () => ({
...jest.requireActual('../../../app/data'),
useSubscriptions: jest.fn(),
}));

const baseProps = {
missingUserSubsidyReason: undefined,
isUserEnrolled: false,
Expand All @@ -17,6 +26,18 @@ const mockMissingUserSubsidyReason = {
};

describe('<CourseRunCardStatus />', () => {
beforeEach(() => {
useSubscriptions.mockReturnValue({
data: {
customerAgreement: {
hasCustomLicenseExpirationMessaging: false,
expiredSubscriptionModalMessaging: null,
urlForExpiredModal: null,
hyperLinkTextForExpiredModal: null,
},
},
});
});
test('does not render if there is no missing subsidy reason', () => {
const { container } = render(<CourseRunCardStatus />);
expect(container).toBeEmptyDOMElement();
Expand Down Expand Up @@ -52,4 +73,20 @@ describe('<CourseRunCardStatus />', () => {
expect(screen.queryByText(mockMissingUserSubsidyReason.userMessage)).not.toBeInTheDocument();
expect(screen.queryByTestId(mockActionTestId)).not.toBeInTheDocument();
});

test('render lock status when license has been expired', () => {
const props = {
...baseProps,
missingUserSubsidyReason: mockMissingUserSubsidyReason,
};
useSubscriptions.mockReturnValue({
data: {
customerAgreement: {
hasCustomLicenseExpirationMessaging: true,
},
},
});
render(<CourseRunCardStatus {...props} />);
expect(screen.getByTestId('custom-license-expiration-message-id')).toBeInTheDocument();
});
});
2 changes: 2 additions & 0 deletions src/components/course/routes/CourseAbout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
useIsAssignmentsOnlyLearner,
usePassLearnerCsodParams,
} from '../../app/data';
import ExpiredSubscriptionModal from '../ExpiredSubscriptionModal';

const CourseAbout = () => {
const { data: canOnlyViewHighlightSets } = useCanOnlyViewHighlights();
Expand All @@ -28,6 +29,7 @@ const CourseAbout = () => {

return (
<>
<ExpiredSubscriptionModal />
<CourseHeader />
<Container size="lg" className="py-5">
<Row>
Expand Down
13 changes: 12 additions & 1 deletion src/components/course/routes/tests/CourseAbout.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { AppContext } from '@edx/frontend-platform/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import CourseAbout from '../CourseAbout';
import { renderWithRouter } from '../../../../utils/tests';
import { useEnterpriseCustomer, useCanOnlyViewHighlights } from '../../../app/data';
import { useEnterpriseCustomer, useCanOnlyViewHighlights, useSubscriptions } from '../../../app/data';
import { authenticatedUserFactory, enterpriseCustomerFactory } from '../../../app/data/services/data/__factories__';

jest.mock('../../../app/data', () => ({
Expand All @@ -15,6 +15,7 @@ jest.mock('../../../app/data', () => ({
useIsAssignmentsOnlyLearner: jest.fn().mockReturnValue(false),
useCanOnlyViewHighlights: jest.fn().mockReturnValue(false),
usePassLearnerCsodParams: jest.fn(),
useSubscriptions: jest.fn(),
}));

jest.mock('../../course-header/CourseHeader', () => jest.fn(() => (
Expand Down Expand Up @@ -67,6 +68,16 @@ describe('CourseAbout', () => {
beforeEach(() => {
jest.clearAllMocks();
useEnterpriseCustomer.mockReturnValue({ data: mockEnterpriseCustomer });
useSubscriptions.mockReturnValue({
data: {
customerAgreement: {
hasCustomLicenseExpirationMessaging: false,
expiredSubscriptionModalMessaging: null,
urlForExpiredModal: null,
hyperLinkTextForExpiredModal: null,
},
},
});
});

it('renders', () => {
Expand Down

0 comments on commit beca20e

Please sign in to comment.