fix: propTypes warnings in Problem Editor, refactor some code to TS (#1280)
* fix: a11y - missing 'alt' text for Problem Editor IconButton * fix: warning in <ProblemTypeSelect> component - missing key prop in list * fix: warning: `problemType` required in `ProblemEditor`, but is `null` * fix: warning: The prop `onClose` marked as required in `SelectTypeModal` * fix: warning: prop `name` is marked as required in `ForwardRef(_c)` * fix: warning: props `alt`, `id`, and `key` are required * test: improve test coverage of SelectTypeModal, refactor some code * test: improve test coverage
This commit is contained in:
5
src/custom.d.ts
vendored
5
src/custom.d.ts
vendored
@@ -3,6 +3,11 @@ declare module '*.svg' {
|
||||
export default content;
|
||||
}
|
||||
|
||||
declare module '*.png' {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
||||
|
||||
declare module '*.json' {
|
||||
const value: any;
|
||||
export default value;
|
||||
|
||||
@@ -1,21 +1,29 @@
|
||||
import React from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import messages from './messages';
|
||||
import * as hooks from './hooks';
|
||||
|
||||
import supportedEditors from './supportedEditors';
|
||||
import type { EditorComponent } from './EditorComponent';
|
||||
|
||||
const Editor = ({
|
||||
export interface Props extends EditorComponent {
|
||||
blockType: string;
|
||||
blockId: string | null;
|
||||
learningContextId: string | null;
|
||||
lmsEndpointUrl: string | null;
|
||||
studioEndpointUrl: string | null;
|
||||
}
|
||||
|
||||
const Editor: React.FC<Props> = ({
|
||||
learningContextId,
|
||||
blockType,
|
||||
blockId,
|
||||
lmsEndpointUrl,
|
||||
studioEndpointUrl,
|
||||
onClose,
|
||||
returnFunction,
|
||||
onClose = null,
|
||||
returnFunction = null,
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
hooks.initializeApp({
|
||||
@@ -46,23 +54,5 @@ const Editor = ({
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Editor.defaultProps = {
|
||||
blockId: null,
|
||||
learningContextId: null,
|
||||
lmsEndpointUrl: null,
|
||||
onClose: null,
|
||||
returnFunction: null,
|
||||
studioEndpointUrl: null,
|
||||
};
|
||||
|
||||
Editor.propTypes = {
|
||||
blockId: PropTypes.string,
|
||||
blockType: PropTypes.string.isRequired,
|
||||
learningContextId: PropTypes.string,
|
||||
lmsEndpointUrl: PropTypes.string,
|
||||
onClose: PropTypes.func,
|
||||
returnFunction: PropTypes.func,
|
||||
studioEndpointUrl: PropTypes.string,
|
||||
};
|
||||
|
||||
export default Editor;
|
||||
6
src/editors/EditorComponent.ts
Normal file
6
src/editors/EditorComponent.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
/** Shared interface that all Editor components (like ProblemEditor) adhere to */
|
||||
export interface EditorComponent {
|
||||
onClose: (() => void) | null;
|
||||
// TODO: get a better type for the 'result' here
|
||||
returnFunction?: (() => (result: any) => void) | null;
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
|
||||
import {
|
||||
ActionRow,
|
||||
Button,
|
||||
ModalDialog,
|
||||
} from '@openedx/paragon';
|
||||
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import messages from './messages';
|
||||
import * as hooks from '../hooks';
|
||||
|
||||
@@ -16,68 +15,49 @@ import { actions, selectors } from '../../../../../data/redux';
|
||||
const SelectTypeFooter = ({
|
||||
onCancel,
|
||||
selected,
|
||||
// redux
|
||||
defaultSettings,
|
||||
updateField,
|
||||
setBlockTitle,
|
||||
// injected,
|
||||
intl,
|
||||
}) => (
|
||||
<div className="editor-footer fixed-bottom">
|
||||
<ModalDialog.Footer className="border-top-0">
|
||||
<ActionRow>
|
||||
<ActionRow.Spacer />
|
||||
<Button
|
||||
aria-label={intl.formatMessage(messages.cancelButtonAriaLabel)}
|
||||
variant="tertiary"
|
||||
onClick={onCancel}
|
||||
>
|
||||
<FormattedMessage {...messages.cancelButtonLabel} />
|
||||
</Button>
|
||||
<Button
|
||||
aria-label={intl.formatMessage(messages.selectButtonAriaLabel)}
|
||||
onClick={hooks.onSelect({
|
||||
selected,
|
||||
updateField,
|
||||
setBlockTitle,
|
||||
defaultSettings,
|
||||
})}
|
||||
disabled={!selected}
|
||||
>
|
||||
<FormattedMessage {...messages.selectButtonLabel} />
|
||||
</Button>
|
||||
</ActionRow>
|
||||
</ModalDialog.Footer>
|
||||
</div>
|
||||
);
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const defaultSettings = useSelector(selectors.problem.defaultSettings);
|
||||
const dispatch = useDispatch();
|
||||
const updateField = React.useCallback((data) => dispatch(actions.problem.updateField(data)), [dispatch]);
|
||||
const setBlockTitle = React.useCallback((title) => dispatch(actions.app.setBlockTitle(title)), [dispatch]);
|
||||
return (
|
||||
<div className="editor-footer fixed-bottom">
|
||||
<ModalDialog.Footer className="border-top-0">
|
||||
<ActionRow>
|
||||
<ActionRow.Spacer />
|
||||
<Button
|
||||
aria-label={intl.formatMessage(messages.cancelButtonAriaLabel)}
|
||||
variant="tertiary"
|
||||
onClick={onCancel}
|
||||
>
|
||||
<FormattedMessage {...messages.cancelButtonLabel} />
|
||||
</Button>
|
||||
<Button
|
||||
aria-label={intl.formatMessage(messages.selectButtonAriaLabel)}
|
||||
onClick={hooks.onSelect({
|
||||
selected,
|
||||
updateField,
|
||||
setBlockTitle,
|
||||
defaultSettings,
|
||||
})}
|
||||
disabled={!selected}
|
||||
>
|
||||
<FormattedMessage {...messages.selectButtonLabel} />
|
||||
</Button>
|
||||
</ActionRow>
|
||||
</ModalDialog.Footer>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
SelectTypeFooter.defaultProps = {
|
||||
selected: null,
|
||||
};
|
||||
|
||||
SelectTypeFooter.propTypes = {
|
||||
defaultSettings: PropTypes.shape({
|
||||
maxAttempts: PropTypes.number,
|
||||
rerandomize: PropTypes.string,
|
||||
showResetButton: PropTypes.bool,
|
||||
showanswer: PropTypes.string,
|
||||
}).isRequired,
|
||||
onCancel: PropTypes.func.isRequired,
|
||||
selected: PropTypes.string,
|
||||
updateField: PropTypes.func.isRequired,
|
||||
setBlockTitle: PropTypes.func.isRequired,
|
||||
// injected
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export const mapStateToProps = (state) => ({
|
||||
defaultSettings: selectors.problem.defaultSettings(state),
|
||||
});
|
||||
|
||||
export const mapDispatchToProps = {
|
||||
updateField: actions.problem.updateField,
|
||||
setBlockTitle: actions.app.setBlockTitle,
|
||||
};
|
||||
|
||||
export const SelectTypeFooterInternal = SelectTypeFooter; // For testing only
|
||||
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(SelectTypeFooter));
|
||||
export default SelectTypeFooter;
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
import 'CourseAuthoring/editors/setupEditorTest';
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
|
||||
import { Button } from '@openedx/paragon';
|
||||
import { formatMessage } from '../../../../../testUtils';
|
||||
import * as module from './SelectTypeFooter';
|
||||
import SelectTypeFooter from './SelectTypeFooter';
|
||||
import * as hooks from '../hooks';
|
||||
import { actions } from '../../../../../data/redux';
|
||||
|
||||
const SelectTypeFooter = module.SelectTypeFooterInternal;
|
||||
|
||||
jest.mock('../hooks', () => ({
|
||||
onSelect: jest.fn().mockName('onSelect'),
|
||||
@@ -46,15 +42,4 @@ describe('SelectTypeFooter', () => {
|
||||
.toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('mapStateToProps', () => {
|
||||
test('is empty', () => {
|
||||
expect(module.mapDispatchToProps.defaultSettings).toEqual(actions.problem.defaultSettings);
|
||||
});
|
||||
});
|
||||
describe('mapDispatchToProps', () => {
|
||||
test('loads updateField from problem.updateField actions', () => {
|
||||
expect(module.mapDispatchToProps.updateField).toEqual(actions.problem.updateField);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -17,6 +17,7 @@ exports[`SelectTypeWrapper snapshot 1`] = `
|
||||
className="pgn__modal-close-container"
|
||||
>
|
||||
<IconButton
|
||||
alt="Exit the editor"
|
||||
iconAs="Icon"
|
||||
src={[MockFunction icons.Close]}
|
||||
/>
|
||||
@@ -30,7 +31,7 @@ exports[`SelectTypeWrapper snapshot 1`] = `
|
||||
test child
|
||||
</h1>
|
||||
</ModalDialog.Body>
|
||||
<injectIntl(ShimmedIntlComponent)
|
||||
<SelectTypeFooter
|
||||
selected="iMAsElecTedValUE"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { injectIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Icon, ModalDialog, IconButton } from '@openedx/paragon';
|
||||
import { Close } from '@openedx/paragon/icons';
|
||||
import SelectTypeFooter from './SelectTypeFooter';
|
||||
|
||||
import * as hooks from '../../../../EditorContainer/hooks';
|
||||
import ecMessages from '../../../../EditorContainer/messages';
|
||||
import messages from './messages';
|
||||
|
||||
const SelectTypeWrapper = ({
|
||||
@@ -14,6 +15,7 @@ const SelectTypeWrapper = ({
|
||||
selected,
|
||||
}) => {
|
||||
const handleCancel = hooks.handleCancel({ onClose });
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -27,6 +29,7 @@ const SelectTypeWrapper = ({
|
||||
src={Close}
|
||||
iconAs={Icon}
|
||||
onClick={handleCancel}
|
||||
alt={intl.formatMessage(ecMessages.exitButtonAlt)}
|
||||
/>
|
||||
</div>
|
||||
</ModalDialog.Title>
|
||||
@@ -51,5 +54,4 @@ SelectTypeWrapper.propTypes = {
|
||||
onClose: PropTypes.func,
|
||||
};
|
||||
|
||||
export const SelectTypeWrapperInternal = SelectTypeWrapper; // For testing only
|
||||
export default injectIntl(SelectTypeWrapper);
|
||||
export default SelectTypeWrapper;
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'CourseAuthoring/editors/setupEditorTest';
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
import { IconButton } from '@openedx/paragon';
|
||||
import { SelectTypeWrapperInternal as SelectTypeWrapper } from '.';
|
||||
import SelectTypeWrapper from '.';
|
||||
import { handleCancel } from '../../../../EditorContainer/hooks';
|
||||
|
||||
jest.mock('../../../../EditorContainer/hooks', () => ({
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`SelectTypeModal snapshot 1`] = `
|
||||
<injectIntl(ShimmedIntlComponent)
|
||||
onClose={[MockFunction]}
|
||||
selected="mOcKsELEcted"
|
||||
>
|
||||
<Row
|
||||
className="justify-content-center"
|
||||
>
|
||||
<Stack
|
||||
className="flex-wrap mb-6"
|
||||
direction="horizontal"
|
||||
gap={4}
|
||||
>
|
||||
<injectIntl(ShimmedIntlComponent)
|
||||
selected="mOcKsELEcted"
|
||||
setSelected={[MockFunction setSelected]}
|
||||
/>
|
||||
<injectIntl(ShimmedIntlComponent)
|
||||
problemType="mOcKsELEcted"
|
||||
/>
|
||||
</Stack>
|
||||
</Row>
|
||||
</injectIntl(ShimmedIntlComponent)>
|
||||
`;
|
||||
@@ -1,16 +1,11 @@
|
||||
import 'CourseAuthoring/editors/setupEditorTest';
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
|
||||
import { formatMessage } from '../../../../../testUtils';
|
||||
import * as module from './AdvanceTypeSelect';
|
||||
|
||||
const AdvanceTypeSelect = module.AdvanceTypeSelectInternal;
|
||||
import AdvanceTypeSelect from './AdvanceTypeSelect';
|
||||
|
||||
describe('AdvanceTypeSelect', () => {
|
||||
const props = {
|
||||
intl: { formatMessage },
|
||||
selected: 'blankadvanced',
|
||||
selected: 'blankadvanced' as const,
|
||||
setSelected: jest.fn().mockName('setSelect'),
|
||||
};
|
||||
describe('snapshots', () => {
|
||||
@@ -29,11 +24,6 @@ describe('AdvanceTypeSelect', () => {
|
||||
shallow(<AdvanceTypeSelect {...props} selected="customgrader" />).snapshot,
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
test('snapshots: renders as expected with problemType is drag_and_drop', () => {
|
||||
expect(
|
||||
shallow(<AdvanceTypeSelect {...props} selected="drag_and_drop" />).snapshot,
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
test('snapshots: renders as expected with problemType is formularesponse', () => {
|
||||
expect(
|
||||
shallow(<AdvanceTypeSelect {...props} selected="formularesponse" />).snapshot,
|
||||
@@ -44,14 +34,14 @@ describe('AdvanceTypeSelect', () => {
|
||||
shallow(<AdvanceTypeSelect {...props} selected="imageresponse" />).snapshot,
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
test('snapshots: renders as expected with problemType is jsinput_response', () => {
|
||||
test('snapshots: renders as expected with problemType is jsinputresponse', () => {
|
||||
expect(
|
||||
shallow(<AdvanceTypeSelect {...props} selected="jsinput_response" />).snapshot,
|
||||
shallow(<AdvanceTypeSelect {...props} selected="jsinputresponse" />).snapshot,
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
test('snapshots: renders as expected with problemType is problem_with_hint', () => {
|
||||
test('snapshots: renders as expected with problemType is problemwithhint', () => {
|
||||
expect(
|
||||
shallow(<AdvanceTypeSelect {...props} selected="problem_with_hint" />).snapshot,
|
||||
shallow(<AdvanceTypeSelect {...props} selected="problemwithhint" />).snapshot,
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,4 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
Form,
|
||||
@@ -12,22 +11,36 @@ import {
|
||||
Col,
|
||||
} from '@openedx/paragon';
|
||||
import { ArrowBack } from '@openedx/paragon/icons';
|
||||
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { AdvanceProblems, ProblemTypeKeys } from '../../../../../data/constants/problem';
|
||||
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
|
||||
import {
|
||||
AdvancedProblemType,
|
||||
AdvanceProblems,
|
||||
ProblemType,
|
||||
ProblemTypeKeys,
|
||||
} from '../../../../../data/constants/problem';
|
||||
import messages from './messages';
|
||||
|
||||
const AdvanceTypeSelect = ({
|
||||
interface Props {
|
||||
selected: AdvancedProblemType;
|
||||
setSelected: React.Dispatch<ProblemType | AdvancedProblemType>;
|
||||
}
|
||||
|
||||
const AdvanceTypeSelect: React.FC<Props> = ({
|
||||
selected,
|
||||
setSelected,
|
||||
// injected
|
||||
intl,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const handleChange = e => { setSelected(e.target.value); };
|
||||
return (
|
||||
<Col xs={12} md={8} className="justify-content-center">
|
||||
<Form.Group className="border rounded text-primary-500 p-0">
|
||||
<ActionRow className="border-primary-100 border-bottom py-3 pl-2.5 pr-4">
|
||||
<IconButton src={ArrowBack} iconAs={Icon} onClick={() => setSelected(ProblemTypeKeys.SINGLESELECT)} />
|
||||
<IconButton
|
||||
src={ArrowBack}
|
||||
iconAs={Icon}
|
||||
alt={intl.formatMessage(messages.advanceMenuGoBack)}
|
||||
onClick={() => setSelected(ProblemTypeKeys.SINGLESELECT)}
|
||||
/>
|
||||
<ActionRow.Spacer />
|
||||
<Form.Label className="h4">
|
||||
<FormattedMessage {...messages.advanceMenuTitle} />
|
||||
@@ -43,7 +56,7 @@ const AdvanceTypeSelect = ({
|
||||
{Object.entries(AdvanceProblems).map(([type, data]) => {
|
||||
if (data.status !== '') {
|
||||
return (
|
||||
<ActionRow className="border-primary-100 border-bottom m-0 py-3 w-100">
|
||||
<ActionRow className="border-primary-100 border-bottom m-0 py-3 w-100" key={type}>
|
||||
<Form.Radio id={type} value={type}>
|
||||
{intl.formatMessage(messages.advanceProblemTypeLabel, { problemType: data.title })}
|
||||
</Form.Radio>
|
||||
@@ -51,7 +64,7 @@ const AdvanceTypeSelect = ({
|
||||
<OverlayTrigger
|
||||
placement="right"
|
||||
overlay={(
|
||||
<Tooltip>
|
||||
<Tooltip id={`tooltip-adv-${type}`}>
|
||||
<div className="text-left">
|
||||
{intl.formatMessage(messages.supportStatusTooltipMessage, { supportStatus: data.status.replace(' ', '_') })}
|
||||
</div>
|
||||
@@ -66,7 +79,7 @@ const AdvanceTypeSelect = ({
|
||||
);
|
||||
}
|
||||
return (
|
||||
<ActionRow className="border-primary-100 border-bottom m-0 py-3 w-100">
|
||||
<ActionRow className="border-primary-100 border-bottom m-0 py-3 w-100" key={type}>
|
||||
<Form.Radio id={type} value={type}>
|
||||
{intl.formatMessage(messages.advanceProblemTypeLabel, { problemType: data.title })}
|
||||
</Form.Radio>
|
||||
@@ -86,16 +99,4 @@ const AdvanceTypeSelect = ({
|
||||
);
|
||||
};
|
||||
|
||||
AdvanceTypeSelect.defaultProps = {
|
||||
selected: null,
|
||||
};
|
||||
|
||||
AdvanceTypeSelect.propTypes = {
|
||||
selected: PropTypes.string,
|
||||
setSelected: PropTypes.func.isRequired,
|
||||
// injected
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export const AdvanceTypeSelectInternal = AdvanceTypeSelect; // For testing only
|
||||
export default injectIntl(AdvanceTypeSelect);
|
||||
export default AdvanceTypeSelect;
|
||||
@@ -1,12 +1,11 @@
|
||||
import 'CourseAuthoring/editors/setupEditorTest';
|
||||
import React from 'react';
|
||||
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
import { ProblemTypeKeys } from '../../../../../data/constants/problem';
|
||||
import { ProblemTypeSelectInternal as ProblemTypeSelect } from './ProblemTypeSelect';
|
||||
import ProblemTypeSelect from './ProblemTypeSelect';
|
||||
|
||||
describe('ProblemTypeSelect', () => {
|
||||
const props = {
|
||||
selected: null,
|
||||
setSelected: jest.fn(),
|
||||
};
|
||||
|
||||
@@ -1,24 +1,35 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button, Container } from '@openedx/paragon';
|
||||
import { FormattedMessage, injectIntl } from '@edx/frontend-platform/i18n';
|
||||
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
|
||||
// SelectableBox in paragon has a bug where you can't change selection. So we override it
|
||||
import SelectableBox from '../../../../../sharedComponents/SelectableBox';
|
||||
import { ProblemTypes, ProblemTypeKeys, AdvanceProblemKeys } from '../../../../../data/constants/problem';
|
||||
import {
|
||||
ProblemTypes,
|
||||
ProblemTypeKeys,
|
||||
AdvanceProblemKeys,
|
||||
AdvancedProblemType,
|
||||
ProblemType,
|
||||
} from '../../../../../data/constants/problem';
|
||||
import messages from './messages';
|
||||
|
||||
const ProblemTypeSelect = ({
|
||||
interface Props {
|
||||
selected: ProblemType;
|
||||
setSelected: (selected: ProblemType | AdvancedProblemType) => void;
|
||||
}
|
||||
|
||||
const ProblemTypeSelect: React.FC<Props> = ({
|
||||
selected,
|
||||
setSelected,
|
||||
}) => {
|
||||
const handleChange = e => setSelected(e.target.value);
|
||||
const handleClick = () => setSelected(AdvanceProblemKeys.BLANK);
|
||||
const settings = { 'aria-label': 'checkbox', type: 'radio' };
|
||||
const settings = { type: 'radio' };
|
||||
|
||||
return (
|
||||
<Container style={{ width: '494px', height: '400px' }}>
|
||||
<SelectableBox.Set
|
||||
name="problem-type"
|
||||
columns={1}
|
||||
onChange={handleChange}
|
||||
type={settings.type}
|
||||
@@ -30,6 +41,7 @@ const ProblemTypeSelect = ({
|
||||
<SelectableBox
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id={key}
|
||||
key={key}
|
||||
value={key}
|
||||
{...settings}
|
||||
>
|
||||
@@ -45,10 +57,5 @@ const ProblemTypeSelect = ({
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
ProblemTypeSelect.propTypes = {
|
||||
selected: PropTypes.string.isRequired,
|
||||
setSelected: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export const ProblemTypeSelectInternal = ProblemTypeSelect; // For testing only
|
||||
export default injectIntl(ProblemTypeSelect);
|
||||
export default ProblemTypeSelect;
|
||||
@@ -13,6 +13,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with default
|
||||
className="border-primary-100 border-bottom py-3 pl-2.5 pr-4"
|
||||
>
|
||||
<IconButton
|
||||
alt="Go back"
|
||||
iconAs="Icon"
|
||||
onClick={[Function]}
|
||||
/>
|
||||
@@ -36,6 +37,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with default
|
||||
>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="blankadvanced"
|
||||
>
|
||||
<Radio
|
||||
id="blankadvanced"
|
||||
@@ -47,6 +49,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with default
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="circuitschematic"
|
||||
>
|
||||
<Radio
|
||||
id="circuitschematic"
|
||||
@@ -57,7 +60,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with default
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-circuitschematic"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -91,6 +96,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with default
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="jsinputresponse"
|
||||
>
|
||||
<Radio
|
||||
id="jsinputresponse"
|
||||
@@ -102,6 +108,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with default
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="customgrader"
|
||||
>
|
||||
<Radio
|
||||
id="customgrader"
|
||||
@@ -112,7 +119,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with default
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-customgrader"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -146,6 +155,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with default
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="imageresponse"
|
||||
>
|
||||
<Radio
|
||||
id="imageresponse"
|
||||
@@ -156,7 +166,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with default
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-imageresponse"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -190,6 +202,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with default
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="formularesponse"
|
||||
>
|
||||
<Radio
|
||||
id="formularesponse"
|
||||
@@ -201,6 +214,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with default
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="problemwithhint"
|
||||
>
|
||||
<Radio
|
||||
id="problemwithhint"
|
||||
@@ -211,7 +225,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with default
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-problemwithhint"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -271,6 +287,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
className="border-primary-100 border-bottom py-3 pl-2.5 pr-4"
|
||||
>
|
||||
<IconButton
|
||||
alt="Go back"
|
||||
iconAs="Icon"
|
||||
onClick={[Function]}
|
||||
/>
|
||||
@@ -294,6 +311,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="blankadvanced"
|
||||
>
|
||||
<Radio
|
||||
id="blankadvanced"
|
||||
@@ -305,6 +323,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="circuitschematic"
|
||||
>
|
||||
<Radio
|
||||
id="circuitschematic"
|
||||
@@ -315,7 +334,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-circuitschematic"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -349,6 +370,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="jsinputresponse"
|
||||
>
|
||||
<Radio
|
||||
id="jsinputresponse"
|
||||
@@ -360,6 +382,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="customgrader"
|
||||
>
|
||||
<Radio
|
||||
id="customgrader"
|
||||
@@ -370,7 +393,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-customgrader"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -404,6 +429,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="imageresponse"
|
||||
>
|
||||
<Radio
|
||||
id="imageresponse"
|
||||
@@ -414,7 +440,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-imageresponse"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -448,6 +476,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="formularesponse"
|
||||
>
|
||||
<Radio
|
||||
id="formularesponse"
|
||||
@@ -459,6 +488,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="problemwithhint"
|
||||
>
|
||||
<Radio
|
||||
id="problemwithhint"
|
||||
@@ -469,7 +499,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-problemwithhint"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -529,6 +561,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
className="border-primary-100 border-bottom py-3 pl-2.5 pr-4"
|
||||
>
|
||||
<IconButton
|
||||
alt="Go back"
|
||||
iconAs="Icon"
|
||||
onClick={[Function]}
|
||||
/>
|
||||
@@ -552,6 +585,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="blankadvanced"
|
||||
>
|
||||
<Radio
|
||||
id="blankadvanced"
|
||||
@@ -563,6 +597,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="circuitschematic"
|
||||
>
|
||||
<Radio
|
||||
id="circuitschematic"
|
||||
@@ -573,7 +608,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-circuitschematic"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -607,6 +644,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="jsinputresponse"
|
||||
>
|
||||
<Radio
|
||||
id="jsinputresponse"
|
||||
@@ -618,6 +656,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="customgrader"
|
||||
>
|
||||
<Radio
|
||||
id="customgrader"
|
||||
@@ -628,7 +667,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-customgrader"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -662,6 +703,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="imageresponse"
|
||||
>
|
||||
<Radio
|
||||
id="imageresponse"
|
||||
@@ -672,7 +714,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-imageresponse"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -706,6 +750,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="formularesponse"
|
||||
>
|
||||
<Radio
|
||||
id="formularesponse"
|
||||
@@ -717,6 +762,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="problemwithhint"
|
||||
>
|
||||
<Radio
|
||||
id="problemwithhint"
|
||||
@@ -727,265 +773,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
{supportStatus, select,
|
||||
Provisional {Provisionally supported tools might lack the robustness of functionality
|
||||
that your courses require. edX does not have control over the quality of the software,
|
||||
or of the content that can be provided using these tools.
|
||||
|
||||
|
||||
|
||||
Test these tools thoroughly before using them in your course, especially in graded
|
||||
sections. Complete documentstion might not be available for provisionally supported
|
||||
tools, or documentation might be available from sources other than edX.}
|
||||
Not_supported {Tools with no support are not maintained by edX, and might be deprecated
|
||||
in the future. They are not recommened for use in courses due to non-compliance with one
|
||||
or more of the base requirements, such as testing, accessibility, internationalization,
|
||||
and documentation.}
|
||||
other { }
|
||||
}
|
||||
</div>
|
||||
</Tooltip>
|
||||
}
|
||||
placement="right"
|
||||
>
|
||||
<div
|
||||
className="text-gray-500"
|
||||
>
|
||||
Not supported
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
</ActionRow>
|
||||
</RadioSet>
|
||||
</Form.Group>
|
||||
<Hyperlink
|
||||
destination="https://edx.readthedocs.io/projects/edx-partner-course-staff/en/latest/exercises_tools/create_exercises_and_tools.html#advanced"
|
||||
target="_blank"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Learn more about advanced problem types"
|
||||
description="Label for Learn more about advanced problem types button"
|
||||
id="authoring.problemEditor.advanceProblem.learnMoreButtonLabel.label"
|
||||
/>
|
||||
</Hyperlink>
|
||||
</Col>
|
||||
`;
|
||||
|
||||
exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problemType is drag_and_drop 1`] = `
|
||||
<Col
|
||||
className="justify-content-center"
|
||||
md={8}
|
||||
xs={12}
|
||||
>
|
||||
<Form.Group
|
||||
className="border rounded text-primary-500 p-0"
|
||||
>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom py-3 pl-2.5 pr-4"
|
||||
>
|
||||
<IconButton
|
||||
iconAs="Icon"
|
||||
onClick={[Function]}
|
||||
/>
|
||||
<ActionRow.Spacer />
|
||||
<Form.Label
|
||||
className="h4"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Advanced problems"
|
||||
description="Title for advanced problem menu"
|
||||
id="authoring.problemEditor.advanceProblem.menu.title"
|
||||
/>
|
||||
</Form.Label>
|
||||
<ActionRow.Spacer />
|
||||
</ActionRow>
|
||||
<RadioSet
|
||||
className="px-4"
|
||||
name="advanceTypes"
|
||||
onChange={[Function]}
|
||||
value="drag_and_drop"
|
||||
>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
>
|
||||
<Radio
|
||||
id="blankadvanced"
|
||||
value="blankadvanced"
|
||||
>
|
||||
Blank problem
|
||||
</Radio>
|
||||
<ActionRow.Spacer />
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
>
|
||||
<Radio
|
||||
id="circuitschematic"
|
||||
value="circuitschematic"
|
||||
>
|
||||
Circuit schematic builder
|
||||
</Radio>
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
{supportStatus, select,
|
||||
Provisional {Provisionally supported tools might lack the robustness of functionality
|
||||
that your courses require. edX does not have control over the quality of the software,
|
||||
or of the content that can be provided using these tools.
|
||||
|
||||
|
||||
|
||||
Test these tools thoroughly before using them in your course, especially in graded
|
||||
sections. Complete documentstion might not be available for provisionally supported
|
||||
tools, or documentation might be available from sources other than edX.}
|
||||
Not_supported {Tools with no support are not maintained by edX, and might be deprecated
|
||||
in the future. They are not recommened for use in courses due to non-compliance with one
|
||||
or more of the base requirements, such as testing, accessibility, internationalization,
|
||||
and documentation.}
|
||||
other { }
|
||||
}
|
||||
</div>
|
||||
</Tooltip>
|
||||
}
|
||||
placement="right"
|
||||
>
|
||||
<div
|
||||
className="text-gray-500"
|
||||
>
|
||||
Not supported
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
>
|
||||
<Radio
|
||||
id="jsinputresponse"
|
||||
value="jsinputresponse"
|
||||
>
|
||||
Custom JavaScript display and grading
|
||||
</Radio>
|
||||
<ActionRow.Spacer />
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
>
|
||||
<Radio
|
||||
id="customgrader"
|
||||
value="customgrader"
|
||||
>
|
||||
Custom Python-evaluated input
|
||||
</Radio>
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
{supportStatus, select,
|
||||
Provisional {Provisionally supported tools might lack the robustness of functionality
|
||||
that your courses require. edX does not have control over the quality of the software,
|
||||
or of the content that can be provided using these tools.
|
||||
|
||||
|
||||
|
||||
Test these tools thoroughly before using them in your course, especially in graded
|
||||
sections. Complete documentstion might not be available for provisionally supported
|
||||
tools, or documentation might be available from sources other than edX.}
|
||||
Not_supported {Tools with no support are not maintained by edX, and might be deprecated
|
||||
in the future. They are not recommened for use in courses due to non-compliance with one
|
||||
or more of the base requirements, such as testing, accessibility, internationalization,
|
||||
and documentation.}
|
||||
other { }
|
||||
}
|
||||
</div>
|
||||
</Tooltip>
|
||||
}
|
||||
placement="right"
|
||||
>
|
||||
<div
|
||||
className="text-gray-500"
|
||||
>
|
||||
Provisional
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
>
|
||||
<Radio
|
||||
id="imageresponse"
|
||||
value="imageresponse"
|
||||
>
|
||||
Image mapped input
|
||||
</Radio>
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
{supportStatus, select,
|
||||
Provisional {Provisionally supported tools might lack the robustness of functionality
|
||||
that your courses require. edX does not have control over the quality of the software,
|
||||
or of the content that can be provided using these tools.
|
||||
|
||||
|
||||
|
||||
Test these tools thoroughly before using them in your course, especially in graded
|
||||
sections. Complete documentstion might not be available for provisionally supported
|
||||
tools, or documentation might be available from sources other than edX.}
|
||||
Not_supported {Tools with no support are not maintained by edX, and might be deprecated
|
||||
in the future. They are not recommened for use in courses due to non-compliance with one
|
||||
or more of the base requirements, such as testing, accessibility, internationalization,
|
||||
and documentation.}
|
||||
other { }
|
||||
}
|
||||
</div>
|
||||
</Tooltip>
|
||||
}
|
||||
placement="right"
|
||||
>
|
||||
<div
|
||||
className="text-gray-500"
|
||||
>
|
||||
Not supported
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
>
|
||||
<Radio
|
||||
id="formularesponse"
|
||||
value="formularesponse"
|
||||
>
|
||||
Math expression input
|
||||
</Radio>
|
||||
<ActionRow.Spacer />
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
>
|
||||
<Radio
|
||||
id="problemwithhint"
|
||||
value="problemwithhint"
|
||||
>
|
||||
Problem with adaptive hint
|
||||
</Radio>
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-problemwithhint"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -1045,6 +835,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
className="border-primary-100 border-bottom py-3 pl-2.5 pr-4"
|
||||
>
|
||||
<IconButton
|
||||
alt="Go back"
|
||||
iconAs="Icon"
|
||||
onClick={[Function]}
|
||||
/>
|
||||
@@ -1068,6 +859,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="blankadvanced"
|
||||
>
|
||||
<Radio
|
||||
id="blankadvanced"
|
||||
@@ -1079,6 +871,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="circuitschematic"
|
||||
>
|
||||
<Radio
|
||||
id="circuitschematic"
|
||||
@@ -1089,7 +882,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-circuitschematic"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -1123,6 +918,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="jsinputresponse"
|
||||
>
|
||||
<Radio
|
||||
id="jsinputresponse"
|
||||
@@ -1134,6 +930,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="customgrader"
|
||||
>
|
||||
<Radio
|
||||
id="customgrader"
|
||||
@@ -1144,7 +941,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-customgrader"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -1178,6 +977,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="imageresponse"
|
||||
>
|
||||
<Radio
|
||||
id="imageresponse"
|
||||
@@ -1188,7 +988,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-imageresponse"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -1222,6 +1024,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="formularesponse"
|
||||
>
|
||||
<Radio
|
||||
id="formularesponse"
|
||||
@@ -1233,6 +1036,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="problemwithhint"
|
||||
>
|
||||
<Radio
|
||||
id="problemwithhint"
|
||||
@@ -1243,7 +1047,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-problemwithhint"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -1303,6 +1109,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
className="border-primary-100 border-bottom py-3 pl-2.5 pr-4"
|
||||
>
|
||||
<IconButton
|
||||
alt="Go back"
|
||||
iconAs="Icon"
|
||||
onClick={[Function]}
|
||||
/>
|
||||
@@ -1326,6 +1133,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="blankadvanced"
|
||||
>
|
||||
<Radio
|
||||
id="blankadvanced"
|
||||
@@ -1337,6 +1145,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="circuitschematic"
|
||||
>
|
||||
<Radio
|
||||
id="circuitschematic"
|
||||
@@ -1347,7 +1156,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-circuitschematic"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -1381,6 +1192,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="jsinputresponse"
|
||||
>
|
||||
<Radio
|
||||
id="jsinputresponse"
|
||||
@@ -1392,6 +1204,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="customgrader"
|
||||
>
|
||||
<Radio
|
||||
id="customgrader"
|
||||
@@ -1402,7 +1215,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-customgrader"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -1436,6 +1251,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="imageresponse"
|
||||
>
|
||||
<Radio
|
||||
id="imageresponse"
|
||||
@@ -1446,7 +1262,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-imageresponse"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -1480,6 +1298,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="formularesponse"
|
||||
>
|
||||
<Radio
|
||||
id="formularesponse"
|
||||
@@ -1491,6 +1310,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="problemwithhint"
|
||||
>
|
||||
<Radio
|
||||
id="problemwithhint"
|
||||
@@ -1501,7 +1321,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-problemwithhint"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -1548,7 +1370,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</Col>
|
||||
`;
|
||||
|
||||
exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problemType is jsinput_response 1`] = `
|
||||
exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problemType is jsinputresponse 1`] = `
|
||||
<Col
|
||||
className="justify-content-center"
|
||||
md={8}
|
||||
@@ -1561,6 +1383,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
className="border-primary-100 border-bottom py-3 pl-2.5 pr-4"
|
||||
>
|
||||
<IconButton
|
||||
alt="Go back"
|
||||
iconAs="Icon"
|
||||
onClick={[Function]}
|
||||
/>
|
||||
@@ -1580,10 +1403,11 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
className="px-4"
|
||||
name="advanceTypes"
|
||||
onChange={[Function]}
|
||||
value="jsinput_response"
|
||||
value="jsinputresponse"
|
||||
>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="blankadvanced"
|
||||
>
|
||||
<Radio
|
||||
id="blankadvanced"
|
||||
@@ -1595,6 +1419,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="circuitschematic"
|
||||
>
|
||||
<Radio
|
||||
id="circuitschematic"
|
||||
@@ -1605,7 +1430,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-circuitschematic"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -1639,6 +1466,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="jsinputresponse"
|
||||
>
|
||||
<Radio
|
||||
id="jsinputresponse"
|
||||
@@ -1650,6 +1478,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="customgrader"
|
||||
>
|
||||
<Radio
|
||||
id="customgrader"
|
||||
@@ -1660,7 +1489,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-customgrader"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -1694,6 +1525,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="imageresponse"
|
||||
>
|
||||
<Radio
|
||||
id="imageresponse"
|
||||
@@ -1704,7 +1536,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-imageresponse"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -1738,6 +1572,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="formularesponse"
|
||||
>
|
||||
<Radio
|
||||
id="formularesponse"
|
||||
@@ -1749,6 +1584,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="problemwithhint"
|
||||
>
|
||||
<Radio
|
||||
id="problemwithhint"
|
||||
@@ -1759,7 +1595,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-problemwithhint"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -1806,7 +1644,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</Col>
|
||||
`;
|
||||
|
||||
exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problemType is problem_with_hint 1`] = `
|
||||
exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problemType is problemwithhint 1`] = `
|
||||
<Col
|
||||
className="justify-content-center"
|
||||
md={8}
|
||||
@@ -1819,6 +1657,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
className="border-primary-100 border-bottom py-3 pl-2.5 pr-4"
|
||||
>
|
||||
<IconButton
|
||||
alt="Go back"
|
||||
iconAs="Icon"
|
||||
onClick={[Function]}
|
||||
/>
|
||||
@@ -1838,10 +1677,11 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
className="px-4"
|
||||
name="advanceTypes"
|
||||
onChange={[Function]}
|
||||
value="problem_with_hint"
|
||||
value="problemwithhint"
|
||||
>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="blankadvanced"
|
||||
>
|
||||
<Radio
|
||||
id="blankadvanced"
|
||||
@@ -1853,6 +1693,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="circuitschematic"
|
||||
>
|
||||
<Radio
|
||||
id="circuitschematic"
|
||||
@@ -1863,7 +1704,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-circuitschematic"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -1897,6 +1740,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="jsinputresponse"
|
||||
>
|
||||
<Radio
|
||||
id="jsinputresponse"
|
||||
@@ -1908,6 +1752,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="customgrader"
|
||||
>
|
||||
<Radio
|
||||
id="customgrader"
|
||||
@@ -1918,7 +1763,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-customgrader"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -1952,6 +1799,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="imageresponse"
|
||||
>
|
||||
<Radio
|
||||
id="imageresponse"
|
||||
@@ -1962,7 +1810,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-imageresponse"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -1996,6 +1846,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="formularesponse"
|
||||
>
|
||||
<Radio
|
||||
id="formularesponse"
|
||||
@@ -2007,6 +1858,7 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
</ActionRow>
|
||||
<ActionRow
|
||||
className="border-primary-100 border-bottom m-0 py-3 w-100"
|
||||
key="problemwithhint"
|
||||
>
|
||||
<Radio
|
||||
id="problemwithhint"
|
||||
@@ -2017,7 +1869,9 @@ exports[`AdvanceTypeSelect snapshots snapshots: renders as expected with problem
|
||||
<ActionRow.Spacer />
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
id="tooltip-adv-problemwithhint"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
@@ -11,18 +11,19 @@ exports[`ProblemTypeSelect snapshot DROPDOWN 1`] = `
|
||||
>
|
||||
<ForwardRef
|
||||
columns={1}
|
||||
name="problem-type"
|
||||
onChange={[Function]}
|
||||
type="radio"
|
||||
value="optionresponse"
|
||||
>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="multiplechoiceresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="multiplechoiceresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -31,13 +32,13 @@ exports[`ProblemTypeSelect snapshot DROPDOWN 1`] = `
|
||||
Single select
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="choiceresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="choiceresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -46,13 +47,13 @@ exports[`ProblemTypeSelect snapshot DROPDOWN 1`] = `
|
||||
Multi-select
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="optionresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="optionresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -61,13 +62,13 @@ exports[`ProblemTypeSelect snapshot DROPDOWN 1`] = `
|
||||
Dropdown
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="numericalresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="numericalresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -76,13 +77,13 @@ exports[`ProblemTypeSelect snapshot DROPDOWN 1`] = `
|
||||
Numerical input
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="stringresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="stringresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -116,18 +117,19 @@ exports[`ProblemTypeSelect snapshot MULTISELECT 1`] = `
|
||||
>
|
||||
<ForwardRef
|
||||
columns={1}
|
||||
name="problem-type"
|
||||
onChange={[Function]}
|
||||
type="radio"
|
||||
value="choiceresponse"
|
||||
>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="multiplechoiceresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="multiplechoiceresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -136,13 +138,13 @@ exports[`ProblemTypeSelect snapshot MULTISELECT 1`] = `
|
||||
Single select
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="choiceresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="choiceresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -151,13 +153,13 @@ exports[`ProblemTypeSelect snapshot MULTISELECT 1`] = `
|
||||
Multi-select
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="optionresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="optionresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -166,13 +168,13 @@ exports[`ProblemTypeSelect snapshot MULTISELECT 1`] = `
|
||||
Dropdown
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="numericalresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="numericalresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -181,13 +183,13 @@ exports[`ProblemTypeSelect snapshot MULTISELECT 1`] = `
|
||||
Numerical input
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="stringresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="stringresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -221,18 +223,19 @@ exports[`ProblemTypeSelect snapshot NUMERIC 1`] = `
|
||||
>
|
||||
<ForwardRef
|
||||
columns={1}
|
||||
name="problem-type"
|
||||
onChange={[Function]}
|
||||
type="radio"
|
||||
value="numericalresponse"
|
||||
>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="multiplechoiceresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="multiplechoiceresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -241,13 +244,13 @@ exports[`ProblemTypeSelect snapshot NUMERIC 1`] = `
|
||||
Single select
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="choiceresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="choiceresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -256,13 +259,13 @@ exports[`ProblemTypeSelect snapshot NUMERIC 1`] = `
|
||||
Multi-select
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="optionresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="optionresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -271,13 +274,13 @@ exports[`ProblemTypeSelect snapshot NUMERIC 1`] = `
|
||||
Dropdown
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="numericalresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="numericalresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -286,13 +289,13 @@ exports[`ProblemTypeSelect snapshot NUMERIC 1`] = `
|
||||
Numerical input
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="stringresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="stringresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -326,18 +329,19 @@ exports[`ProblemTypeSelect snapshot SINGLESELECT 1`] = `
|
||||
>
|
||||
<ForwardRef
|
||||
columns={1}
|
||||
name="problem-type"
|
||||
onChange={[Function]}
|
||||
type="radio"
|
||||
value="multiplechoiceresponse"
|
||||
>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="multiplechoiceresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="multiplechoiceresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -346,13 +350,13 @@ exports[`ProblemTypeSelect snapshot SINGLESELECT 1`] = `
|
||||
Single select
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="choiceresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="choiceresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -361,13 +365,13 @@ exports[`ProblemTypeSelect snapshot SINGLESELECT 1`] = `
|
||||
Multi-select
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="optionresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="optionresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -376,13 +380,13 @@ exports[`ProblemTypeSelect snapshot SINGLESELECT 1`] = `
|
||||
Dropdown
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="numericalresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="numericalresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -391,13 +395,13 @@ exports[`ProblemTypeSelect snapshot SINGLESELECT 1`] = `
|
||||
Numerical input
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="stringresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="stringresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -431,18 +435,19 @@ exports[`ProblemTypeSelect snapshot TEXTINPUT 1`] = `
|
||||
>
|
||||
<ForwardRef
|
||||
columns={1}
|
||||
name="problem-type"
|
||||
onChange={[Function]}
|
||||
type="radio"
|
||||
value="stringresponse"
|
||||
>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="multiplechoiceresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="multiplechoiceresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -451,13 +456,13 @@ exports[`ProblemTypeSelect snapshot TEXTINPUT 1`] = `
|
||||
Single select
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="choiceresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="choiceresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -466,13 +471,13 @@ exports[`ProblemTypeSelect snapshot TEXTINPUT 1`] = `
|
||||
Multi-select
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="optionresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="optionresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -481,13 +486,13 @@ exports[`ProblemTypeSelect snapshot TEXTINPUT 1`] = `
|
||||
Dropdown
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="numericalresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="numericalresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -496,13 +501,13 @@ exports[`ProblemTypeSelect snapshot TEXTINPUT 1`] = `
|
||||
Numerical input
|
||||
</ForwardRef>
|
||||
<ForwardRef
|
||||
aria-label="checkbox"
|
||||
checked={false}
|
||||
className="border border-light-400 text-primary-500 shadow-none"
|
||||
id="stringresponse"
|
||||
inputHidden={true}
|
||||
isIndeterminate={false}
|
||||
isInvalid={false}
|
||||
key="stringresponse"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
@@ -12,6 +12,11 @@ const messages = defineMessages({
|
||||
defaultMessage: 'Advanced problems',
|
||||
description: 'Title for advanced problem menu',
|
||||
},
|
||||
advanceMenuGoBack: {
|
||||
id: 'authoring.problemEditor.advanceProblem.menu.goBack',
|
||||
defaultMessage: 'Go back',
|
||||
description: 'Return to the previous menu that shows basic problem types',
|
||||
},
|
||||
advanceProblemTypeLabel: {
|
||||
id: 'authoring.problemEditor.advanceProblem.problemType.label',
|
||||
defaultMessage: '{problemType}',
|
||||
@@ -1,28 +1,10 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import {
|
||||
AdvanceProblemKeys, AdvanceProblems, ProblemTypeKeys, ProblemTypes,
|
||||
} from '../../../../data/constants/problem';
|
||||
import { StrictDict, snakeCaseKeys } from '../../../../utils';
|
||||
// This 'module' self-import hack enables mocking during tests.
|
||||
// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
|
||||
// should be re-thought and cleaned up to avoid this pattern.
|
||||
// eslint-disable-next-line import/no-self-import
|
||||
import * as module from './hooks';
|
||||
import { snakeCaseKeys } from '../../../../utils';
|
||||
import { getDataFromOlx } from '../../../../data/redux/thunkActions/problem';
|
||||
|
||||
export const state = StrictDict({
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
selected: (val) => useState(val),
|
||||
});
|
||||
|
||||
export const selectHooks = () => {
|
||||
const [selected, setSelected] = module.state.selected(ProblemTypeKeys.SINGLESELECT);
|
||||
return {
|
||||
selected,
|
||||
setSelected,
|
||||
};
|
||||
};
|
||||
|
||||
export const onSelect = ({
|
||||
selected,
|
||||
updateField,
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
/* eslint-disable prefer-destructuring */
|
||||
import React from 'react';
|
||||
import { MockUseState } from '../../../../testUtils';
|
||||
// This 'module' self-import hack enables mocking during tests.
|
||||
// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
|
||||
// should be re-thought and cleaned up to avoid this pattern.
|
||||
// eslint-disable-next-line import/no-self-import
|
||||
import * as module from './hooks';
|
||||
import * as hooks from './hooks';
|
||||
import { AdvanceProblems, ProblemTypeKeys, ProblemTypes } from '../../../../data/constants/problem';
|
||||
import { getDataFromOlx } from '../../../../data/redux/thunkActions/problem';
|
||||
|
||||
@@ -15,7 +10,6 @@ jest.mock('react', () => ({
|
||||
useEffect: jest.fn(),
|
||||
}));
|
||||
|
||||
const state = new MockUseState(module);
|
||||
const mockUpdateField = jest.fn().mockName('updateField');
|
||||
const mockSelected = 'multiplechoiceresponse';
|
||||
const mockAdvancedSelected = 'circuitschematic';
|
||||
@@ -28,35 +22,14 @@ const mockDefaultSettings = {
|
||||
showanswer: 'always',
|
||||
};
|
||||
|
||||
let hook;
|
||||
|
||||
describe('SelectTypeModal hooks', () => {
|
||||
beforeEach(() => {
|
||||
state.mock();
|
||||
});
|
||||
afterEach(() => {
|
||||
state.restore();
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('selectHooks', () => {
|
||||
beforeEach(() => {
|
||||
hook = module.selectHooks();
|
||||
});
|
||||
test('selected defaults to SINGLESELECT', () => {
|
||||
expect(hook.selected).toEqual(ProblemTypeKeys.SINGLESELECT);
|
||||
});
|
||||
test('setSelected sets state as expected', () => {
|
||||
const expectedArg = 'neWvAl';
|
||||
state.mockVal(state.keys.selected, 'mOcKvAl');
|
||||
hook.setSelected(expectedArg);
|
||||
expect(state.setState.selected).toHaveBeenCalledWith(expectedArg);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onSelect', () => {
|
||||
test('updateField is called with selected templated if selected is an Advanced Problem', () => {
|
||||
module.onSelect({
|
||||
hooks.onSelect({
|
||||
selected: mockAdvancedSelected,
|
||||
updateField: mockUpdateField,
|
||||
setBlockTitle: mocksetBlockTitle,
|
||||
@@ -68,7 +41,7 @@ describe('SelectTypeModal hooks', () => {
|
||||
expect(mocksetBlockTitle).toHaveBeenCalledWith(AdvanceProblems[mockAdvancedSelected].title);
|
||||
});
|
||||
test('updateField is called with selected on visual propblems', () => {
|
||||
module.onSelect({
|
||||
hooks.onSelect({
|
||||
selected: mockSelected,
|
||||
updateField: mockUpdateField,
|
||||
setBlockTitle: mocksetBlockTitle,
|
||||
@@ -106,7 +79,7 @@ describe('SelectTypeModal hooks', () => {
|
||||
|
||||
describe('SINGLESELECT', () => {
|
||||
beforeEach(() => {
|
||||
module.useArrowNav(ProblemTypeKeys.SINGLESELECT, mockSetSelected);
|
||||
hooks.useArrowNav(ProblemTypeKeys.SINGLESELECT, mockSetSelected);
|
||||
[cb, prereqs] = React.useEffect.mock.calls[0];
|
||||
cb();
|
||||
});
|
||||
@@ -125,7 +98,7 @@ describe('SelectTypeModal hooks', () => {
|
||||
});
|
||||
describe('MULTISELECT', () => {
|
||||
beforeEach(() => {
|
||||
module.useArrowNav(ProblemTypeKeys.MULTISELECT, mockSetSelected);
|
||||
hooks.useArrowNav(ProblemTypeKeys.MULTISELECT, mockSetSelected);
|
||||
[cb, prereqs] = React.useEffect.mock.calls[0];
|
||||
cb();
|
||||
});
|
||||
@@ -144,7 +117,7 @@ describe('SelectTypeModal hooks', () => {
|
||||
});
|
||||
describe('DROPDOWN', () => {
|
||||
beforeEach(() => {
|
||||
module.useArrowNav(ProblemTypeKeys.DROPDOWN, mockSetSelected);
|
||||
hooks.useArrowNav(ProblemTypeKeys.DROPDOWN, mockSetSelected);
|
||||
[cb, prereqs] = React.useEffect.mock.calls[0];
|
||||
cb();
|
||||
});
|
||||
@@ -163,7 +136,7 @@ describe('SelectTypeModal hooks', () => {
|
||||
});
|
||||
describe('NUMERIC', () => {
|
||||
beforeEach(() => {
|
||||
module.useArrowNav(ProblemTypeKeys.NUMERIC, mockSetSelected);
|
||||
hooks.useArrowNav(ProblemTypeKeys.NUMERIC, mockSetSelected);
|
||||
[cb, prereqs] = React.useEffect.mock.calls[0];
|
||||
cb();
|
||||
});
|
||||
@@ -182,7 +155,7 @@ describe('SelectTypeModal hooks', () => {
|
||||
});
|
||||
describe('TEXTINPUT', () => {
|
||||
beforeEach(() => {
|
||||
module.useArrowNav(ProblemTypeKeys.TEXTINPUT, mockSetSelected);
|
||||
hooks.useArrowNav(ProblemTypeKeys.TEXTINPUT, mockSetSelected);
|
||||
[cb, prereqs] = React.useEffect.mock.calls[0];
|
||||
cb();
|
||||
});
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import 'CourseAuthoring/editors/setupEditorTest';
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
import SelectTypeModal from '.';
|
||||
|
||||
jest.mock('./hooks', () => ({
|
||||
selectHooks: jest.fn(() => ({
|
||||
selected: 'mOcKsELEcted',
|
||||
setSelected: jest.fn().mockName('setSelected'),
|
||||
})),
|
||||
useArrowNav: jest.fn().mockName('useArrowNav'),
|
||||
}));
|
||||
|
||||
describe('SelectTypeModal', () => {
|
||||
const props = {
|
||||
onClose: jest.fn(),
|
||||
};
|
||||
|
||||
test('snapshot', () => {
|
||||
expect(shallow(<SelectTypeModal {...props} />).snapshot).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,47 @@
|
||||
import { Provider } from 'react-redux';
|
||||
import {
|
||||
fireEvent,
|
||||
render,
|
||||
screen,
|
||||
initializeMocks,
|
||||
} from '../../../../../testUtils';
|
||||
import editorStore from '../../../../data/store';
|
||||
import * as hooks from './hooks';
|
||||
import SelectTypeModal from '.';
|
||||
|
||||
describe('SelectTypeModal', () => {
|
||||
beforeEach(() => {
|
||||
initializeMocks();
|
||||
});
|
||||
test('it can select a basic problem type', async () => {
|
||||
const mockClose = jest.fn();
|
||||
const mockSelect = jest.fn();
|
||||
jest.spyOn(hooks, 'onSelect').mockImplementation(mockSelect);
|
||||
// This is a new-style test, unlike most of the old snapshot-based editor tests.
|
||||
render(<Provider store={editorStore}><SelectTypeModal onClose={mockClose} /></Provider>);
|
||||
|
||||
// First we see the menu of problem types:
|
||||
expect(await screen.findByRole('button', { name: 'Numerical input' })).toBeInTheDocument();
|
||||
// And the "Advanced" types are not yet listed:
|
||||
expect(screen.queryByRole('radio', { name: 'Custom JavaScript display and grading' })).not.toBeInTheDocument();
|
||||
|
||||
// Before we select a problem type, try viewing the advanced types and then going back:
|
||||
const advancedButton = await screen.findByRole('button', { name: 'Advanced problem types' });
|
||||
fireEvent.click(advancedButton);
|
||||
|
||||
// Now we see the advanced types:
|
||||
await screen.findByRole('radio', { name: 'Custom JavaScript display and grading' });
|
||||
expect(screen.queryByRole('button', { name: 'Numerical input' })).not.toBeInTheDocument();
|
||||
|
||||
const goBackButton = screen.getByRole('button', { name: 'Go back' });
|
||||
fireEvent.click(goBackButton);
|
||||
|
||||
const numericalInputBtn = await screen.findByRole('button', { name: 'Numerical input' });
|
||||
fireEvent.click(numericalInputBtn);
|
||||
|
||||
// Now we save our selection:
|
||||
const selectBtn = screen.getByRole('button', { name: 'Select' });
|
||||
fireEvent.click(selectBtn);
|
||||
expect(mockSelect).toHaveBeenLastCalledWith(expect.objectContaining({ selected: 'numericalresponse' }));
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,4 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { Row, Stack } from '@openedx/paragon';
|
||||
import ProblemTypeSelect from './content/ProblemTypeSelect';
|
||||
@@ -7,18 +6,27 @@ import Preview from './content/Preview';
|
||||
import AdvanceTypeSelect from './content/AdvanceTypeSelect';
|
||||
import SelectTypeWrapper from './SelectTypeWrapper';
|
||||
import * as hooks from './hooks';
|
||||
import { AdvanceProblemKeys } from '../../../../data/constants/problem';
|
||||
import {
|
||||
AdvancedProblemType,
|
||||
isAdvancedProblemType,
|
||||
ProblemType,
|
||||
ProblemTypeKeys,
|
||||
} from '../../../../data/constants/problem';
|
||||
|
||||
const SelectTypeModal = ({
|
||||
interface Props {
|
||||
onClose: (() => void) | null;
|
||||
}
|
||||
|
||||
const SelectTypeModal: React.FC<Props> = ({
|
||||
onClose,
|
||||
}) => {
|
||||
const { selected, setSelected } = hooks.selectHooks();
|
||||
const [selected, setSelected] = React.useState<ProblemType | AdvancedProblemType>(ProblemTypeKeys.SINGLESELECT);
|
||||
hooks.useArrowNav(selected, setSelected);
|
||||
|
||||
return (
|
||||
<SelectTypeWrapper onClose={onClose} selected={selected}>
|
||||
<Row className="justify-content-center">
|
||||
{(!Object.values(AdvanceProblemKeys).includes(selected)) ? (
|
||||
{(!isAdvancedProblemType(selected)) ? (
|
||||
<Stack direction="horizontal" gap={4} className="flex-wrap mb-6">
|
||||
<ProblemTypeSelect selected={selected} setSelected={setSelected} />
|
||||
<Preview problemType={selected} />
|
||||
@@ -29,8 +37,4 @@ const SelectTypeModal = ({
|
||||
);
|
||||
};
|
||||
|
||||
SelectTypeModal.propTypes = {
|
||||
onClose: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default SelectTypeModal;
|
||||
@@ -65,7 +65,6 @@ describe('ProblemEditor', () => {
|
||||
const wrapper = shallow(<ProblemEditor
|
||||
{...props}
|
||||
blockFinished
|
||||
studioViewFinished
|
||||
advancedSettingsFinished
|
||||
blockFailed
|
||||
/>);
|
||||
@@ -75,7 +74,6 @@ describe('ProblemEditor', () => {
|
||||
const wrapper = shallow(<ProblemEditor
|
||||
{...props}
|
||||
blockFinished
|
||||
studioViewFinished
|
||||
advancedSettingsFinished
|
||||
/>);
|
||||
expect(wrapper.instance.findByType('SelectTypeModal')).toHaveLength(1);
|
||||
@@ -85,7 +83,6 @@ describe('ProblemEditor', () => {
|
||||
{...props}
|
||||
problemType="multiplechoiceresponse"
|
||||
blockFinished
|
||||
studioViewFinished
|
||||
advancedSettingsFinished
|
||||
/>);
|
||||
expect(wrapper.instance.findByType('EditProblemView')).toHaveLength(1);
|
||||
@@ -1,17 +1,29 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Spinner } from '@openedx/paragon';
|
||||
import { injectIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
import SelectTypeModal from './components/SelectTypeModal';
|
||||
import EditProblemView from './components/EditProblemView';
|
||||
import { selectors, thunkActions } from '../../data/redux';
|
||||
import { RequestKeys } from '../../data/constants/requests';
|
||||
import messages from './messages';
|
||||
import { ProblemType } from '../../data/constants/problem';
|
||||
import type { EditorComponent } from '../../EditorComponent';
|
||||
|
||||
const ProblemEditor = ({
|
||||
export interface Props extends EditorComponent {
|
||||
// redux
|
||||
advancedSettingsFinished: boolean;
|
||||
blockFinished: boolean;
|
||||
blockFailed: boolean;
|
||||
/** null if this is a new problem */
|
||||
problemType: ProblemType | null;
|
||||
initializeProblemEditor: (blockValue: any) => void;
|
||||
blockValue: Record<string, any>;
|
||||
}
|
||||
|
||||
const ProblemEditor: React.FC<Props> = ({
|
||||
onClose,
|
||||
returnFunction,
|
||||
returnFunction = null,
|
||||
// Redux
|
||||
problemType,
|
||||
blockFinished,
|
||||
@@ -52,21 +64,6 @@ const ProblemEditor = ({
|
||||
return (<EditProblemView {...{ onClose, returnFunction }} />);
|
||||
};
|
||||
|
||||
ProblemEditor.defaultProps = {
|
||||
returnFunction: null,
|
||||
};
|
||||
ProblemEditor.propTypes = {
|
||||
onClose: PropTypes.func.isRequired,
|
||||
returnFunction: PropTypes.func,
|
||||
// redux
|
||||
advancedSettingsFinished: PropTypes.bool.isRequired,
|
||||
blockFinished: PropTypes.bool.isRequired,
|
||||
blockFailed: PropTypes.bool.isRequired,
|
||||
problemType: PropTypes.string.isRequired,
|
||||
initializeProblemEditor: PropTypes.func.isRequired,
|
||||
blockValue: PropTypes.objectOf(PropTypes.shape({})).isRequired,
|
||||
};
|
||||
|
||||
export const mapStateToProps = (state) => ({
|
||||
blockFinished: selectors.requests.isFinished(state, { requestKey: RequestKeys.fetchBlock }),
|
||||
blockFailed: selectors.requests.isFailed(state, { requestKey: RequestKeys.fetchBlock }),
|
||||
@@ -80,4 +77,4 @@ export const mapDispatchToProps = {
|
||||
};
|
||||
|
||||
export const ProblemEditorInternal = ProblemEditor; // For testing only
|
||||
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ProblemEditor));
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ProblemEditor);
|
||||
@@ -14,7 +14,8 @@ export const ProblemTypeKeys = StrictDict({
|
||||
NUMERIC: 'numericalresponse',
|
||||
TEXTINPUT: 'stringresponse',
|
||||
ADVANCED: 'advanced',
|
||||
});
|
||||
} as const);
|
||||
export type ProblemType = typeof ProblemTypeKeys[keyof typeof ProblemTypeKeys];
|
||||
|
||||
export const ProblemTypes = StrictDict({
|
||||
[ProblemTypeKeys.SINGLESELECT]: {
|
||||
@@ -84,7 +85,12 @@ export const AdvanceProblemKeys = StrictDict({
|
||||
IMAGE: 'imageresponse',
|
||||
FORMULA: 'formularesponse',
|
||||
PROBLEMWITHHINT: 'problemwithhint',
|
||||
});
|
||||
} as const);
|
||||
export type AdvancedProblemType = typeof AdvanceProblemKeys[keyof typeof AdvanceProblemKeys];
|
||||
|
||||
export function isAdvancedProblemType(pt: ProblemType | AdvancedProblemType): pt is AdvancedProblemType {
|
||||
return Object.values(AdvanceProblemKeys).includes(pt as any);
|
||||
}
|
||||
|
||||
export const AdvanceProblems = StrictDict({
|
||||
[AdvanceProblemKeys.BLANK]: {
|
||||
@@ -122,7 +128,7 @@ export const AdvanceProblems = StrictDict({
|
||||
status: 'Not supported',
|
||||
template: advancedOlxTemplates.problemWithHint,
|
||||
},
|
||||
});
|
||||
} as const);
|
||||
|
||||
export const ShowAnswerTypesKeys = StrictDict({
|
||||
ALWAYS: 'always',
|
||||
@@ -137,7 +143,7 @@ export const ShowAnswerTypesKeys = StrictDict({
|
||||
AFTER_ALL_ATTEMPTS: 'after_all_attempts',
|
||||
AFTER_ALL_ATTEMPTS_OR_CORRECT: 'after_all_attempts_or_correct',
|
||||
ATTEMPTED_NO_PAST_DUE: 'attempted_no_past_due',
|
||||
});
|
||||
} as const);
|
||||
|
||||
export const ShowAnswerTypes = StrictDict({
|
||||
[ShowAnswerTypesKeys.ALWAYS]: {
|
||||
@@ -188,14 +194,14 @@ export const ShowAnswerTypes = StrictDict({
|
||||
id: 'authoring.problemeditor.settings.showanswertype.attempted_no_past_due',
|
||||
defaultMessage: 'Attempted',
|
||||
},
|
||||
});
|
||||
} as const);
|
||||
|
||||
export const RandomizationTypesKeys = StrictDict({
|
||||
NEVER: 'never',
|
||||
ALWAYS: 'always',
|
||||
ONRESET: 'onreset',
|
||||
PERSTUDENT: 'per_student',
|
||||
});
|
||||
} as const);
|
||||
|
||||
export const RandomizationTypes = StrictDict({
|
||||
[RandomizationTypesKeys.ALWAYS]: {
|
||||
@@ -214,9 +220,9 @@ export const RandomizationTypes = StrictDict({
|
||||
id: 'authoring.problemeditor.settings.RandomizationTypes.perstudent',
|
||||
defaultMessage: 'Per Student',
|
||||
},
|
||||
});
|
||||
} as const);
|
||||
|
||||
export const RichTextProblems = [ProblemTypeKeys.SINGLESELECT, ProblemTypeKeys.MULTISELECT];
|
||||
export const RichTextProblems = [ProblemTypeKeys.SINGLESELECT, ProblemTypeKeys.MULTISELECT] as const;
|
||||
|
||||
export const settingsOlxAttributes = [
|
||||
'@_display_name',
|
||||
@@ -226,4 +232,4 @@ export const settingsOlxAttributes = [
|
||||
'@_show_reset_button',
|
||||
'@_submission_wait_seconds',
|
||||
'@_attempts_before_showanswer_button',
|
||||
];
|
||||
] as const;
|
||||
@@ -20,7 +20,7 @@ const modules = {
|
||||
|
||||
const moduleProps = (propName) => Object.keys(modules).reduce(
|
||||
(obj, moduleKey) => ({ ...obj, [moduleKey]: modules[moduleKey][propName] }),
|
||||
{},
|
||||
/** @type {Record<string, any>} */({}),
|
||||
);
|
||||
|
||||
const rootReducer = combineReducers(moduleProps('reducer'));
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
// These additional mocks and setup are required for some tests in src/editors/
|
||||
// and are imported on an as-needed basis.
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// TODO: tests using this 'setupEditorTest', shallow rendering, and snapshots
|
||||
// should be replaced with modern tests that use src/testUtils.ts and
|
||||
// @testing-library/react. See
|
||||
// src/editors/containers/ProblemEditor/components/SelectTypeModal/index.test.tsx
|
||||
// for an example of an editor test in the new format.
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
import { formatMessage as mockFormatMessage } from './testUtils';
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import 'jest-canvas-mock';
|
||||
|
||||
@@ -8,7 +18,7 @@ jest.mock('@edx/frontend-platform/i18n', () => {
|
||||
const PropTypes = jest.requireActual('prop-types');
|
||||
return {
|
||||
...i18n,
|
||||
useIntl: () => ({ formatMessage: (m) => m.defaultMessage }),
|
||||
useIntl: () => ({ formatMessage: mockFormatMessage }),
|
||||
intlShape: PropTypes.shape({
|
||||
formatMessage: PropTypes.func,
|
||||
}),
|
||||
|
||||
@@ -15,6 +15,6 @@ const supportedEditors = {
|
||||
[blockTypes.video_upload]: VideoUploadEditor,
|
||||
// ADDED_EDITORS GO BELOW
|
||||
[blockTypes.game]: GameEditor,
|
||||
};
|
||||
} as const;
|
||||
|
||||
export default supportedEditors;
|
||||
@@ -19,6 +19,6 @@ const strictGet = (target, name) => {
|
||||
return undefined;
|
||||
};
|
||||
|
||||
const StrictDict = (dict) => new Proxy(dict, { get: strictGet });
|
||||
const StrictDict = <T extends Record<string, any>>(dict: T) => new Proxy(dict, { get: strictGet }) as T;
|
||||
|
||||
export default StrictDict;
|
||||
@@ -7,6 +7,7 @@
|
||||
import React from 'react';
|
||||
import { AxiosError } from 'axios';
|
||||
import { jest } from '@jest/globals';
|
||||
import type { Store } from 'redux';
|
||||
import { initializeMockApp } from '@edx/frontend-platform';
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
@@ -25,7 +26,7 @@ import { ToastContext, type ToastContextData } from './generic/toast-context';
|
||||
import initializeReduxStore from './store';
|
||||
|
||||
/** @deprecated Use React Query and/or regular React Context instead of redux */
|
||||
let reduxStore;
|
||||
let reduxStore: Store;
|
||||
let queryClient;
|
||||
let axiosMock: MockAdapter;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user