Skip to content

Commit

Permalink
fix: display onboarding expired after expiration (#997)
Browse files Browse the repository at this point in the history
Currently expiring soon is displayed 28 days before expiration
and forever afterwards. Adds an actual expired state for after.

Also clarifies the expring soon message which assumed other course,
that was not necessarily true.

Also updates the take action lines when you do not have valid
onboarding to make sure they appear for everything not currently valid
or in process, and updates the submitted process lines to not appear
for expired statuses.
  • Loading branch information
ashultz0 authored Nov 3, 2022
1 parent df91fef commit 19d06d6
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 10 deletions.
34 changes: 33 additions & 1 deletion src/course-home/outline-tab/OutlineTab.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -1017,6 +1017,22 @@ describe('Outline Tab', () => {
});

it('displays expiration warning', async () => {
const expirationDate = new Date();
// This message will render if the expiration date is within 28 days; set the date 10 days in future
expirationDate.setTime(expirationDate.getTime() + 864800000);
axiosMock.onGet(proctoringInfoUrl).reply(200, {
onboarding_status: 'verified',
onboarding_link: 'test',
expiration_date: expirationDate.toString(),
onboarding_release_date: onboardingReleaseDate.toISOString(),
});
await fetchAndRender();
await screen.findByText('This course contains proctored exams');
expect(screen.queryByText('Your onboarding profile has been approved. However, your onboarding status is expiring soon. Please complete onboarding again to ensure that you will be able to continue taking proctored exams.')).toBeInTheDocument();
expect(screen.queryByText('Onboarding profile review can take 2+ business days.')).toBeInTheDocument();
});

it('displays expiration warning for other course', async () => {
const expirationDate = new Date();
// This message will render if the expiration date is within 28 days; set the date 10 days in future
expirationDate.setTime(expirationDate.getTime() + 864800000);
Expand All @@ -1028,7 +1044,23 @@ describe('Outline Tab', () => {
});
await fetchAndRender();
await screen.findByText('This course contains proctored exams');
expect(screen.queryByText('Your onboarding profile has been approved in another course. However, your onboarding status is expiring soon. Please complete onboarding again to ensure that you will be able to continue taking proctored exams.')).toBeInTheDocument();
expect(screen.queryByText('Your onboarding profile has been approved. However, your onboarding status is expiring soon. Please complete onboarding again to ensure that you will be able to continue taking proctored exams.')).toBeInTheDocument();
expect(screen.queryByText('Onboarding profile review can take 2+ business days.')).toBeInTheDocument();
});

it('displays expired', async () => {
const expirationDate = new Date();
// This message appears after expiration, set the date 10 days in the past
expirationDate.setTime(expirationDate.getTime() - 864800000);
axiosMock.onGet(proctoringInfoUrl).reply(200, {
onboarding_status: 'verified',
onboarding_link: 'test',
expiration_date: expirationDate.toString(),
onboarding_release_date: onboardingReleaseDate.toISOString(),
});
await fetchAndRender();
await screen.findByText('This course contains proctored exams');
expect(screen.queryByText('Your onboarding status has expired. Please complete onboarding again to continue taking proctored exams.')).toBeInTheDocument();
expect(screen.queryByText('Onboarding profile review can take 2+ business days.')).toBeInTheDocument();
});

Expand Down
12 changes: 11 additions & 1 deletion src/course-home/outline-tab/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,11 @@ const messages = defineMessages({
defaultMessage: 'Expiring Soon',
description: 'A label to indicate that proctortrack onboarding exam will expire soon',
},
expiredProctoringStatus: {
id: 'learning.proctoringPanel.status.expired',
defaultMessage: 'Expired',
description: 'A label to indicate that proctortrack onboarding exam has expired',
},
proctoringCurrentStatus: {
id: 'learning.proctoringPanel.status',
defaultMessage: 'Current Onboarding Status:',
Expand Down Expand Up @@ -278,9 +283,14 @@ const messages = defineMessages({
},
expiringSoonProctoringMessage: {
id: 'learning.proctoringPanel.message.expiringSoon',
defaultMessage: 'Your onboarding profile has been approved in another course. However, your onboarding status is expiring soon. Please complete onboarding again to ensure that you will be able to continue taking proctored exams.',
defaultMessage: 'Your onboarding profile has been approved. However, your onboarding status is expiring soon. Please complete onboarding again to ensure that you will be able to continue taking proctored exams.',
description: 'The text that recommend an action when the status of the proctortrack onboarding exam is (expiring soon)',
},
expiredProctoringMessage: {
id: 'learning.proctoringPanel.message.expired',
defaultMessage: 'Your onboarding status has expired. Please complete onboarding again to continue taking proctored exams.',
description: 'The text that recommend an action when the status of the proctortrack onboarding exam is (expired)',
},
proctoringPanelGeneralInfo: {
id: 'learning.proctoringPanel.generalInfo',
defaultMessage: 'You must complete the onboarding process prior to taking any proctored exam. ',
Expand Down
32 changes: 24 additions & 8 deletions src/course-home/outline-tab/widgets/ProctoringInfoPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ function ProctoringInfoPanel({ intl }) {
error: 'error',
otherCourseApproved: 'otherCourseApproved',
expiringSoon: 'expiringSoon',
expired: 'expired',
};

function getReadableStatusClass(examStatus) {
Expand All @@ -54,9 +55,14 @@ function ProctoringInfoPanel({ intl }) {
return readableClass;
}

function isNotYetSubmitted(examStatus) {
const NO_SHOW_STATES = ['submitted', 'second_review_required', 'verified'];
return !NO_SHOW_STATES.includes(examStatus);
function isCurrentlySubmitted(examStatus) {
const SUBMITTED_STATES = ['submitted', 'second_review_required'];
return SUBMITTED_STATES.includes(examStatus);
}

function isSubmissionRequired(examStatus) {
const OK_STATES = [readableStatuses.submitted, readableStatuses.verified];
return !OK_STATES.includes(examStatus);
}

function isNotYetReleased(examReleaseDate) {
Expand All @@ -77,11 +83,19 @@ function ProctoringInfoPanel({ intl }) {
return borderClass;
}

function isExpired(dateString) {
// Returns true if the expiration date has passed
const today = new Date();
const expirationDateObject = new Date(dateString);
return today >= expirationDateObject.getTime();
}

function isExpiringSoon(dateString) {
// Returns true if the expiration date is within 28 days
const twentyeightDays = 28 * 24 * 60 * 60 * 1000;
const today = new Date();
const expirationDateObject = new Date(dateString);
return today > expirationDateObject.getTime() - 2419200000;
return today > expirationDateObject.getTime() - twentyeightDays;
}

useEffect(() => {
Expand All @@ -96,7 +110,9 @@ function ProctoringInfoPanel({ intl }) {
setStatus(response.onboarding_status);
setLink(response.onboarding_link);
const expirationDate = response.expiration_date;
if (expirationDate && isExpiringSoon(expirationDate)) {
if (expirationDate && isExpired(expirationDate)) {
setReadableStatus(getReadableStatusClass('expired'));
} else if (expirationDate && isExpiringSoon(expirationDate)) {
setReadableStatus(getReadableStatusClass('expiringSoon'));
} else {
setReadableStatus(getReadableStatusClass(response.onboarding_status));
Expand Down Expand Up @@ -175,17 +191,17 @@ function ProctoringInfoPanel({ intl }) {
{![readableStatuses.verified, readableStatuses.otherCourseApproved].includes(readableStatus) && (
<>
<p>
{isNotYetSubmitted(status) && (
{!isCurrentlySubmitted(status) && (
intl.formatMessage(messages.proctoringPanelGeneralInfo)
)}
{!isNotYetSubmitted(status) && (
{isCurrentlySubmitted(status) && (
intl.formatMessage(messages.proctoringPanelGeneralInfoSubmitted)
)}
</p>
<p>{intl.formatMessage(messages.proctoringPanelGeneralTime)}</p>
</>
)}
{isNotYetSubmitted(status) && (
{isSubmissionRequired(readableStatus) && (
onboardingExamButton
)}
<Button variant="outline-primary" block href="https://support.edx.org/hc/en-us/sections/115004169247-Taking-Timed-and-Proctored-Exams">
Expand Down

0 comments on commit 19d06d6

Please sign in to comment.