From 5ef1495366e824a1d003dfff897483d7b67016de Mon Sep 17 00:00:00 2001 From: Sameen Fatima <55431213+sameenfatima78@users.noreply.github.com> Date: Mon, 18 Sep 2023 14:10:30 +0500 Subject: [PATCH] Revert "Revert "feat: subsidy box points to learner credit (#810)" (#821)" This reverts commit 3fdce2ed95b4ac5099c310840e619e87ff63d4ec. --- .../sidebar/EnterpriseOffersSummaryCard.jsx | 72 ------------------- .../sidebar/LearnerCreditSummaryCard.jsx | 62 ++++++++++++++++ .../dashboard/sidebar/SubsidiesSummary.jsx | 28 ++++++-- .../dashboard/sidebar/data/constants.js | 6 ++ .../sidebar/tests/DashboardSidebar.test.jsx | 47 +++++++++++- .../EnterpriseOffersSummaryCard.test.jsx | 65 ----------------- .../tests/LearnerCreditSummaryCard.test.jsx | 42 +++++++++++ src/components/dashboard/sidebar/utils.js | 5 ++ .../enterprise-user-subsidy/UserSubsidy.jsx | 12 +++- .../data/hooks/hooks.js | 20 ++++++ .../data/hooks/hooks.test.jsx | 43 +++++++++++ .../enterprise-user-subsidy/data/service.js | 10 +++ .../tests/UserSubsidy.test.jsx | 18 ++++- 13 files changed, 285 insertions(+), 145 deletions(-) delete mode 100644 src/components/dashboard/sidebar/EnterpriseOffersSummaryCard.jsx create mode 100644 src/components/dashboard/sidebar/LearnerCreditSummaryCard.jsx delete mode 100644 src/components/dashboard/sidebar/tests/EnterpriseOffersSummaryCard.test.jsx create mode 100644 src/components/dashboard/sidebar/tests/LearnerCreditSummaryCard.test.jsx create mode 100644 src/components/dashboard/sidebar/utils.js diff --git a/src/components/dashboard/sidebar/EnterpriseOffersSummaryCard.jsx b/src/components/dashboard/sidebar/EnterpriseOffersSummaryCard.jsx deleted file mode 100644 index 3cd4df7ef5..0000000000 --- a/src/components/dashboard/sidebar/EnterpriseOffersSummaryCard.jsx +++ /dev/null @@ -1,72 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { Badge, Row, Col } from '@edx/paragon'; -import dayjs from 'dayjs'; -import { - ENTERPRISE_OFFER_SUMMARY_CARD_TITLE, - ENTERPRISE_OFFER_ACTIVE_BADGE_LABEL, - ENTERPRISE_OFFER_ACTIVE_BADGE_VARIANT, -} from './data/constants'; -import SidebarCard from './SidebarCard'; - -function getOfferExpiringFirst(offers) { - return offers - .filter(offer => offer.isCurrent) - .sort((a, b) => new Date(a.endDatetime) - new Date(b.endDatetime))[0]; -} - -const EnterpriseOffersSummaryCard = ({ - className, offers, searchCoursesCta, -}) => { - const offerExpiringFirst = getOfferExpiringFirst(offers); - - return ( - -

{ENTERPRISE_OFFER_SUMMARY_CARD_TITLE}

- - {ENTERPRISE_OFFER_ACTIVE_BADGE_LABEL} - - - ) - } - cardClassNames={className} - > -

- Apply your organization's Learner Credit balance to enroll into courses with no out of pocket cost. -

- {offerExpiringFirst?.endDatetime && ( -

- Available until {dayjs(offerExpiringFirst.endDatetime).format('MMM D, YYYY')} -

- )} - {searchCoursesCta && ( - - {searchCoursesCta} - - )} -
- ); -}; - -EnterpriseOffersSummaryCard.propTypes = { - offers: PropTypes.arrayOf(PropTypes.shape({ - endDatetime: PropTypes.string, - remainingBalanceForUser: PropTypes.number, - })).isRequired, - className: PropTypes.string, - searchCoursesCta: PropTypes.node, -}; - -EnterpriseOffersSummaryCard.defaultProps = { - className: undefined, - searchCoursesCta: undefined, -}; - -export default EnterpriseOffersSummaryCard; diff --git a/src/components/dashboard/sidebar/LearnerCreditSummaryCard.jsx b/src/components/dashboard/sidebar/LearnerCreditSummaryCard.jsx new file mode 100644 index 0000000000..009ed9418a --- /dev/null +++ b/src/components/dashboard/sidebar/LearnerCreditSummaryCard.jsx @@ -0,0 +1,62 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Badge, Row, Col } from '@edx/paragon'; +import dayjs from 'dayjs'; +import { + LEARNER_CREDIT_SUMMARY_CARD_TITLE, + LEARNER_CREDIT_ACTIVE_BADGE_LABEL, + LEARNER_CREDIT_ACTIVE_BADGE_VARIANT, + LEARNER_CREDIT_CARD_SUMMARY, +} from './data/constants'; +import SidebarCard from './SidebarCard'; + +const LearnerCreditSummaryCard = ({ + className, expirationDate, searchCoursesCta, +}) => ( + +

{LEARNER_CREDIT_SUMMARY_CARD_TITLE}

+ + {LEARNER_CREDIT_ACTIVE_BADGE_LABEL} + + + ) + } + cardClassNames={className} + > +

+ { LEARNER_CREDIT_CARD_SUMMARY } +

+ + {expirationDate && ( +

+ Available until {dayjs(expirationDate).format('MMM D, YYYY')} +

+ )} + + {searchCoursesCta && ( + + {searchCoursesCta} + + )} +
+); + +LearnerCreditSummaryCard.propTypes = { + expirationDate: PropTypes.string.isRequired, + className: PropTypes.string, + searchCoursesCta: PropTypes.node, +}; + +LearnerCreditSummaryCard.defaultProps = { + className: undefined, + searchCoursesCta: undefined, +}; + +export default LearnerCreditSummaryCard; diff --git a/src/components/dashboard/sidebar/SubsidiesSummary.jsx b/src/components/dashboard/sidebar/SubsidiesSummary.jsx index 6a28f068c3..76a8337927 100644 --- a/src/components/dashboard/sidebar/SubsidiesSummary.jsx +++ b/src/components/dashboard/sidebar/SubsidiesSummary.jsx @@ -7,13 +7,23 @@ import { Button } from '@edx/paragon'; import classNames from 'classnames'; import CouponCodesSummaryCard from './CouponCodesSummaryCard'; import SubscriptionSummaryCard from './SubscriptionSummaryCard'; -import EnterpriseOffersSummaryCard from './EnterpriseOffersSummaryCard'; +import LearnerCreditSummaryCard from './LearnerCreditSummaryCard'; import { UserSubsidyContext } from '../../enterprise-user-subsidy'; import { LICENSE_STATUS } from '../../enterprise-user-subsidy/data/constants'; import { CATALOG_ACCESS_CARD_BUTTON_TEXT } from './data/constants'; import SidebarCard from './SidebarCard'; import { CourseEnrollmentsContext } from '../main-content/course-enrollments/CourseEnrollmentsContextProvider'; import { SubsidyRequestsContext, SUBSIDY_TYPE } from '../../enterprise-subsidy-requests'; +import { getOfferExpiringFirst, getPolicyExpiringFirst } from './utils'; + +function getLearnerCreditSummaryCardData({ enterpriseOffers, redeemableLearnerCreditPolicies }) { + const enterpriseOfferExpiringFirst = getOfferExpiringFirst(enterpriseOffers); + const learnerCreditPolicyExpiringFirst = getPolicyExpiringFirst(redeemableLearnerCreditPolicies); + return { + expirationDate: learnerCreditPolicyExpiringFirst?.subsidyExpirationDate + || enterpriseOfferExpiringFirst?.endDatetime, + }; +} const SubsidiesSummary = ({ className, showSearchCoursesCta, totalCoursesEligibleForCertificate, courseEndDate, programProgressPage, @@ -35,8 +45,14 @@ const SubsidiesSummary = ({ couponCodes: { couponCodesCount }, enterpriseOffers, canEnrollWithEnterpriseOffers, + redeemableLearnerCreditPolicies, } = useContext(UserSubsidyContext); + const learnerCreditSummaryCardData = getLearnerCreditSummaryCardData({ + enterpriseOffers, + redeemableLearnerCreditPolicies, + }); + const { requestsBySubsidyType, } = useContext(SubsidyRequestsContext); @@ -54,9 +70,10 @@ const SubsidiesSummary = ({ && userSubscriptionLicense?.status === LICENSE_STATUS.ACTIVATED) || licenseRequests.length > 0; const hasAssignedCodesOrCodeRequests = couponCodesCount > 0 || couponCodeRequests.length > 0; + const hasAvailableLearnerCreditPolicies = redeemableLearnerCreditPolicies?.length > 0; const hasAvailableSubsidyOrRequests = hasActiveLicenseOrLicenseRequest - || hasAssignedCodesOrCodeRequests || canEnrollWithEnterpriseOffers; + || hasAssignedCodesOrCodeRequests || canEnrollWithEnterpriseOffers || hasAvailableLearnerCreditPolicies; if (!hasAvailableSubsidyOrRequests) { return null; @@ -100,10 +117,11 @@ const SubsidiesSummary = ({ className="border-0 shadow-none" /> )} - {canEnrollWithEnterpriseOffers && ( - )} diff --git a/src/components/dashboard/sidebar/data/constants.js b/src/components/dashboard/sidebar/data/constants.js index d442ec0c5c..38e6cbea79 100644 --- a/src/components/dashboard/sidebar/data/constants.js +++ b/src/components/dashboard/sidebar/data/constants.js @@ -36,6 +36,12 @@ export const ENTERPRISE_OFFER_ACTIVE_BADGE_LABEL = 'Active'; export const ENTERPRISE_OFFER_ACTIVE_BADGE_VARIANT = 'success'; export const ENTERPRISE_OFFER_SUMMARY_CARD_SUMMARY = 'Apply your organization\'s learner credit balance to enroll into courses with no out of pocket cost.'; +// LearnerCreditSummaryCard +export const LEARNER_CREDIT_SUMMARY_CARD_TITLE = 'Learner Credit'; +export const LEARNER_CREDIT_ACTIVE_BADGE_LABEL = 'Active'; +export const LEARNER_CREDIT_ACTIVE_BADGE_VARIANT = 'success'; +export const LEARNER_CREDIT_CARD_SUMMARY = 'Apply your organization\'s learner credit balance to enroll into courses with no out of pocket cost.'; + // Dashboard Sidebar texts export const CATALOG_ACCESS_CARD_BUTTON_TEXT = 'Find a course'; export const NEED_HELP_BLOCK_TITLE = 'Need help?'; diff --git a/src/components/dashboard/sidebar/tests/DashboardSidebar.test.jsx b/src/components/dashboard/sidebar/tests/DashboardSidebar.test.jsx index f97e12c810..679c23dd7a 100644 --- a/src/components/dashboard/sidebar/tests/DashboardSidebar.test.jsx +++ b/src/components/dashboard/sidebar/tests/DashboardSidebar.test.jsx @@ -13,6 +13,7 @@ import { LICENSE_REQUESTED_NOTICE, COUPON_CODES_SUMMARY_NOTICE, ENTERPRISE_OFFER_SUMMARY_CARD_TITLE, + LEARNER_CREDIT_SUMMARY_CARD_TITLE, } from '../data/constants'; import { LICENSE_STATUS } from '../../../enterprise-user-subsidy/data/constants'; import CourseEnrollmentsContextProvider from '../../main-content/course-enrollments/CourseEnrollmentsContextProvider'; @@ -61,6 +62,7 @@ describe('', () => { couponCodesCount: 0, }, enterpriseOffers: [], + redeemableLearnerCreditPolicies: undefined, }; const initialAppState = { enterpriseConfig: { @@ -173,7 +175,7 @@ describe('', () => { ); expect(screen.queryByText(SUBSCRIPTION_SUMMARY_CARD_TITLE)).toBeFalsy(); }); - test('Enterprise offers summary card is displayed when enterprise has active offers and no subscriptions or coupons', () => { + test('Enterprise offers summary card is displayed when enterprise has active offers and no subscriptions or coupons or learner credit', () => { renderWithRouter( ', () => { expect(screen.queryByText(SUBSCRIPTION_SUMMARY_CARD_TITLE)).not.toBeInTheDocument(); expect(screen.queryByText(COUPON_CODES_SUMMARY_NOTICE)).toBeInTheDocument(); }); + + test('Learner credit summary card is displayed when enterprise has learner credit', () => { + renderWithRouter( + , + ); + expect(screen.queryByText(LEARNER_CREDIT_SUMMARY_CARD_TITLE)).toBeInTheDocument(); + }); + + test('Only learner credit summary card is displayed when enterprise has both; learner credit and offers', () => { + const policyExpirationDate = '2030-01-01 12:00:00Z'; + const offerEndDate = '2027-10-25'; + renderWithRouter( + , + ); + expect(screen.getByText('2030', { exact: false })).toBeInTheDocument(); + expect(screen.queryByText('2027', { exact: false })).toBeFalsy(); + }); + test('Find a course button is not rendered when user has no coupon codes or license subsidy', () => { renderWithRouter( ', () => { - it('should render searchCoursesCta', () => { - const cta = 'Search Courses'; - render( - {cta} - } - />, - ); - - expect(screen.getByText(ENTERPRISE_OFFER_SUMMARY_CARD_TITLE)).toBeInTheDocument(); - expect(screen.getByText(cta)).toBeInTheDocument(); - }); - - it('should render default summary text if remainingBalanceForUser is null', () => { - render( - , - ); - - expect(screen.getByTestId('offer-summary-text')).toBeInTheDocument(); - }); - - it('should render earliest, current offer end date, if applicable', () => { - render( - , - ); - expect(screen.getByTestId('offer-summary-end-date-text')).toBeInTheDocument(); - expect(screen.getByText('Dec 1, 2023')).toBeInTheDocument(); - }); -}); diff --git a/src/components/dashboard/sidebar/tests/LearnerCreditSummaryCard.test.jsx b/src/components/dashboard/sidebar/tests/LearnerCreditSummaryCard.test.jsx new file mode 100644 index 0000000000..ccc48b5bdc --- /dev/null +++ b/src/components/dashboard/sidebar/tests/LearnerCreditSummaryCard.test.jsx @@ -0,0 +1,42 @@ +import React from 'react'; +import '@testing-library/jest-dom/extend-expect'; +import { screen, render } from '@testing-library/react'; +import LearnerCreditSummaryCard from '../LearnerCreditSummaryCard'; +import { LEARNER_CREDIT_SUMMARY_CARD_TITLE } from '../data/constants'; + +const TEST_EXPIRATION_DATE = '2022-06-01T00:00:00Z'; + +describe('', () => { + it('should render searchCoursesCta', () => { + const cta = 'Search Courses'; + render( + {cta} + } + />, + ); + expect(screen.getByText(LEARNER_CREDIT_SUMMARY_CARD_TITLE)).toBeInTheDocument(); + expect(screen.getByText(cta)).toBeInTheDocument(); + }); + + it('should render default summary text', () => { + render( + , + ); + expect(screen.getByTestId('learner-credit-summary-text')).toBeInTheDocument(); + }); + + it('should render the expiration date passed as prop', () => { + render( + , + ); + expect(screen.getByTestId('learner-credit-summary-end-date-text')).toBeInTheDocument(); + expect(screen.getByText('2022', { exact: false })).toBeInTheDocument(); + }); +}); diff --git a/src/components/dashboard/sidebar/utils.js b/src/components/dashboard/sidebar/utils.js new file mode 100644 index 0000000000..17b20e7e64 --- /dev/null +++ b/src/components/dashboard/sidebar/utils.js @@ -0,0 +1,5 @@ +export const getOfferExpiringFirst = (offers) => offers?.filter(offer => offer.isCurrent) + .sort((a, b) => new Date(a.endDatetime) - new Date(b.endDatetime))[0]; + +export const getPolicyExpiringFirst = (policies) => policies?.filter(policy => policy.active) + .sort((a, b) => new Date(a.subsidyExpirationDate) - new Date(b.subsidyExpirationDate))[0]; diff --git a/src/components/enterprise-user-subsidy/UserSubsidy.jsx b/src/components/enterprise-user-subsidy/UserSubsidy.jsx index 87ac8f8f78..400f1d8cd6 100644 --- a/src/components/enterprise-user-subsidy/UserSubsidy.jsx +++ b/src/components/enterprise-user-subsidy/UserSubsidy.jsx @@ -9,6 +9,7 @@ import { LoadingSpinner } from '../loading-spinner'; import { useCouponCodes, useSubscriptions, + useRedeemableLearnerCreditPolicies, } from './data/hooks'; import { useEnterpriseOffers } from './enterprise-offers/data/hooks'; import { LOADING_SCREEN_READER_TEXT } from './data/constants'; @@ -18,6 +19,7 @@ export const UserSubsidyContext = createContext(); const UserSubsidy = ({ children }) => { const { enterpriseConfig, authenticatedUser } = useContext(AppContext); + const { userId } = authenticatedUser; // Subscriptions const { customerAgreementConfig, @@ -28,6 +30,11 @@ const UserSubsidy = ({ children }) => { activateUserLicense, } = useSubscriptions({ enterpriseConfig, authenticatedUser }); + const { + data: redeemableLearnerCreditPolicies, + isLoading: isLoadingRedeemablePolicies, + } = useRedeemableLearnerCreditPolicies(enterpriseConfig.uuid, userId); + // Coupon Codes const [couponCodes, isLoadingCouponCodes] = useCouponCodes(enterpriseConfig.uuid); @@ -50,10 +57,11 @@ const UserSubsidy = ({ children }) => { isLoadingSubscriptions, isLoadingCouponCodes, isLoadingEnterpriseOffers, + isLoadingRedeemablePolicies, ]; return loadingStates.includes(true); }, - [isLoadingSubscriptions, isLoadingCouponCodes, isLoadingEnterpriseOffers], + [isLoadingSubscriptions, isLoadingCouponCodes, isLoadingEnterpriseOffers, isLoadingRedeemablePolicies], ); const contextValue = useMemo( @@ -72,6 +80,7 @@ const UserSubsidy = ({ children }) => { showExpirationNotifications, customerAgreementConfig, activateUserLicense, + redeemableLearnerCreditPolicies, }; }, [ @@ -86,6 +95,7 @@ const UserSubsidy = ({ children }) => { showExpirationNotifications, customerAgreementConfig, activateUserLicense, + redeemableLearnerCreditPolicies, ], ); diff --git a/src/components/enterprise-user-subsidy/data/hooks/hooks.js b/src/components/enterprise-user-subsidy/data/hooks/hooks.js index d8d556f57c..9069ed3d93 100644 --- a/src/components/enterprise-user-subsidy/data/hooks/hooks.js +++ b/src/components/enterprise-user-subsidy/data/hooks/hooks.js @@ -13,6 +13,7 @@ import { LICENSE_STATUS } from '../constants'; import { fetchSubscriptionLicensesForUser, fetchCustomerAgreementData, + fetchRedeemableLearnerCreditPolicies, requestAutoAppliedLicense, activateLicense, } from '../service'; @@ -244,3 +245,22 @@ export function useCustomerAgreementData(enterpriseId) { return [customerAgreement, isLoading]; } + +const getRedeemablePoliciesData = async ({ queryKey }) => { + const enterpriseId = queryKey[1]; + const userID = queryKey[2]; + try { + const response = await fetchRedeemableLearnerCreditPolicies(enterpriseId, userID); + return camelCaseObject(response.data); + } catch (error) { + logError(error); + return []; + } +}; + +export function useRedeemableLearnerCreditPolicies(enterpriseId, userID) { + return useQuery({ + queryKey: ['redeemablePolicies', enterpriseId, userID], + queryFn: getRedeemablePoliciesData, + }); +} diff --git a/src/components/enterprise-user-subsidy/data/hooks/hooks.test.jsx b/src/components/enterprise-user-subsidy/data/hooks/hooks.test.jsx index 31824dc105..7972b3dc6e 100644 --- a/src/components/enterprise-user-subsidy/data/hooks/hooks.test.jsx +++ b/src/components/enterprise-user-subsidy/data/hooks/hooks.test.jsx @@ -7,12 +7,14 @@ import { useCouponCodes, useCustomerAgreementData, useSubscriptionLicense, + useRedeemableLearnerCreditPolicies, } from '.'; import { fetchSubscriptionLicensesForUser, activateLicense, requestAutoAppliedLicense, fetchCustomerAgreementData, + fetchRedeemableLearnerCreditPolicies, } from '../service'; import { fetchCouponsOverview } from '../../coupons/data/service'; import { fetchCouponCodeAssignments } from '../../coupons'; @@ -37,6 +39,7 @@ jest.mock('../../../../config', () => ({ const TEST_SUBSCRIPTION_UUID = 'test-subscription-uuid'; const TEST_LICENSE_UUID = 'test-license-uuid'; const TEST_ENTERPRISE_UUID = 'test-enterprise-uuid'; +const TEST_USER_ID = '35'; const TEST_ACTIVATION_KEY = 'test-activation-key'; const mockEnterpriseConfig = { @@ -50,6 +53,25 @@ const mockLicense = { activation_key: TEST_ACTIVATION_KEY, }; const mockSubscriptionPlan = { uuid: TEST_SUBSCRIPTION_UUID, is_active: true, title: 'title' }; +const mockLearnerCredit = [ + { + uuid: '3a93089e-9ff6-4d70-88d5-71c9cda7ce12', + policy_redemption_url: 'http://localhost:18270/api/v1/policy-redemption/3a93089e-9ff6-4d70-88d5-71c9cda7ce12/redeem/', + remaining_balance_per_user: 500, + remaining_balance: 50000, + subsidy_expiration_date: '2030-01-01 12:00:00Z', + policy_type: 'PerLearnerEnrollmentCreditAccessPolicy', + enterprise_customer_uuid: 'd0a6c526-670b-4991-b213-83f7b1216f29', + description: 'test Subsidy policy', + active: true, + catalog_uuid: '8e353fcc-b623-4912-85ee-1f0d045c6d1c', + subsidy_uuid: '8e353fcc-b623-4912-85ee-1f0d045c6d1c', + access_method: 'direct', + spend_limit: 5000, + per_learner_enrollment_limit: 10, + per_learner_spend_limit: 1500, + }, +]; const mockUser = { roles: [] }; const mockEnterpriseUser = { roles: [`enterprise_learner:${TEST_ENTERPRISE_UUID}`] }; const mockCustomerAgreement = { @@ -342,3 +364,24 @@ describe('useCustomerAgreementData', () => { ]); }); }); + +describe('useRedeemableLearnerCreditPolicies', () => { + const Wrapper = ({ children }) => ( + + {children} + + ); + + it('fetches and returns redeemable learner credit policies', async () => { + fetchRedeemableLearnerCreditPolicies.mockResolvedValueOnce({ + data: mockLearnerCredit, + }); + const { result, waitForNextUpdate } = renderHook( + () => useRedeemableLearnerCreditPolicies(TEST_ENTERPRISE_UUID, TEST_USER_ID), + { wrapper: Wrapper }, + ); + await waitForNextUpdate(); + expect(fetchRedeemableLearnerCreditPolicies).toHaveBeenCalledWith(TEST_ENTERPRISE_UUID, TEST_USER_ID); + expect(result.current.data).toEqual(camelCaseObject(mockLearnerCredit)); + }); +}); diff --git a/src/components/enterprise-user-subsidy/data/service.js b/src/components/enterprise-user-subsidy/data/service.js index f07541efc6..667846e526 100644 --- a/src/components/enterprise-user-subsidy/data/service.js +++ b/src/components/enterprise-user-subsidy/data/service.js @@ -35,6 +35,16 @@ export function fetchCustomerAgreementData(enterpriseUUID) { return getAuthenticatedHttpClient().get(url); } +export function fetchRedeemableLearnerCreditPolicies(enterpriseUUID, userID) { + const queryParams = new URLSearchParams({ + enterprise_customer_uuid: enterpriseUUID, + lms_user_id: userID, + }); + const config = getConfig(); + const url = `${config.ENTERPRISE_ACCESS_BASE_URL}/api/v1/policy-redemption/credits_available/?${queryParams.toString()}`; + return getAuthenticatedHttpClient().get(url); +} + export function requestAutoAppliedLicense(customerAgreementId) { const config = getConfig(); const url = `${config.LICENSE_MANAGER_URL}/api/v1/customer-agreement/${customerAgreementId}/auto-apply/`; diff --git a/src/components/enterprise-user-subsidy/tests/UserSubsidy.test.jsx b/src/components/enterprise-user-subsidy/tests/UserSubsidy.test.jsx index f34291ecb9..6d83e947f9 100644 --- a/src/components/enterprise-user-subsidy/tests/UserSubsidy.test.jsx +++ b/src/components/enterprise-user-subsidy/tests/UserSubsidy.test.jsx @@ -6,13 +6,14 @@ import '@testing-library/jest-dom/extend-expect'; import UserSubsidy from '../UserSubsidy'; import { LOADING_SCREEN_READER_TEXT } from '../data/constants'; -import { useCouponCodes, useSubscriptions } from '../data/hooks'; +import { useCouponCodes, useSubscriptions, useRedeemableLearnerCreditPolicies } from '../data/hooks'; import { useEnterpriseOffers } from '../enterprise-offers/data/hooks'; jest.mock('../data/hooks', () => ({ ...jest.requireActual('../data/hooks'), useSubscriptions: jest.fn().mockReturnValue({}), useCouponCodes: jest.fn().mockReturnValue([]), + useRedeemableLearnerCreditPolicies: jest.fn().mockReturnValue([]), })); jest.mock('../enterprise-offers/data/hooks', () => ({ @@ -60,47 +61,62 @@ describe('UserSubsidy', () => { isSubscriptionsLoading: false, isCouponCodesLoading: false, isEnterpriseOffersLoading: false, + isLoadingRedeemablePolicies: false, isLoadingExpected: false, }, { isSubscriptionsLoading: true, isCouponCodesLoading: false, isEnterpriseOffersLoading: false, + isLoadingRedeemablePolicies: false, isLoadingExpected: true, }, { isSubscriptionsLoading: false, isCouponCodesLoading: true, isEnterpriseOffersLoading: false, + isLoadingRedeemablePolicies: false, isLoadingExpected: true, }, { isSubscriptionsLoading: false, isCouponCodesLoading: false, isEnterpriseOffersLoading: true, + isLoadingRedeemablePolicies: false, + isLoadingExpected: true, + }, + { + isSubscriptionsLoading: false, + isCouponCodesLoading: false, + isEnterpriseOffersLoading: false, + isLoadingRedeemablePolicies: true, isLoadingExpected: true, }, { isSubscriptionsLoading: true, isCouponCodesLoading: true, isEnterpriseOffersLoading: true, + isLoadingRedeemablePolicies: true, isLoadingExpected: true, }, { isSubscriptionsLoading: true, isCouponCodesLoading: true, isEnterpriseOffersLoading: false, + isLoadingRedeemablePolicies: true, isLoadingExpected: true, }, ])('shows loading spinner when expected (%s)', ({ isSubscriptionsLoading, isCouponCodesLoading, isEnterpriseOffersLoading, + isLoadingRedeemablePolicies, isLoadingExpected, }) => { useSubscriptions.mockReturnValue({ isLoading: isSubscriptionsLoading }); useCouponCodes.mockReturnValue([[], isCouponCodesLoading]); useEnterpriseOffers.mockReturnValue({ isLoading: isEnterpriseOffersLoading }); + useRedeemableLearnerCreditPolicies.mockReturnValue({ data: [], isLoading: isLoadingRedeemablePolicies }); const Component = (