Skip to content

Commit

Permalink
feat: Add redirect to enterprise learner dashboard (#1251)
Browse files Browse the repository at this point in the history
When a learner tries to load the B2C course page for a course that
starts in the future (error_code="course_not_started"), normally the
learning MFE automatically redirects to the B2C dashboard.  This change
supports an alternate error_code "course_not_started_enterprise_learner"
to trigger an alternative redirect to the B2B (enterprise) learner
dashboard.

This does two main things:

1. When the course metadata API response indicates
   course_access.error_code = "course_not_started_enterprise_learner"
   then redirect to "/redirect/enterprise-learner-dashboard".
2. When the top-level router matches path "/redirect/enterprise-learner-dashboard"
   then redirec to to the value of config `ENTERPRISE_LEARNER_PORTAL_URL`.

ENT-8078
  • Loading branch information
pwnage101 authored Dec 15, 2023
1 parent 2bf326f commit 7957533
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 5 deletions.
4 changes: 4 additions & 0 deletions global-setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Force all tests to run in UTC to prevent tests from being sensitive to host timezone.
module.exports = async () => {
process.env.TZ = 'UTC';
};
3 changes: 2 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ module.exports = createConfig('jest', {
'react-markdown': '<rootDir>/node_modules/react-markdown/react-markdown.min.js',
},
testTimeout: 30000,
testEnvironment: 'jsdom'
testEnvironment: 'jsdom',
globalSetup: "./global-setup.js"
});
2 changes: 2 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ export const ROUTES = {
UNSUBSCRIBE: '/goal-unsubscribe/:token',
REDIRECT: '/redirect/*',
DASHBOARD: 'dashboard',
ENTERPRISE_LEARNER_DASHBOARD: 'enterprise-learner-dashboard',
CONSENT: 'consent',
};

export const REDIRECT_MODES = {
DASHBOARD_REDIRECT: 'dashboard-redirect',
ENTERPRISE_LEARNER_DASHBOARD_REDIRECT: 'enterprise-learner-dashboard-redirect',
CONSENT_REDIRECT: 'consent-redirect',
HOME_REDIRECT: 'home-redirect',
SURVEY_REDIRECT: 'survey-redirect',
Expand Down
7 changes: 7 additions & 0 deletions src/courseware/CoursewareContainer.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -515,5 +515,12 @@ describe('CoursewareContainer', () => {
const startDate = '2/5/2013'; // This date is based on our courseMetadata factory's sample data.
expect(global.location.href).toEqual(`http://localhost/redirect/dashboard?notlive=${startDate}`);
});

it('should go to the enterprise learner dashboard for a course_not_started_enterprise_learner error code', async () => {
setUpWithDeniedStatus('course_not_started_enterprise_learner');
await loadContainer();

expect(global.location.href).toEqual('http://localhost/redirect/enterprise-learner-dashboard');
});
});
});
4 changes: 4 additions & 0 deletions src/courseware/CoursewareRedirectLandingPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ const CoursewareRedirectLandingPage = () => (
path={ROUTES.DASHBOARD}
element={<PageWrap><RedirectPage pattern="/dashboard" mode={REDIRECT_MODES.DASHBOARD_REDIRECT} /></PageWrap>}
/>
<Route
path={ROUTES.ENTERPRISE_LEARNER_DASHBOARD}
element={<PageWrap><RedirectPage mode={REDIRECT_MODES.ENTERPRISE_LEARNER_DASHBOARD_REDIRECT} /></PageWrap>}
/>
<Route
path={ROUTES.CONSENT}
element={<PageWrap><RedirectPage mode={REDIRECT_MODES.CONSENT_REDIRECT} /></PageWrap>}
Expand Down
14 changes: 14 additions & 0 deletions src/courseware/CoursewareRedirectLandingPage.test.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { MemoryRouter as Router } from 'react-router-dom';
import { mergeConfig } from '@edx/frontend-platform';
import { render, initializeMockApp } from '../setupTest';
import CoursewareRedirectLandingPage from './CoursewareRedirectLandingPage';

Expand All @@ -11,6 +12,9 @@ jest.mock('../decode-page-route', () => jest.fn(({ children }) => <div>{children
describe('CoursewareRedirectLandingPage', () => {
beforeEach(async () => {
await initializeMockApp();
mergeConfig({
ENTERPRISE_LEARNER_PORTAL_URL: 'http://localhost:8734',
}, 'Add configs for URLs');
delete global.location;
global.location = { assign: redirectUrl };
});
Expand All @@ -34,4 +38,14 @@ describe('CoursewareRedirectLandingPage', () => {

expect(redirectUrl).toHaveBeenCalledWith('/course/course-v1:edX+DemoX+Demo_Course/home');
});

it('Redirects to correct enterprise dashboard URL', () => {
render(
<Router initialEntries={['/enterprise-learner-dashboard']}>
<CoursewareRedirectLandingPage />
</Router>,
);

expect(redirectUrl).toHaveBeenCalledWith('http://localhost:8734');
});
});
14 changes: 10 additions & 4 deletions src/courseware/RedirectPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,26 @@ const RedirectPage = ({
const location = useLocation();
const { consentPath } = queryString.parse(location?.search);

const BASE_URL = getConfig().LMS_BASE_URL;
const {
LMS_BASE_URL,
ENTERPRISE_LEARNER_PORTAL_URL,
} = getConfig();

switch (mode) {
case REDIRECT_MODES.DASHBOARD_REDIRECT:
global.location.assign(`${BASE_URL}${pattern}${location?.search}`);
global.location.assign(`${LMS_BASE_URL}${pattern}${location?.search}`);
break;
case REDIRECT_MODES.ENTERPRISE_LEARNER_DASHBOARD_REDIRECT:
global.location.assign(ENTERPRISE_LEARNER_PORTAL_URL);
break;
case REDIRECT_MODES.CONSENT_REDIRECT:
global.location.assign(`${BASE_URL}${consentPath}`);
global.location.assign(`${LMS_BASE_URL}${consentPath}`);
break;
case REDIRECT_MODES.HOME_REDIRECT:
global.location.assign(generatePath(pattern, { courseId }));
break;
default:
global.location.assign(`${BASE_URL}${generatePath(pattern, { courseId })}`);
global.location.assign(`${LMS_BASE_URL}${generatePath(pattern, { courseId })}`);
}

return null;
Expand Down
3 changes: 3 additions & 0 deletions src/shared/access.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ export function getAccessDeniedRedirectUrl(courseId, activeTabSlug, courseAccess
const startDate = (new Intl.DateTimeFormat(getLocale())).format(new Date(start));
url = `/redirect/dashboard?notlive=${startDate}`;
break;
case 'course_not_started_enterprise_learner':
url = '/redirect/enterprise-learner-dashboard';
break;
case 'survey_required':
url = `/redirect/survey/${courseId}`;
break;
Expand Down

0 comments on commit 7957533

Please sign in to comment.