Translation Support (#25)
This commit is contained in:
@@ -6,7 +6,13 @@ import {
|
||||
Alert, Button, Form, Spinner,
|
||||
} from '@edx/paragon';
|
||||
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
|
||||
import {
|
||||
injectIntl,
|
||||
intlShape,
|
||||
FormattedMessage,
|
||||
} from '@edx/frontend-platform/i18n';
|
||||
|
||||
import messages from './ProctoredExamSettings.messages';
|
||||
import StudioApiService from '../data/services/StudioApiService';
|
||||
|
||||
function ExamSettings(props) {
|
||||
@@ -102,7 +108,7 @@ function ExamSettings(props) {
|
||||
function onButtonClick() {
|
||||
if (proctoringProvider === 'proctortrack' && !EmailValidator.validate(proctortrackEscalationEmail)) {
|
||||
if (proctortrackEscalationEmail === '') {
|
||||
const errorMessage = 'The Proctortrack Escalation Email field cannot be empty if proctortrack is the selected provider.';
|
||||
const errorMessage = props.intl.formatMessage(messages['authoring.examsettings.escalationemail.error.blank']);
|
||||
|
||||
setFormStatus({
|
||||
isValid: false,
|
||||
@@ -114,7 +120,7 @@ function ExamSettings(props) {
|
||||
},
|
||||
});
|
||||
} else {
|
||||
const errorMessage = 'The Proctortrack Escalation Email field is in the wrong format and is not valid.';
|
||||
const errorMessage = props.intl.formatMessage(messages['authoring.examsettings.escalationemail.error.invalid']);
|
||||
|
||||
setFormStatus({
|
||||
isValid: false,
|
||||
@@ -169,10 +175,11 @@ function ExamSettings(props) {
|
||||
function getFormErrorMessage() {
|
||||
const numOfErrors = Object.keys(formStatus.errors).length;
|
||||
const errors = Object.entries(formStatus.errors).map(([id, error]) => <li key={id}>{error.dialogErrorMessage}</li>);
|
||||
const messageId = numOfErrors > 1 ? 'authoring.examsettings.error.multiple' : 'authoring.examsettings.error.single';
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>{numOfErrors > 1 ? `There are ${numOfErrors} errors in this form.` : 'There is 1 error in this form.'}</div>
|
||||
<div>{props.intl.formatMessage(messages[messageId], { numOfErrors })}</div>
|
||||
<ul>
|
||||
{errors}
|
||||
</ul>
|
||||
@@ -201,14 +208,18 @@ function ExamSettings(props) {
|
||||
<Form.Check
|
||||
type="checkbox"
|
||||
id="enableProctoredExams"
|
||||
label="Enable Proctored Exams"
|
||||
label={props.intl.formatMessage(messages['authoring.examsettings.enableproctoredexams.label'])}
|
||||
aria-describedby="enableProctoredExamsHelpText"
|
||||
onChange={onEnableProctoredExamsChange}
|
||||
checked={enableProctoredExams}
|
||||
inline
|
||||
/>
|
||||
<Form.Text id="enableProctoredExamsHelpText">
|
||||
If checked, proctored exams are enabled in your course.
|
||||
<FormattedMessage
|
||||
id="authoring.examsettings.enableproctoredexams.help"
|
||||
defaultMessage="If checked, proctored exams are enabled in your course."
|
||||
description="Help text for checkbox to enable proctored exams."
|
||||
/>
|
||||
</Form.Text>
|
||||
</Form.Group>
|
||||
|
||||
@@ -216,12 +227,18 @@ function ExamSettings(props) {
|
||||
{ isEdxStaff && enableProctoredExams && (
|
||||
<fieldset aria-describedby="allowOptingOutHelpText">
|
||||
<Form.Group controlId="formAllowingOptingOut">
|
||||
<Form.Label as="legend">Allow Opting Out of Proctored Exams</Form.Label>
|
||||
<Form.Label as="legend">
|
||||
<FormattedMessage
|
||||
id="authoring.examsettings.allowoptout.label"
|
||||
defaultMessage="Allow Opting Out of Proctored Exams"
|
||||
description="Label for radio selection allowing proctored exam opt out"
|
||||
/>
|
||||
</Form.Label>
|
||||
<Form.Check
|
||||
type="radio"
|
||||
id="allowOptingOutYes"
|
||||
name="allowOptingOut"
|
||||
label="Yes"
|
||||
label={props.intl.formatMessage(messages['authoring.examsettings.allowoptout.yes'])}
|
||||
inline
|
||||
checked={allowOptingOut}
|
||||
onChange={() => onAllowOptingOutChange(true)}
|
||||
@@ -231,16 +248,22 @@ function ExamSettings(props) {
|
||||
type="radio"
|
||||
id="allowOptingOutNo"
|
||||
name="allowOptingOut"
|
||||
label="No"
|
||||
label={props.intl.formatMessage(messages['authoring.examsettings.allowoptout.no'])}
|
||||
inline
|
||||
checked={!allowOptingOut}
|
||||
onChange={() => onAllowOptingOutChange(false)}
|
||||
data-test-id="allowOptingOutNo"
|
||||
/>
|
||||
<Form.Text id="allowOptingOutHelpText">
|
||||
If this value is "Yes", learners can choose to take proctored exams without proctoring.
|
||||
If this value is "No", all learners must take the exam with proctoring.
|
||||
This setting only applies if proctored exams are enabled for the course.
|
||||
<FormattedMessage
|
||||
id="authoring.examsettings.allowoptout.help"
|
||||
defaultMessage={`
|
||||
If this value is "Yes", learners can choose to take proctored exams without proctoring.
|
||||
If this value is "No", all learners must take the exam with proctoring.
|
||||
This setting only applies if proctored exams are enabled for the course.
|
||||
`}
|
||||
description="Help text for proctored exam opt out radio selection"
|
||||
/>
|
||||
</Form.Text>
|
||||
</Form.Group>
|
||||
</fieldset>
|
||||
@@ -249,7 +272,13 @@ function ExamSettings(props) {
|
||||
{/* PROCTORING PROVIDER */}
|
||||
{ enableProctoredExams && (
|
||||
<Form.Group controlId="formProctoringProvider">
|
||||
<Form.Label>Proctoring Provider</Form.Label>
|
||||
<Form.Label>
|
||||
<FormattedMessage
|
||||
id="authoring.examsettings.provider.label"
|
||||
defaultMessage="Proctoring Provider"
|
||||
description="Label for proctoring provider dropdown selection"
|
||||
/>
|
||||
</Form.Label>
|
||||
<Form.Control
|
||||
as="select"
|
||||
value={proctoringProvider}
|
||||
@@ -258,14 +287,22 @@ function ExamSettings(props) {
|
||||
>
|
||||
{getProctoringProviderOptions(availableProctoringProviders)}
|
||||
</Form.Control>
|
||||
<Form.Text id="proctoringProviderHelpText">{cannotEditProctoringProvider() ? ('Proctoring provider cannot be modified after course start date.') : ('Select the proctoring provider you want to use for this course run.')}</Form.Text>
|
||||
<Form.Text id="proctoringProviderHelpText">
|
||||
{cannotEditProctoringProvider() ? props.intl.formatMessage(messages['authoring.examsettings.provider.help.aftercoursestart']) : props.intl.formatMessage(messages['authoring.examsettings.provider.help'])}
|
||||
</Form.Text>
|
||||
</Form.Group>
|
||||
)}
|
||||
|
||||
{/* PROCTORTRACK ESCALATION EMAIL */}
|
||||
{showProctortrackEscalationEmail && enableProctoredExams && (
|
||||
<Form.Group controlId="formProctortrackEscalationEmail">
|
||||
<Form.Label>Proctortrack Escalation Email</Form.Label>
|
||||
<Form.Label>
|
||||
<FormattedMessage
|
||||
id="authoring.examsettings.escalationemail.label"
|
||||
defaultMessage="Proctortrack Escalation Email"
|
||||
description="Label for escalation email text field"
|
||||
/>
|
||||
</Form.Label>
|
||||
<Form.Control
|
||||
ref={proctoringEscalationEmailInputRef}
|
||||
type="email"
|
||||
@@ -277,9 +314,14 @@ function ExamSettings(props) {
|
||||
/>
|
||||
<Form.Control.Feedback type="invalid">{formStatus.errors.formProctortrackEscalationEmail && formStatus.errors.formProctortrackEscalationEmail.inputErrorMessage} </Form.Control.Feedback>
|
||||
<Form.Text id="proctortrackEscalationEmailHelpText">
|
||||
Required if "proctortrack" is selected as your proctoring provider.
|
||||
Enter an email address to be contacted by the support team whenever there are escalations
|
||||
(e.g. appeals, delayed reviews, etc.).
|
||||
<FormattedMessage
|
||||
id="authoring.examsettings.escalationemail.help"
|
||||
defaultMessage={`
|
||||
Required if "proctortrack" is selected as your proctoring provider. Enter an email address to be
|
||||
contacted by the support team whenever there are escalations (e.g. appeals, delayed reviews, etc.).
|
||||
`}
|
||||
description="Help text explaining escalation email field."
|
||||
/>
|
||||
</Form.Text>
|
||||
</Form.Group>
|
||||
)}
|
||||
@@ -287,11 +329,17 @@ function ExamSettings(props) {
|
||||
{ isEdxStaff && enableProctoredExams && (
|
||||
<fieldset aria-describedby="createZendeskTicketsText">
|
||||
<Form.Group controlId="formCreateZendeskTickets">
|
||||
<Form.Label as="legend">Create Zendesk Tickets for Suspicious Proctored Exam Attempts</Form.Label>
|
||||
<Form.Label as="legend">
|
||||
<FormattedMessage
|
||||
id="authoring.examsettings.createzendesk.label"
|
||||
defaultMessage="Create Zendesk Tickets for Suspicious Proctored Exam Attempts"
|
||||
description="Label for Zendesk ticket creation radio select."
|
||||
/>
|
||||
</Form.Label>
|
||||
<Form.Check
|
||||
type="radio"
|
||||
id="createZendeskTicketsYes"
|
||||
label="Yes"
|
||||
label={props.intl.formatMessage(messages['authoring.examsettings.createzendesk.yes'])}
|
||||
inline
|
||||
name="createZendeskTickets"
|
||||
checked={createZendeskTickets}
|
||||
@@ -301,7 +349,7 @@ function ExamSettings(props) {
|
||||
<Form.Check
|
||||
type="radio"
|
||||
id="createZendeskTicketsNo"
|
||||
label="No"
|
||||
label={props.intl.formatMessage(messages['authoring.examsettings.createzendesk.no'])}
|
||||
inline
|
||||
name="createZendeskTickets"
|
||||
checked={!createZendeskTickets}
|
||||
@@ -309,8 +357,11 @@ function ExamSettings(props) {
|
||||
data-test-id="createZendeskTicketsNo"
|
||||
/>
|
||||
<Form.Text id="createZendeskTicketsText">
|
||||
If this value is "Yes",
|
||||
a Zendesk ticket will be created for suspicious proctored exam attempts.
|
||||
<FormattedMessage
|
||||
id="authoring.examsettings.createzendesk.help"
|
||||
defaultMessage="If this value is "Yes", a Zendesk ticket will be created for suspicious proctored exam attempts."
|
||||
description="Help text for Zendesk ticket creation radio select"
|
||||
/>
|
||||
</Form.Text>
|
||||
</Form.Group>
|
||||
</fieldset>
|
||||
@@ -321,7 +372,11 @@ function ExamSettings(props) {
|
||||
onClick={onButtonClick}
|
||||
disabled={submissionInProgress}
|
||||
>
|
||||
Submit
|
||||
<FormattedMessage
|
||||
id="authoring.examsettings.submit"
|
||||
defaultMessage="Submit"
|
||||
description="Form submit button"
|
||||
/>
|
||||
</Button> {' '}
|
||||
{submissionInProgress && <Spinner animation="border" variant="primary" data-test-id="saveInProgress" aria-label="Save in progress" />}
|
||||
</Form>
|
||||
@@ -338,7 +393,13 @@ function ExamSettings(props) {
|
||||
data-test-id="spinnerContainer"
|
||||
>
|
||||
<Spinner className animation="border" role="status" variant="primary">
|
||||
<span className="sr-only">Loading...</span>
|
||||
<span className="sr-only">
|
||||
<FormattedMessage
|
||||
id="authoring.examsettings.loading"
|
||||
defaultMessage="Loading..."
|
||||
description=""
|
||||
/>
|
||||
</span>
|
||||
</Spinner>
|
||||
</div>
|
||||
);
|
||||
@@ -347,10 +408,15 @@ function ExamSettings(props) {
|
||||
function renderConnectionError() {
|
||||
return (
|
||||
<Alert variant="danger" data-test-id="connectionError">
|
||||
We encountered a technical error when loading this page.
|
||||
This might be a temporary issue, so please try again in a few minutes.
|
||||
If the problem persists,
|
||||
please go to <Alert.Link href="https://support.edx.org/hc/en-us">edX Support Page</Alert.Link> for help.
|
||||
<FormattedMessage
|
||||
id="authoring.examsettings.alert.error.connection"
|
||||
defaultMessage={`
|
||||
We encountered a technical error when loading this page. This might be a temporary issue,
|
||||
so please try again in a few minutes. If the problem persists, please go to {support_link} for help.
|
||||
`}
|
||||
values={{ support_link: <Alert.Link href="https://support.edx.org/hc/en-us">{props.intl.formatMessage(messages['authoring.examsettings.support.text'])}</Alert.Link> }}
|
||||
description=""
|
||||
/>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
@@ -358,8 +424,13 @@ function ExamSettings(props) {
|
||||
function renderPermissionError() {
|
||||
return (
|
||||
<Alert variant="danger" data-test-id="permissionError">
|
||||
You are not authorized to view this page. If you feel you should have access,
|
||||
please reach out to your course team admin to be given access.
|
||||
<FormattedMessage
|
||||
id="authoring.examsettings.alert.error.permission"
|
||||
defaultMessage={`
|
||||
You are not authorized to view this page. If you feel you should have access,
|
||||
please reach out to your course team admin to be given access.
|
||||
`}
|
||||
/>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
@@ -373,8 +444,14 @@ function ExamSettings(props) {
|
||||
data-test-id="saveSuccess"
|
||||
onClose={() => setSaveSuccess(false)}
|
||||
>
|
||||
Proctored exam settings saved successfully.
|
||||
You can go back to your course in Studio <Alert.Link href={studioCourseRunURL}>here</Alert.Link>.
|
||||
<FormattedMessage
|
||||
id="authoring.examsettings.alert.success"
|
||||
defaultMessage={`
|
||||
Proctored exam settings saved successfully.
|
||||
You can go back to your course in Studio {studioCourseRunURL}.
|
||||
`}
|
||||
values={{ studioCourseRunURL: <Alert.Link href={studioCourseRunURL}>here</Alert.Link> }}
|
||||
/>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
@@ -387,10 +464,16 @@ function ExamSettings(props) {
|
||||
data-test-id="saveError"
|
||||
onClose={() => setSaveError(false)}
|
||||
>
|
||||
We encountered a technical error while trying to save proctored exam settings.
|
||||
This might be a temporary issue, so please try again in a few minutes.
|
||||
If the problem persists,
|
||||
please go to <Alert.Link href="https://support.edx.org/hc/en-us">edX Support Page</Alert.Link> for help.
|
||||
<FormattedMessage
|
||||
id="authoring.examsettings.alert.error"
|
||||
defaultMessage={`
|
||||
We encountered a technical error while trying to save proctored exam settings.
|
||||
This might be a temporary issue, so please try again in a few minutes.
|
||||
If the problem persists,
|
||||
please go to {support_link} for help.
|
||||
`}
|
||||
values={{ support_link: <Alert.Link href="https://support.edx.org/hc/en-us">{props.intl.formatMessage(messages['authoring.examsettings.support.text'])}</Alert.Link> }}
|
||||
/>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
@@ -459,9 +542,10 @@ function ExamSettings(props) {
|
||||
}
|
||||
|
||||
ExamSettings.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
courseId: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
ExamSettings.defaultProps = {};
|
||||
|
||||
export default ExamSettings;
|
||||
export default injectIntl(ExamSettings);
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
'authoring.examsettings.allowoptout.no': {
|
||||
id: 'authoring.examsettings.allowoptout.no',
|
||||
defaultMessage: 'No',
|
||||
description: '"No" option for yes/no radio button set',
|
||||
},
|
||||
'authoring.examsettings.allowoptout.yes': {
|
||||
id: 'authoring.examsettings.allowoptout.yes',
|
||||
defaultMessage: 'Yes',
|
||||
description: '"Yes" option for yes/no radio button set',
|
||||
},
|
||||
'authoring.examsettings.createzendesk.no': {
|
||||
id: 'authoring.examsettings.createzendesk.no',
|
||||
defaultMessage: 'No',
|
||||
description: '"No" option for yes/no radio button set.',
|
||||
},
|
||||
'authoring.examsettings.createzendesk.yes': {
|
||||
id: 'authoring.examsettings.createzendesk.yes',
|
||||
defaultMessage: 'Yes',
|
||||
description: '"Yes" option for yes/no radio button set.',
|
||||
},
|
||||
'authoring.examsettings.support.text': {
|
||||
id: 'authoring.examsettings.support.text',
|
||||
defaultMessage: 'edX Support Page',
|
||||
description: 'Text linking to the support page.',
|
||||
},
|
||||
'authoring.examsettings.enableproctoredexams.label': {
|
||||
id: 'authoring.examsettings.escalationemail.enableproctoredexams.label',
|
||||
defaultMessage: 'Enable Proctored Exams',
|
||||
description: 'Label for checkbox to enable proctored exams.',
|
||||
},
|
||||
'authoring.examsettings.escalationemail.error.blank': {
|
||||
id: 'authoring.examsettings.escalationemail.error.blank',
|
||||
defaultMessage: 'The Proctortrack Escalation Email field cannot be empty if proctortrack is the selected provider.',
|
||||
description: 'Error message for missing required email field.',
|
||||
},
|
||||
'authoring.examsettings.escalationemail.error.invalid': {
|
||||
id: 'authoring.examsettings.escalationemail.error.invalid',
|
||||
defaultMessage: 'The Proctortrack Escalation Email field is in the wrong format and is not valid.',
|
||||
description: 'Error message for a invalid email format.',
|
||||
},
|
||||
'authoring.examsettings.error.single': {
|
||||
id: 'authoring.examsettings.error.single',
|
||||
defaultMessage: 'There is 1 error in this form.',
|
||||
description: 'Error alert for one and only one error in the form.',
|
||||
},
|
||||
'authoring.examsettings.error.multiple': {
|
||||
id: 'authoring.examsettings.escalationemail.error.multiple',
|
||||
defaultMessage: 'There are {numOfErrors} errors in this form.',
|
||||
description: 'Error alert for multiple errors in the form.',
|
||||
},
|
||||
'authoring.examsettings.provider.label': {
|
||||
id: 'authoring.examsettings.provider.label',
|
||||
defaultMessage: 'Proctoring Provider',
|
||||
description: 'Label for provider dropdown selection.',
|
||||
},
|
||||
'authoring.examsettings.provider.help': {
|
||||
id: 'authoring.examsettings.provider.help',
|
||||
defaultMessage: 'Select the proctoring provider you want to use for this course run.',
|
||||
description: 'Help text for selecting a proctoring provider.',
|
||||
},
|
||||
'authoring.examsettings.provider.help.aftercoursestart': {
|
||||
id: 'authoring.examsettings.provider.help.aftercoursestart',
|
||||
defaultMessage: 'Proctoring provider cannot be modified after course start date.',
|
||||
description: 'Help text notifying the user that the provider cannot be changed for a course that has already begun.',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
@@ -2,6 +2,7 @@ import React from 'react';
|
||||
import {
|
||||
render, screen, cleanup, waitFor, waitForElementToBeRemoved, fireEvent, act,
|
||||
} from '@testing-library/react';
|
||||
import { IntlProvider, injectIntl } from '@edx/frontend-platform/i18n';
|
||||
import * as auth from '@edx/frontend-platform/auth';
|
||||
import ProctoredExamSettings from './ProctoredExamSettings';
|
||||
import StudioApiService from '../data/services/StudioApiService';
|
||||
@@ -10,6 +11,14 @@ const defaultProps = {
|
||||
courseId: 'course-v1%3AedX%2BDemoX%2BDemo_Course',
|
||||
};
|
||||
|
||||
const IntlProctoredExamSettings = injectIntl(ProctoredExamSettings);
|
||||
|
||||
const intlWrapper = children => (
|
||||
<IntlProvider locale="en">
|
||||
{children}
|
||||
</IntlProvider>
|
||||
);
|
||||
|
||||
describe('ProctoredExamSettings field dependency tests', () => {
|
||||
beforeEach(async () => {
|
||||
auth.getAuthenticatedHttpClient = jest.fn(() => ({
|
||||
@@ -29,7 +38,7 @@ describe('ProctoredExamSettings field dependency tests', () => {
|
||||
}));
|
||||
|
||||
auth.getAuthenticatedUser = jest.fn(() => ({ userId: 3, administrator: true }));
|
||||
await act(async () => render(<ProctoredExamSettings {...defaultProps} />));
|
||||
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -90,7 +99,7 @@ describe('ProctoredExamSettings field dependency tests', () => {
|
||||
}),
|
||||
}));
|
||||
|
||||
await act(async () => render(<ProctoredExamSettings {...defaultProps} />));
|
||||
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
|
||||
await waitFor(() => {
|
||||
screen.getByLabelText('Enable Proctored Exams');
|
||||
});
|
||||
@@ -148,7 +157,7 @@ describe('ProctoredExamSettings validation with invalid escalation email', () =>
|
||||
}));
|
||||
|
||||
auth.getAuthenticatedUser = jest.fn(() => ({ userId: 3, administrator: false }));
|
||||
await act(async () => render(<ProctoredExamSettings {...defaultProps} />));
|
||||
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -305,28 +314,28 @@ describe('Disables proctoring provider options', () => {
|
||||
|
||||
it('disables irrelevant Proctoring Provider fields when user is not an administrator and it is after start date', async () => {
|
||||
mockAPI(mockGetPastCourseData, false);
|
||||
await act(async () => render(<ProctoredExamSettings {...defaultProps} />));
|
||||
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
|
||||
const providerOption = screen.getByTestId('proctortrack');
|
||||
expect(providerOption.hasAttribute('disabled')).toEqual(true);
|
||||
});
|
||||
|
||||
it('enables all Proctoring Provider options if user is not an administrator and it is before start date', async () => {
|
||||
mockAPI(mockGetFutureCourseData, false);
|
||||
await act(async () => render(<ProctoredExamSettings {...defaultProps} />));
|
||||
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
|
||||
const providerOption = screen.getByTestId('proctortrack');
|
||||
expect(providerOption.hasAttribute('disabled')).toEqual(false);
|
||||
});
|
||||
|
||||
it('enables all Proctoring Provider options if user administrator and it is after start date', async () => {
|
||||
mockAPI(mockGetPastCourseData, true);
|
||||
await act(async () => render(<ProctoredExamSettings {...defaultProps} />));
|
||||
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
|
||||
const providerOption = screen.getByTestId('proctortrack');
|
||||
expect(providerOption.hasAttribute('disabled')).toEqual(false);
|
||||
});
|
||||
|
||||
it('enables all Proctoring Provider options if user administrator and it is before start date', async () => {
|
||||
mockAPI(mockGetFutureCourseData, true);
|
||||
await act(async () => render(<ProctoredExamSettings {...defaultProps} />));
|
||||
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
|
||||
const providerOption = screen.getByTestId('proctortrack');
|
||||
expect(providerOption.hasAttribute('disabled')).toEqual(false);
|
||||
});
|
||||
@@ -362,14 +371,14 @@ describe('Hides fields based on user permissions', () => {
|
||||
|
||||
it('hides opting out and zendesk tickets for non edX staff', async () => {
|
||||
mockAuthentication(false);
|
||||
await act(async () => render(<ProctoredExamSettings {...defaultProps} />));
|
||||
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
|
||||
expect(screen.queryByTestId('allowOptingOutYes')).toBeNull();
|
||||
expect(screen.queryByTestId('createZendeskTicketsYes')).toBeNull();
|
||||
});
|
||||
|
||||
it('shows opting out and zendesk tickets for edX staff', async () => {
|
||||
mockAuthentication(true);
|
||||
await act(async () => render(<ProctoredExamSettings {...defaultProps} />));
|
||||
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
|
||||
expect(screen.queryByTestId('allowOptingOutYes')).not.toBeNull();
|
||||
expect(screen.queryByTestId('createZendeskTicketsYes')).not.toBeNull();
|
||||
});
|
||||
@@ -377,10 +386,13 @@ describe('Hides fields based on user permissions', () => {
|
||||
|
||||
describe('ProctoredExamSettings connection states tests', () => {
|
||||
it('shows the spinner before the connection is complete', async () => {
|
||||
render(<ProctoredExamSettings {...defaultProps} />);
|
||||
auth.getAuthenticatedUser = jest.fn(() => ({ userId: 3, administrator: false }));
|
||||
auth.getAuthenticatedHttpClient = jest.fn(() => ({
|
||||
get: jest.fn(() => new Promise(() => {})),
|
||||
}));
|
||||
render(<IntlProvider local="en"><IntlProctoredExamSettings {...defaultProps} /></IntlProvider>);
|
||||
const spinner = screen.getByTestId('spinnerContainer');
|
||||
expect(spinner.textContent).toEqual('Loading...');
|
||||
await waitForElementToBeRemoved(spinner);
|
||||
});
|
||||
|
||||
it('show connection error message when we suffer server side error', async () => {
|
||||
@@ -395,7 +407,7 @@ describe('ProctoredExamSettings connection states tests', () => {
|
||||
},
|
||||
}));
|
||||
|
||||
await act(async () => render(<ProctoredExamSettings {...defaultProps} />));
|
||||
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
|
||||
const connectionError = screen.getByTestId('connectionError');
|
||||
expect(connectionError.textContent).toEqual(
|
||||
expect.stringContaining('We encountered a technical error'),
|
||||
@@ -414,7 +426,7 @@ describe('ProctoredExamSettings connection states tests', () => {
|
||||
},
|
||||
}));
|
||||
|
||||
await act(async () => render(<ProctoredExamSettings {...defaultProps} />));
|
||||
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
|
||||
const connectionError = screen.getByTestId('permissionError');
|
||||
expect(connectionError.textContent).toEqual(
|
||||
expect.stringContaining('You are not authorized to view this page'),
|
||||
@@ -453,7 +465,7 @@ describe('ProctoredExamSettings save settings tests', () => {
|
||||
|
||||
it('Show spinner while saving', async () => {
|
||||
const mockedFunctions = mockAPI(mockGetData, { data: 'success' });
|
||||
await act(async () => render(<ProctoredExamSettings {...defaultProps} />));
|
||||
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
|
||||
const submitButton = screen.getByTestId('submissionButton');
|
||||
expect(screen.queryByTestId('saveInProgress')).toBeFalsy();
|
||||
fireEvent.click(submitButton);
|
||||
@@ -466,7 +478,7 @@ describe('ProctoredExamSettings save settings tests', () => {
|
||||
|
||||
it('Makes API call successfully with proctoring_escalation_email if proctortrack', async () => {
|
||||
const mockedFunctions = mockAPI(mockGetData, { data: 'success' });
|
||||
await act(async () => render(<ProctoredExamSettings {...defaultProps} />));
|
||||
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
|
||||
// Make a change to the provider to proctortrack and set the email
|
||||
const selectElement = screen.getByDisplayValue('mockproc');
|
||||
await act(async () => {
|
||||
@@ -532,7 +544,7 @@ describe('ProctoredExamSettings save settings tests', () => {
|
||||
|
||||
it('Makes API call generated error', async () => {
|
||||
const mockedFunctions = mockAPI(mockGetData, false);
|
||||
await act(async () => render(<ProctoredExamSettings {...defaultProps} />));
|
||||
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
|
||||
// Make a change to the provider to proctortrack and set the email
|
||||
const submitButton = screen.getByTestId('submissionButton');
|
||||
await act(async () => {
|
||||
|
||||
Reference in New Issue
Block a user