diff --git a/src/components/app/data/hooks/index.js b/src/components/app/data/hooks/index.js
index 3eee9934f..691d7f99d 100644
--- a/src/components/app/data/hooks/index.js
+++ b/src/components/app/data/hooks/index.js
@@ -48,3 +48,4 @@ export { default as useVideoCourseMetadata } from './useVideoCourseMetadata';
export { default as useVideoCourseReviews } from './useVideoCourseReviews';
export { default as useBFF } from './useBFF';
export { default as useIsBFFEnabled } from './useIsBFFEnabled';
+export { default as useHasValidLicenseOrSubscriptionRequestsEnabled } from './useHasValidLicenseOrSubscriptionRequestsEnabled';
diff --git a/src/components/app/data/hooks/useHasValidLicenseOrSubscriptionRequestsEnabled.js b/src/components/app/data/hooks/useHasValidLicenseOrSubscriptionRequestsEnabled.js
new file mode 100644
index 000000000..6507a12a0
--- /dev/null
+++ b/src/components/app/data/hooks/useHasValidLicenseOrSubscriptionRequestsEnabled.js
@@ -0,0 +1,14 @@
+import { SUBSIDY_TYPE } from '../../../../constants';
+import { LICENSE_STATUS } from '../../../enterprise-user-subsidy/data/constants';
+import { useBrowseAndRequestConfiguration } from './useBrowseAndRequest';
+import useSubscriptions from './useSubscriptions';
+
+export default function useHasValidLicenseOrSubscriptionRequestsEnabled() {
+ const { data: { subscriptionLicense } } = useSubscriptions();
+ const { data: browseAndRequestConfiguration } = useBrowseAndRequestConfiguration();
+ const hasActivatedAndCurrentLicense = subscriptionLicense?.status === LICENSE_STATUS.ACTIVATED
+ && subscriptionLicense?.subscriptionPlan?.isCurrent;
+ const hasRequestsEnabledForSubscriptions = browseAndRequestConfiguration?.subsidyRequestsEnabled
+ && browseAndRequestConfiguration.subsidyType === SUBSIDY_TYPE.LICENSE;
+ return hasActivatedAndCurrentLicense || hasRequestsEnabledForSubscriptions;
+}
diff --git a/src/components/app/data/hooks/useHasValidLicenseOrSubscriptionRequestsEnabled.test.jsx b/src/components/app/data/hooks/useHasValidLicenseOrSubscriptionRequestsEnabled.test.jsx
new file mode 100644
index 000000000..3760b2f00
--- /dev/null
+++ b/src/components/app/data/hooks/useHasValidLicenseOrSubscriptionRequestsEnabled.test.jsx
@@ -0,0 +1,94 @@
+import { renderHook } from '@testing-library/react-hooks';
+import useHasValidLicenseOrSubscriptionRequestsEnabled from './useHasValidLicenseOrSubscriptionRequestsEnabled';
+import { LICENSE_STATUS } from '../../../enterprise-user-subsidy/data/constants';
+import { SUBSIDY_TYPE } from '../../../../constants';
+import { useBrowseAndRequestConfiguration } from './useBrowseAndRequest';
+import useSubscriptions from './useSubscriptions';
+
+jest.mock('./useBrowseAndRequest');
+jest.mock('./useSubscriptions');
+
+describe('useHasValidLicenseOrSubscriptionRequestsEnabled', () => {
+ it('should return true when the subscription license is activated and current', () => {
+ useSubscriptions.mockReturnValue({
+ data: {
+ subscriptionLicense: {
+ status: LICENSE_STATUS.ACTIVATED,
+ subscriptionPlan: {
+ isCurrent: true,
+ },
+ },
+ },
+ });
+ useBrowseAndRequestConfiguration.mockReturnValue({
+ data: {
+ subsidyRequestsEnabled: false,
+ subsidyType: SUBSIDY_TYPE.LICENSE,
+ },
+ });
+
+ const { result } = renderHook(() => useHasValidLicenseOrSubscriptionRequestsEnabled());
+ expect(result.current).toBe(true);
+ });
+
+ it('should return true when subsidy requests are enabled for subscriptions', () => {
+ useSubscriptions.mockReturnValue({
+ data: {
+ subscriptionLicense: {
+ status: LICENSE_STATUS.REVOKED,
+ subscriptionPlan: {
+ isCurrent: false,
+ },
+ },
+ },
+ });
+ useBrowseAndRequestConfiguration.mockReturnValue({
+ data: {
+ subsidyRequestsEnabled: true,
+ subsidyType: SUBSIDY_TYPE.LICENSE,
+ },
+ });
+
+ const { result } = renderHook(() => useHasValidLicenseOrSubscriptionRequestsEnabled());
+ expect(result.current).toBe(true);
+ });
+
+ it('should return false when the subscription license is not activated and not current, and subsidy requests are not enabled', () => {
+ useSubscriptions.mockReturnValue({
+ data: {
+ subscriptionLicense: {
+ status: LICENSE_STATUS.REVOKED,
+ subscriptionPlan: {
+ isCurrent: false,
+ },
+ },
+ },
+ });
+ useBrowseAndRequestConfiguration.mockReturnValue({
+ data: {
+ subsidyRequestsEnabled: false,
+ subsidyType: SUBSIDY_TYPE.LICENSE,
+ },
+ });
+
+ const { result } = renderHook(() => useHasValidLicenseOrSubscriptionRequestsEnabled());
+ expect(result.current).toBe(false);
+ });
+
+ it('should return false when subscriptionLicense is undefined and subsidy requests are not enabled', () => {
+ useSubscriptions.mockReturnValue({
+ data: {
+ subscriptionLicense: undefined,
+ },
+ });
+ useBrowseAndRequestConfiguration.mockReturnValue({
+ data: {
+ subsidyRequestsEnabled: false,
+ subsidyType: SUBSIDY_TYPE.LICENSE,
+ },
+ });
+
+ const { result } = renderHook(() => useHasValidLicenseOrSubscriptionRequestsEnabled());
+ expect(result.current).toBe(false);
+ });
+});
diff --git a/src/components/microlearning/VideoDetailPage.jsx b/src/components/microlearning/VideoDetailPage.jsx
index 11399ef67..6c02bc11c 100644
--- a/src/components/microlearning/VideoDetailPage.jsx
+++ b/src/components/microlearning/VideoDetailPage.jsx
@@ -10,7 +10,7 @@ import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import { Person, Speed, Timelapse } from '@openedx/paragon/icons';
import { Link } from 'react-router-dom';
import {
- useEnterpriseCustomer, useSubscriptions, useVideoCourseMetadata, useVideoDetails,
+ useEnterpriseCustomer, useHasValidLicenseOrSubscriptionRequestsEnabled, useVideoCourseMetadata, useVideoDetails,
} from '../app/data';
import './styles/VideoDetailPage.scss';
import DelayedFallbackContainer from '../DelayedFallback/DelayedFallbackContainer';
@@ -19,7 +19,6 @@ import { getContentPriceDisplay, getCoursePrice, useCoursePacingType } from '../
import VideoCourseReview from './VideoCourseReview';
import { hasTruthyValue, isDefinedAndNotNull } from '../../utils/common';
import { getLevelType } from './data/utils';
-import { hasActivatedAndCurrentSubscription } from '../search/utils';
import { features } from '../../config';
import VideoFeedbackCard from './VideoFeedbackCard';
@@ -38,7 +37,7 @@ const VideoDetailPage = () => {
const { data: courseMetadata } = useVideoCourseMetadata(videoData?.courseKey);
const coursePrice = getCoursePrice(courseMetadata);
const [pacingType, pacingTypeContent] = useCoursePacingType(courseMetadata?.activeCourseRun);
- const { data: { subscriptionLicense } } = useSubscriptions();
+ const hasValidLicenseOrSubRequest = useHasValidLicenseOrSubscriptionRequestsEnabled();
const playerRef = useRef(null);
const intl = useIntl();
@@ -49,7 +48,7 @@ const VideoDetailPage = () => {
};
const enableVideos = (
features.FEATURE_ENABLE_VIDEO_CATALOG
- && hasActivatedAndCurrentSubscription(subscriptionLicense, enterpriseCustomer.enableBrowseAndRequest)
+ && hasValidLicenseOrSubRequest
);
useEffect(() => {
diff --git a/src/components/microlearning/tests/VideoDetailPage.test.jsx b/src/components/microlearning/tests/VideoDetailPage.test.jsx
index d88fd3ee0..514d44b2e 100644
--- a/src/components/microlearning/tests/VideoDetailPage.test.jsx
+++ b/src/components/microlearning/tests/VideoDetailPage.test.jsx
@@ -15,6 +15,7 @@ import {
useVideoCourseMetadata,
useVideoCourseReviews,
useVideoDetails,
+ useHasValidLicenseOrSubscriptionRequestsEnabled,
} from '../../app/data';
import { COURSE_PACING_MAP } from '../../course/data';
import { LICENSE_STATUS } from '../../enterprise-user-subsidy/data/constants';
@@ -54,6 +55,7 @@ jest.mock('../../app/data', () => ({
useVideoCourseMetadata: jest.fn(() => ({ data: { courseKey: 'test-course-key' } })),
useVideoCourseReviews: jest.fn(() => ({ data: { courseKey: 'test-course-key' } })),
useSubscriptions: jest.fn(),
+ useHasValidLicenseOrSubscriptionRequestsEnabled: jest.fn(),
}));
jest.mock('react-router-dom', () => ({
@@ -140,6 +142,7 @@ describe('VideoDetailPage', () => {
},
});
features.FEATURE_ENABLE_VIDEO_CATALOG = true;
+ useHasValidLicenseOrSubscriptionRequestsEnabled.mockReturnValue(true);
});
it('Renders video details when data is available', () => {
@@ -197,17 +200,7 @@ describe('VideoDetailPage', () => {
expect(screen.getByTestId('not-found-page')).toBeInTheDocument();
});
it('renders a not found page when user do not have active subscription', () => {
- useSubscriptions.mockReturnValue({
- data: {
- subscriptionLicense: {
- status: LICENSE_STATUS.ACTIVATED,
- subscriptionPlan: {
- enterpriseCatalogUuid: 'test-catalog-uuid',
- isCurrent: false,
- },
- },
- },
- });
+ useHasValidLicenseOrSubscriptionRequestsEnabled.mockReturnValue(false);
renderWithRouter();
expect(screen.getByTestId('not-found-page')).toBeInTheDocument();
});
diff --git a/src/components/search/Search.jsx b/src/components/search/Search.jsx
index 923674d19..980a392da 100644
--- a/src/components/search/Search.jsx
+++ b/src/components/search/Search.jsx
@@ -24,13 +24,12 @@ import {
useDefaultSearchFilters,
useEnterpriseCustomer,
useEnterpriseOffers,
+ useHasValidLicenseOrSubscriptionRequestsEnabled,
useIsAssignmentsOnlyLearner,
- useSubscriptions,
} from '../app/data';
import { useAlgoliaSearch } from '../../utils/hooks';
import ContentTypeSearchResultsContainer from './ContentTypeSearchResultsContainer';
import SearchVideo from './SearchVideo';
-import { hasActivatedAndCurrentSubscription } from './utils';
import VideoBanner from '../microlearning/VideoBanner';
import CustomSubscriptionExpirationModal from '../custom-expired-subscription-modal';
@@ -54,6 +53,7 @@ function useSearchPathwayModal() {
const Search = () => {
const config = getConfig();
const { data: enterpriseCustomer } = useEnterpriseCustomer();
+ const hasValidLicenseOrSubRequest = useHasValidLicenseOrSubscriptionRequestsEnabled();
const intl = useIntl();
const navigate = useNavigate();
@@ -79,11 +79,10 @@ const Search = () => {
closePathwayModal,
} = useSearchPathwayModal();
- const { data: { subscriptionLicense } } = useSubscriptions();
const enableVideos = (
canOnlyViewHighlightSets === false
&& features.FEATURE_ENABLE_VIDEO_CATALOG
- && hasActivatedAndCurrentSubscription(subscriptionLicense, enterpriseCustomer.enableBrowseAndRequest)
+ && hasValidLicenseOrSubRequest
);
const PAGE_TITLE = intl.formatMessage({
diff --git a/src/components/search/SearchPage.jsx b/src/components/search/SearchPage.jsx
index 2f7b58bf4..1b88a680e 100644
--- a/src/components/search/SearchPage.jsx
+++ b/src/components/search/SearchPage.jsx
@@ -1,20 +1,19 @@
import { SearchData } from '@edx/frontend-enterprise-catalog-search';
import { useIntl } from '@edx/frontend-platform/i18n';
-import { useEnterpriseCustomer, useSubscriptions } from '../app/data';
import Search from './Search';
import { SEARCH_TRACKING_NAME } from './constants';
-import { getSearchFacetFilters, hasActivatedAndCurrentSubscription } from './utils';
+import { getSearchFacetFilters } from './utils';
import { features } from '../../config';
+import { useHasValidLicenseOrSubscriptionRequestsEnabled } from '../app/data';
const SearchPage = () => {
- const { data: enterpriseCustomer } = useEnterpriseCustomer();
- const intl = useIntl();
+ const hasValidLicenseOrSubRequest = useHasValidLicenseOrSubscriptionRequestsEnabled();
- const { data: { subscriptionLicense } } = useSubscriptions();
+ const intl = useIntl();
const enableVideos = (
features.FEATURE_ENABLE_VIDEO_CATALOG
- && hasActivatedAndCurrentSubscription(subscriptionLicense, enterpriseCustomer.enableBrowseAndRequest)
+ && hasValidLicenseOrSubRequest
);
return (
diff --git a/src/components/search/tests/Search.test.jsx b/src/components/search/tests/Search.test.jsx
index 094b7996a..e44f5eb8b 100644
--- a/src/components/search/tests/Search.test.jsx
+++ b/src/components/search/tests/Search.test.jsx
@@ -7,7 +7,7 @@ import '../../skills-quiz/__mocks__/react-instantsearch-dom';
import { queryClient, renderWithRouter } from '../../../utils/tests';
import '@testing-library/jest-dom';
import Search from '../Search';
-import { useDefaultSearchFilters, useEnterpriseCustomer } from '../../app/data';
+import { useDefaultSearchFilters, useEnterpriseCustomer, useHasValidLicenseOrSubscriptionRequestsEnabled } from '../../app/data';
import { useAlgoliaSearch } from '../../../utils/hooks';
import { enterpriseCustomerFactory } from '../../app/data/services/data/__factories__';
import { features } from '../../../config';
@@ -31,6 +31,7 @@ jest.mock('../../app/data', () => ({
useCanOnlyViewHighlights: jest.fn(() => ({ data: false })),
useIsAssignmentsOnlyLearner: jest.fn().mockReturnValue(false),
useDefaultSearchFilters: jest.fn(),
+ useHasValidLicenseOrSubscriptionRequestsEnabled: jest.fn(),
}));
jest.mock('../../../utils/hooks', () => ({
...jest.requireActual('../../../utils/hooks'),
@@ -75,6 +76,7 @@ describe('', () => {
jest.clearAllMocks();
useEnterpriseCustomer.mockReturnValue({ data: mockEnterpriseCustomer });
useDefaultSearchFilters.mockReturnValue(mockFilter);
+ useHasValidLicenseOrSubscriptionRequestsEnabled.mockReturnValue(true);
useAlgoliaSearch.mockReturnValue([{ search: jest.fn(), appId: 'test-app-id' }, { indexName: 'mock-index-name' }]);
});
test('renders the video beta banner component', () => {
diff --git a/src/components/search/tests/SearchPage.test.jsx b/src/components/search/tests/SearchPage.test.jsx
index d2e2336d7..e6303aff2 100644
--- a/src/components/search/tests/SearchPage.test.jsx
+++ b/src/components/search/tests/SearchPage.test.jsx
@@ -2,7 +2,7 @@ import { screen } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import { AppContext } from '@edx/frontend-platform/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
-import { useEnterpriseCustomer, useSubscriptions } from '../../app/data';
+import { useEnterpriseCustomer, useHasValidLicenseOrSubscriptionRequestsEnabled, useSubscriptions } from '../../app/data';
import { LICENSE_STATUS } from '../../enterprise-user-subsidy/data/constants';
import SearchPage from '../SearchPage';
import { features } from '../../../config';
@@ -12,11 +12,11 @@ import { enterpriseCustomerFactory } from '../../app/data/services/data/__factor
jest.mock('../../app/data', () => ({
useSubscriptions: jest.fn(),
useEnterpriseCustomer: jest.fn(),
+ useHasValidLicenseOrSubscriptionRequestsEnabled: jest.fn(),
}));
jest.mock('../utils', () => ({
getSearchFacetFilters: jest.fn().mockReturnValue([]),
- hasActivatedAndCurrentSubscription: jest.fn().mockReturnValue(true),
}));
jest.mock('../Search', () => function Search() {
@@ -40,6 +40,7 @@ describe('SearchPage', () => {
jest.clearAllMocks();
features.FEATURE_ENABLE_VIDEO_CATALOG = true;
useEnterpriseCustomer.mockReturnValue({ data: mockEnterpriseCustomer });
+ useHasValidLicenseOrSubscriptionRequestsEnabled.mockReturnValue(true);
});
it('renders SearchPage component', () => {
diff --git a/src/components/search/tests/SearchSections.test.jsx b/src/components/search/tests/SearchSections.test.jsx
index 18a556072..d4557887d 100644
--- a/src/components/search/tests/SearchSections.test.jsx
+++ b/src/components/search/tests/SearchSections.test.jsx
@@ -10,7 +10,9 @@ import '@testing-library/jest-dom';
import SearchProgram from '../SearchProgram';
import SearchPathway from '../SearchPathway';
import Search from '../Search';
-import { useDefaultSearchFilters, useEnterpriseCustomer } from '../../app/data';
+import {
+ useDefaultSearchFilters, useEnterpriseCustomer, useHasValidLicenseOrSubscriptionRequestsEnabled,
+} from '../../app/data';
import { useAlgoliaSearch } from '../../../utils/hooks';
import { enterpriseCustomerFactory } from '../../app/data/services/data/__factories__';
import SearchVideo from '../SearchVideo';
@@ -28,6 +30,7 @@ jest.mock('../../app/data', () => ({
useIsAssignmentsOnlyLearner: jest.fn().mockReturnValue(false),
useEnterpriseFeatures: jest.fn().mockReturnValue({ data: undefined }),
useDefaultSearchFilters: jest.fn(),
+ useHasValidLicenseOrSubscriptionRequestsEnabled: jest.fn(),
}));
jest.mock('../../../utils/hooks', () => ({
@@ -85,6 +88,7 @@ describe('', () => {
jest.clearAllMocks();
useEnterpriseCustomer.mockReturnValue({ data: mockEnterpriseCustomer });
useDefaultSearchFilters.mockReturnValue(mockFilter);
+ useHasValidLicenseOrSubscriptionRequestsEnabled.mockReturnValue(true);
useAlgoliaSearch.mockReturnValue([{ search: jest.fn(), appId: 'test-app-id' }, { indexName: 'mock-index-name' }]);
});
diff --git a/src/components/search/tests/utils.test.js b/src/components/search/tests/utils.test.js
index 6c9a3b4ab..b0bb13010 100644
--- a/src/components/search/tests/utils.test.js
+++ b/src/components/search/tests/utils.test.js
@@ -1,5 +1,4 @@
-import { getSearchFacetFilters, hasActivatedAndCurrentSubscription } from '../utils';
-import { LICENSE_STATUS } from '../../enterprise-user-subsidy/data/constants';
+import { getSearchFacetFilters } from '../utils';
jest.mock('../../../config', () => ({
features: { PROGRAM_TYPE_FACET: true },
@@ -15,42 +14,3 @@ describe('getSearchFacetFilters', () => {
expect(result.find(item => item.attribute === 'program_type')).toBeDefined();
});
});
-
-describe('hasActivatedAndCurrentSubscription', () => {
- it('should return true when the subscription is activated and current', () => {
- const subscriptionLicense = {
- status: LICENSE_STATUS.ACTIVATED,
- subscriptionPlan: {
- isCurrent: true,
- },
- };
- const enableBrowseAndRequest = false;
-
- const result = hasActivatedAndCurrentSubscription(subscriptionLicense, enableBrowseAndRequest);
- expect(result).toBe(true);
- });
-
- it('should return false when the subscription is not activated and not current', () => {
- const subscriptionLicense = {
- status: LICENSE_STATUS.REVOKED,
- subscriptionPlan: {
- isCurrent: false,
- },
- };
- const enableBrowseAndRequest = false;
-
- const result = hasActivatedAndCurrentSubscription(subscriptionLicense, enableBrowseAndRequest);
- expect(result).toBe(false);
- });
-
- it('should return false when subscriptionLicense is undefined', () => {
- const enableBrowseAndRequest = false;
- const result = hasActivatedAndCurrentSubscription(undefined, enableBrowseAndRequest);
- expect(result).toBe(false);
- });
- it('should return true when enableBrowseAndRequest is true', () => {
- const enableBrowseAndRequest = true;
- const result = hasActivatedAndCurrentSubscription(undefined, enableBrowseAndRequest);
- expect(result).toBe(true);
- });
-});
diff --git a/src/components/search/utils.js b/src/components/search/utils.js
index d41fde3ab..b7015bf9d 100644
--- a/src/components/search/utils.js
+++ b/src/components/search/utils.js
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
import { getSearchFacetFilters as getBaseSearchFacetFilters } from '@edx/frontend-enterprise-catalog-search';
import { features } from '../../config';
-import { LICENSE_STATUS } from '../enterprise-user-subsidy/data/constants';
export function isShortCourse(course) {
return course.course_length === 'short';
@@ -59,11 +58,3 @@ export function getSearchFacetFilters(intl) {
return searchFilters;
}
-
-export const hasActivatedAndCurrentSubscription = (
- subscriptionLicense,
- enableBrowseAndRequest,
-) => (
- (subscriptionLicense?.status === LICENSE_STATUS.ACTIVATED
- && subscriptionLicense?.subscriptionPlan?.isCurrent) || enableBrowseAndRequest
-);