diff --git a/.env.development b/.env.development index 6a1b9a6504..8358ade054 100644 --- a/.env.development +++ b/.env.development @@ -59,3 +59,4 @@ AUTH0_SELF_SERVICE_INTEGRATION='true' MFE_CONFIG_API_URL='http://localhost:18000/api/mfe_config/v1' DEMO_ENTEPRISE_UUID='set a valid enterprise uuid' EDX_ACCESS_URL='' +ANALYTICS_SUPPORTED='true' diff --git a/.env.development-stage b/.env.development-stage index eb62f9c5a2..6fbdfbcb18 100644 --- a/.env.development-stage +++ b/.env.development-stage @@ -37,6 +37,7 @@ HOTJAR_APP_ID='' FEATURE_SSO_SETTINGS_TAB='true' FEATURE_API_CREDENTIALS_TAB='true' FEATURE_PENDING_ENROLLMENT_ACTIONS='false' +ANALYTICS_SUPPORTED='true' # maintenance alert IS_MAINTENANCE_ALERT_ENABLED='' MAINTENANCE_ALERT_MESSAGE='edX is currently in a brief maintenance window. Functionality involving course enrollments is unavailable at this time, including enrollment and assignment. Please check back shortly to continue the learning journey.' diff --git a/.env.test b/.env.test index b49aff98ee..a9cc415da7 100644 --- a/.env.test +++ b/.env.test @@ -17,3 +17,4 @@ ENTERPRISE_SUPPORT_REVOKE_LICENSE_URL = '' PLOTLY_SERVER_URL='http://localhost:8050' DEMO_ENTEPRISE_UUID='set a valid enterprise uuid' EDX_ACCESS_URL='https://2u-guid-staging.us.auth0.com' +ANALYTICS_SUPPORTED='true' diff --git a/src/components/EnterpriseApp/EnterpriseAppRoutes.jsx b/src/components/EnterpriseApp/EnterpriseAppRoutes.jsx index 989ab419ef..15c2a93cf8 100644 --- a/src/components/EnterpriseApp/EnterpriseAppRoutes.jsx +++ b/src/components/EnterpriseApp/EnterpriseAppRoutes.jsx @@ -1,6 +1,7 @@ import React, { useContext } from 'react'; import { Routes, Route, useParams } from 'react-router-dom'; import PropTypes from 'prop-types'; +import { features } from '../../config'; import AdminPage from '../../containers/AdminPage'; import CodeManagementPage from '../CodeManagement'; @@ -12,6 +13,7 @@ import SettingsPage from '../settings'; import { SubscriptionManagementPage } from '../subscriptions'; import { PlotlyAnalyticsPage } from '../PlotlyAnalytics'; import AnalyticsV2Page from '../AdvanceAnalyticsV2/AnalyticsV2Page'; +import FeatureNotSupportedPage from '../FeatureNotSupportedPage'; import { ROUTE_NAMES } from './data/constants'; import BulkEnrollmentResultsDownloadPage from '../BulkEnrollmentResultsDownloadPage'; import { EnterpriseSubsidiesContext } from '../EnterpriseSubsidiesContext'; @@ -38,7 +40,7 @@ const EnterpriseAppRoutes = ({ {enterpriseAppPage === ROUTE_NAMES.learners && ( } + element={features.ANALYTICS_SUPPORTED ? : } /> )} @@ -83,7 +85,7 @@ const EnterpriseAppRoutes = ({ } + element={features.ANALYTICS_SUPPORTED ? : } /> )} @@ -91,7 +93,9 @@ const EnterpriseAppRoutes = ({ } + element={features.ANALYTICS_SUPPORTED + ? + : } /> )} diff --git a/src/components/EnterpriseApp/EnterpriseAppRoutes.test.jsx b/src/components/EnterpriseApp/EnterpriseAppRoutes.test.jsx new file mode 100644 index 0000000000..d706470f45 --- /dev/null +++ b/src/components/EnterpriseApp/EnterpriseAppRoutes.test.jsx @@ -0,0 +1,77 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import '@testing-library/jest-dom/extend-expect'; +import { IntlProvider } from '@edx/frontend-platform/i18n'; +import { features } from '../../config'; +import EnterpriseAppRoutes from './EnterpriseAppRoutes'; +import { EnterpriseSubsidiesContext } from '../EnterpriseSubsidiesContext'; + +jest.mock('../AdvanceAnalyticsV2/AnalyticsV2Page', () => function AnalyticsV2PageMock() { + return
AnalyticsV2Page Mock Component
; +}); +jest.mock('../../containers/AdminPage', () => function AdminPageMock() { + return
AdminPage Mock Component
; +}); +jest.mock('../PlotlyAnalytics', () => ({ + PlotlyAnalyticsPage: () =>
PlotlyAnalyticsPage Mock Component
, +})); + +let mockEnterpriseAppPage = 'analyticsv2'; + +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + Routes: (props) => {props.children}, + Route: ({ element }) => element, + useParams: () => ({ enterpriseAppPage: mockEnterpriseAppPage }), +})); + +const mockEnterpriseSubsidiesContextValue = { + canManageLearnerCredit: true, +}; + +const renderWithProviders = (props) => render( + + + + + , +); + +describe('EnterpriseAppRoutes', () => { + const defaultProps = { + email: 'test@example.com', + enterpriseId: 'test-enterprise-id', + enterpriseName: 'Test Enterprise', + enableCodeManagementPage: false, + enableReportingPage: false, + enableSubscriptionManagementPage: false, + enableAnalyticsPage: true, + enableContentHighlightsPage: false, + }; + + it('renders FeatureNotSupportedPage when ANALYTICS_SUPPORTED is false', () => { + features.ANALYTICS_SUPPORTED = false; + renderWithProviders(defaultProps); + expect(screen.getByText('This feature is currently unavailable in this environment.')).toBeInTheDocument(); + }); + + it('renders AnalyticsV2Page when ANALYTICS_SUPPORTED is true', () => { + features.ANALYTICS_SUPPORTED = true; + renderWithProviders(defaultProps); + expect(screen.getByText('AnalyticsV2Page Mock Component')).toBeInTheDocument(); + }); + + it('renders AdminPage when ANALYTICS_SUPPORTED is true', () => { + mockEnterpriseAppPage = 'learners'; + features.ANALYTICS_SUPPORTED = true; + renderWithProviders(defaultProps); + expect(screen.getByText('AdminPage Mock Component')).toBeInTheDocument(); + }); + + it('renders Analytics when ANALYTICS_SUPPORTED is true', () => { + mockEnterpriseAppPage = 'analytics'; + features.ANALYTICS_SUPPORTED = true; + renderWithProviders(defaultProps); + expect(screen.getByText('PlotlyAnalyticsPage Mock Component')).toBeInTheDocument(); + }); +}); diff --git a/src/components/FeatureNotSupportedPage/FeatureNotSupportedPage.test.jsx b/src/components/FeatureNotSupportedPage/FeatureNotSupportedPage.test.jsx new file mode 100644 index 0000000000..a5ec470020 --- /dev/null +++ b/src/components/FeatureNotSupportedPage/FeatureNotSupportedPage.test.jsx @@ -0,0 +1,18 @@ +import React from 'react'; +import renderer from 'react-test-renderer'; +import { IntlProvider } from '@edx/frontend-platform/i18n'; + +import FeatureNotSupportedPage from './index'; + +describe('', () => { + it('renders correctly', () => { + const tree = renderer + .create(( + + + + )) + .toJSON(); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/src/components/FeatureNotSupportedPage/__snapshots__/FeatureNotSupportedPage.test.jsx.snap b/src/components/FeatureNotSupportedPage/__snapshots__/FeatureNotSupportedPage.test.jsx.snap new file mode 100644 index 0000000000..1639b16a6d --- /dev/null +++ b/src/components/FeatureNotSupportedPage/__snapshots__/FeatureNotSupportedPage.test.jsx.snap @@ -0,0 +1,54 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` renders correctly 1`] = ` +
+
+
+
+ + + + + +
+
+ This feature is currently unavailable in this environment. +
+
+
+
+
+
+`; diff --git a/src/components/FeatureNotSupportedPage/index.jsx b/src/components/FeatureNotSupportedPage/index.jsx new file mode 100644 index 0000000000..3b4bb31fe8 --- /dev/null +++ b/src/components/FeatureNotSupportedPage/index.jsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { Helmet } from 'react-helmet'; +import { FormattedMessage } from '@edx/frontend-platform/i18n'; +import { + Alert, +} from '@openedx/paragon'; +import { + Info, +} from '@openedx/paragon/icons'; + +export const FeatureNotSupported = () => ( + <> + + Feature not supported + +
+ + + +
+ +); + +const FeatureNotSupportedPage = () => ( +
+
+ +
+
+); + +export default FeatureNotSupportedPage; diff --git a/src/config/index.js b/src/config/index.js index 70c4c55c6a..cc3b930b95 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -45,6 +45,7 @@ const features = { REPORTING_CONFIGURATIONS: process.env.FEATURE_REPORTING_CONFIGURATIONS || hasFeatureFlagEnabled('REPORTING_CONFIGURATIONS'), ANALYTICS: process.env.FEATURE_ANALYTICS || hasFeatureFlagEnabled('ANALYTICS'), ANALYTICS_V2: process.env.FEATURE_ANALYTICS_V2 || hasFeatureFlagEnabled('ANALYTICS_V2'), + ANALYTICS_SUPPORTED: process.env.ANALYTICS_SUPPORTED || hasFeatureFlagEnabled('ANALYTICS_SUPPORTED'), SAML_CONFIGURATION: process.env.FEATURE_SAML_CONFIGURATION || hasFeatureFlagEnabled('SAML_CONFIGURATION'), SUPPORT: process.env.FEATURE_SUPPORT || hasFeatureFlagEnabled('SUPPORT'), EXTERNAL_LMS_CONFIGURATION: process.env.FEATURE_EXTERNAL_LMS_CONFIGURATION || hasFeatureFlagEnabled('EXTERNAL_LMS_CONFIGURATION'),