test: replacing snapshot tests with RTL tests part 10 (#2207)

This commit is contained in:
jacobo-dominguez-wgu
2025-06-24 03:50:54 -06:00
committed by GitHub
parent 810dd420fd
commit 085cd7d05c
18 changed files with 300 additions and 1012 deletions

View File

@@ -1,32 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`TitleHeader snapshots editing 1`] = `
<EditableHeader
handleChange={[MockFunction localTitleHooks.handleChange]}
handleKeyDown={[MockFunction localTitleHooks.handleKeyDown]}
inputRef={[MockFunction localTitleHooks.inputRef]}
localTitle="TeST LocALtitLE"
updateTitle={[MockFunction localTitleHooks.updateTitle]}
/>
`;
exports[`TitleHeader snapshots initialized 1`] = `
<div
className="d-flex flex-row align-items-center mt-1"
>
<Truncate.Deprecated>
{
"useSelector": [Function],
}
</Truncate.Deprecated>
<IconButton
alt="Edit Title"
className="mx-2"
iconAs="Icon"
onClick={[MockFunction localTitleHooks.startEditing]}
size="sm"
/>
</div>
`;
exports[`TitleHeader snapshots not initialized 1`] = `"Loading..."`;

View File

@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import { Icon, IconButton, Truncate } from '@openedx/paragon';
import { EditOutline } from '@openedx/paragon/icons';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
import { selectors } from '../../../../data/redux';
import { localTitleHooks } from './hooks';
@@ -13,10 +13,9 @@ import EditableHeader from './EditableHeader';
const TitleHeader = ({
isInitialized,
// injected
intl,
}) => {
if (!isInitialized) { return intl.formatMessage(messages.loading); }
const intl = useIntl();
if (!isInitialized) { return <FormattedMessage {...messages.loading} />; }
// eslint-disable-next-line react-hooks/rules-of-hooks
const dispatch = useDispatch();
// eslint-disable-next-line react-hooks/rules-of-hooks
@@ -66,9 +65,6 @@ const TitleHeader = ({
TitleHeader.defaultProps = {};
TitleHeader.propTypes = {
isInitialized: PropTypes.bool.isRequired,
// injected
intl: intlShape.isRequired,
};
export const TitleHeaderInternal = TitleHeader; // For testing only
export default injectIntl(TitleHeader);
export default TitleHeader;

View File

@@ -1,62 +0,0 @@
import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { useDispatch } from 'react-redux';
import { shallow } from '@edx/react-unit-test-utils';
import { formatMessage } from '../../../../testUtils';
import { localTitleHooks } from './hooks';
import { TitleHeaderInternal as TitleHeader } from '.';
jest.mock('./hooks', () => ({
localTitleHooks: jest.fn(),
}));
jest.mock('@openedx/paragon', () => ({
...jest.requireActual('@openedx/paragon'),
Truncate: ({ children }) => <div>{children}</div>, // eslint-disable-line react/prop-types
IconButton: 'IconButton',
Icon: 'Icon',
}));
jest.mock('./EditableHeader');
describe('TitleHeader', () => {
const props = {
intl: { formatMessage },
isInitialized: false,
setTitle: jest.fn().mockName('args.setTitle'),
title: 'html',
};
const localTitleHooksProps = {
inputRef: jest.fn().mockName('localTitleHooks.inputRef'),
isEditing: false,
handleChange: jest.fn().mockName('localTitleHooks.handleChange'),
handleKeyDown: jest.fn().mockName('localTitleHooks.handleKeyDown'),
localTitle: 'TeST LocALtitLE',
startEditing: jest.fn().mockName('localTitleHooks.startEditing'),
updateTitle: jest.fn().mockName('localTitleHooks.updateTitle'),
};
describe('behavior', () => {
it(' calls localTitleHooks with initialization args', () => {
localTitleHooks.mockReturnValue(localTitleHooksProps);
shallow(<TitleHeader {...props} isInitialized />);
const dispatch = useDispatch();
expect(localTitleHooks).toHaveBeenCalledWith({
dispatch,
});
});
});
describe('snapshots', () => {
test('not initialized', () => {
expect(shallow(<TitleHeader {...props} />).snapshot).toMatchSnapshot();
});
test('initialized', () => {
localTitleHooks.mockReturnValue(localTitleHooksProps);
expect(shallow(<TitleHeader {...props} isInitialized />).shallowWrapper).toMatchSnapshot();
});
test('editing', () => {
localTitleHooks.mockReturnValue({ ...localTitleHooksProps, isEditing: true });
expect(shallow(<TitleHeader {...props} isInitialized />).snapshot).toMatchSnapshot();
});
});
});

View File

@@ -0,0 +1,63 @@
import React from 'react';
import {
render, screen, initializeMocks,
} from '@src/testUtils';
import * as redux from 'react-redux';
import * as hooks from './hooks';
import TitleHeader from '.';
describe('TitleHeader', () => {
// setting any type to prevent warnings on the mockReturnValue
const localTitleHooksProps: any = {
inputRef: jest.fn().mockName('localTitleHooks.inputRef'),
isEditing: false,
handleChange: jest.fn().mockName('localTitleHooks.handleChange'),
handleKeyDown: jest.fn().mockName('localTitleHooks.handleKeyDown'),
localTitle: 'TeST LocALtitLE',
startEditing: jest.fn().mockName('localTitleHooks.startEditing'),
updateTitle: jest.fn().mockName('localTitleHooks.updateTitle'),
};
beforeEach(() => {
initializeMocks();
jest.spyOn(hooks, 'localTitleHooks').mockReturnValue(localTitleHooksProps);
jest.spyOn(redux, 'useSelector').mockReturnValueOnce('Title mock');
});
const props = {
isInitialized: true,
};
describe('behavior', () => {
it('calls localTitleHooks with initialization args', () => {
const mockDispatch = jest.fn();
jest.spyOn(redux, 'useDispatch').mockReturnValueOnce(mockDispatch);
render(<TitleHeader {...props} />);
expect(screen.getByText('Title mock')).toBeInTheDocument();
expect(hooks.localTitleHooks).toHaveBeenCalledWith({ dispatch: mockDispatch });
});
});
describe('renders', () => {
test('component is not initialized and renders loading text', () => {
render(<TitleHeader isInitialized={false} />);
expect(screen.getByText('Loading...')).toBeInTheDocument();
});
test('renders component correctly when initialized is true', () => {
render(<TitleHeader {...props} />);
expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
expect(screen.getByText('Title mock')).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Edit Title' })).toBeInTheDocument();
});
test('renders editing component', () => {
jest.spyOn(hooks, 'localTitleHooks').mockReturnValue({ ...localTitleHooksProps, isEditing: true });
render(<TitleHeader {...props} />);
const editable = screen.getByRole('textbox');
expect(editable).toBeInTheDocument();
expect(editable).toHaveDisplayValue('TeST LocALtitLE');
});
});
});

View File

@@ -1,171 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`HintsCard snapshot snapshot: renders groupFeedbacks setting card multiple groupFeedbacks 1`] = `
<SettingsOption
className=""
extraSections={[]}
hasExpandableTextArea={true}
none={false}
summary=""
title="Group Feedback"
>
<div
className="pb-3"
>
<FormattedMessage
defaultMessage="Group feedback will appear when a student selects a specific set of answers."
description="label for group feedback input"
id="authoring.problemeditor.settings.GroupFeedbackInputLabel"
/>
</div>
<GroupFeedbackRow
answers={
[
"A",
"B",
"C",
]
}
id={1}
key="1"
props="propsValue"
value={
{
"answers": [
"A",
"C",
],
"feedback": "sOmE FeEDBACK",
"id": 1,
"value": "groupFeedback1",
}
}
/>
<GroupFeedbackRow
answers={
[
"A",
"B",
"C",
]
}
id={2}
key="2"
props="propsValue"
value={
{
"answers": [
"A",
],
"feedback": "sOmE FeEDBACK oTher FeEdback",
"id": 2,
"value": "",
}
}
/>
<Button
className="m-0 p-0 font-weight-bold"
onClick={[MockFunction groupFeedbacksCardHooks.handleAdd]}
size="sm"
text={null}
variant="add"
>
<FormattedMessage
defaultMessage="Add group feedback"
description="addGroupFeedbackButtonText"
id="authoring.problemeditor.settings.addGroupFeedbackButtonText"
/>
</Button>
</SettingsOption>
`;
exports[`HintsCard snapshot snapshot: renders groupFeedbacks setting card no groupFeedbacks 1`] = `
<SettingsOption
className=""
extraSections={[]}
hasExpandableTextArea={true}
none={true}
summary="None"
title="Group Feedback"
>
<div
className="pb-3"
>
<FormattedMessage
defaultMessage="Group feedback will appear when a student selects a specific set of answers."
description="label for group feedback input"
id="authoring.problemeditor.settings.GroupFeedbackInputLabel"
/>
</div>
<Button
className="m-0 p-0 font-weight-bold"
onClick={[MockFunction groupFeedbacksCardHooks.handleAdd]}
size="sm"
text={null}
variant="add"
>
<FormattedMessage
defaultMessage="Add group feedback"
description="addGroupFeedbackButtonText"
id="authoring.problemeditor.settings.addGroupFeedbackButtonText"
/>
</Button>
</SettingsOption>
`;
exports[`HintsCard snapshot snapshot: renders groupFeedbacks setting card one groupFeedback 1`] = `
<SettingsOption
className=""
extraSections={[]}
hasExpandableTextArea={true}
none={false}
summary="groupFeedback1"
title="Group Feedback"
>
<div
className="pb-3"
>
<FormattedMessage
defaultMessage="Group feedback will appear when a student selects a specific set of answers."
description="label for group feedback input"
id="authoring.problemeditor.settings.GroupFeedbackInputLabel"
/>
</div>
<GroupFeedbackRow
answers={
[
"A",
"B",
"C",
]
}
id={1}
key="1"
props="propsValue"
value={
{
"answers": [
"A",
"C",
],
"feedback": "sOmE FeEDBACK",
"id": 1,
"value": "groupFeedback1",
}
}
/>
<Button
className="m-0 p-0 font-weight-bold"
onClick={[MockFunction groupFeedbacksCardHooks.handleAdd]}
size="sm"
text={null}
variant="add"
>
<FormattedMessage
defaultMessage="Add group feedback"
description="addGroupFeedbackButtonText"
id="authoring.problemeditor.settings.addGroupFeedbackButtonText"
/>
</Button>
</SettingsOption>
`;

View File

@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { injectIntl, FormattedMessage, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
import SettingsOption from '../../SettingsOption';
import messages from './messages';
import { groupFeedbackCardHooks, groupFeedbackRowHooks } from './hooks';
@@ -11,9 +11,8 @@ const GroupFeedbackCard = ({
groupFeedbacks,
updateSettings,
answers,
// inject
intl,
}) => {
const intl = useIntl();
const { summary, handleAdd } = groupFeedbackCardHooks(groupFeedbacks, updateSettings, answers);
return (
<SettingsOption
@@ -47,7 +46,6 @@ const GroupFeedbackCard = ({
};
GroupFeedbackCard.propTypes = {
intl: intlShape.isRequired,
groupFeedbacks: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.number.isRequired,
feedback: PropTypes.string.isRequired,
@@ -63,5 +61,4 @@ GroupFeedbackCard.propTypes = {
updateSettings: PropTypes.func.isRequired,
};
export const GroupFeedbackCardInternal = GroupFeedbackCard; // For testing only
export default injectIntl(GroupFeedbackCard);
export default GroupFeedbackCard;

View File

@@ -1,83 +0,0 @@
import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { formatMessage } from '../../../../../../../testUtils';
import { GroupFeedbackCardInternal as GroupFeedbackCard } from './index';
import { groupFeedbackRowHooks, groupFeedbackCardHooks } from './hooks';
import messages from './messages';
jest.mock('./hooks', () => ({
groupFeedbackCardHooks: jest.fn(),
groupFeedbackRowHooks: jest.fn(),
}));
describe('HintsCard', () => {
const answers = ['A', 'B', 'C'];
const groupFeedback1 = {
id: 1, value: 'groupFeedback1', answers: ['A', 'C'], feedback: 'sOmE FeEDBACK',
};
const groupFeedback2 = {
id: 2, value: '', answers: ['A'], feedback: 'sOmE FeEDBACK oTher FeEdback',
};
const groupFeedbacks0 = [];
const groupFeedbacks1 = [groupFeedback1];
const groupFeedbacks2 = [groupFeedback1, groupFeedback2];
const props = {
intl: { formatMessage },
groupFeedbacks: groupFeedbacks0,
updateSettings: jest.fn().mockName('args.updateSettings'),
answers,
};
const groupFeedbacksRowHooksProps = { props: 'propsValue' };
groupFeedbackRowHooks.mockReturnValue(groupFeedbacksRowHooksProps);
describe('behavior', () => {
it(' calls groupFeedbacksCardHooks when initialized', () => {
const groupFeedbacksCardHooksProps = {
summary: { message: messages.noGroupFeedbackSummary },
handleAdd: jest.fn().mockName('groupFeedbacksCardHooks.handleAdd'),
};
groupFeedbackCardHooks.mockReturnValue(groupFeedbacksCardHooksProps);
shallow(<GroupFeedbackCard {...props} />);
expect(groupFeedbackCardHooks).toHaveBeenCalledWith(groupFeedbacks0, props.updateSettings, answers);
});
});
describe('snapshot', () => {
test('snapshot: renders groupFeedbacks setting card no groupFeedbacks', () => {
const groupFeedbacksCardHooksProps = {
summary: { message: messages.noGroupFeedbackSummary, values: {} },
handleAdd: jest.fn().mockName('groupFeedbacksCardHooks.handleAdd'),
};
groupFeedbackCardHooks.mockReturnValue(groupFeedbacksCardHooksProps);
expect(shallow(<GroupFeedbackCard {...props} />).snapshot).toMatchSnapshot();
});
test('snapshot: renders groupFeedbacks setting card one groupFeedback', () => {
const groupFeedbacksCardHooksProps = {
summary: {
message: messages.groupFeedbackSummary,
values: { groupFeedback: groupFeedback1.value, count: 1 },
},
handleAdd: jest.fn().mockName('groupFeedbacksCardHooks.handleAdd'),
};
groupFeedbackCardHooks.mockReturnValue(groupFeedbacksCardHooksProps);
expect(shallow(<GroupFeedbackCard {...props} groupFeedbacks={groupFeedbacks1} />).snapshot).toMatchSnapshot();
});
test('snapshot: renders groupFeedbacks setting card multiple groupFeedbacks', () => {
const groupFeedbacksCardHooksProps = {
summary: {
message: messages.groupFeedbackSummary,
values: { groupFeedback: groupFeedback2.value, count: 2 },
},
handleAdd: jest.fn().mockName('groupFeedbacksCardHooks.handleAdd'),
};
groupFeedbackCardHooks.mockReturnValue(groupFeedbacksCardHooksProps);
expect(shallow(<GroupFeedbackCard {...props} groupFeedbacks={groupFeedbacks2} />).snapshot).toMatchSnapshot();
});
});
});

View File

@@ -0,0 +1,94 @@
import React from 'react';
import {
render, screen, initializeMocks, fireEvent,
} from '@src/testUtils';
import GroupFeedbackCard from './index';
import * as hooks from './hooks';
import messages from './messages';
jest.mock('./hooks', () => ({
groupFeedbackCardHooks: jest.fn(),
groupFeedbackRowHooks: jest.fn(),
}));
describe('HintsCard', () => {
const answers = ['A', 'B', 'C'];
const groupFeedback1 = {
id: 1, value: 'groupFeedback1', answers: ['A', 'C'], feedback: 'sOmE FeEDBACK',
};
const groupFeedback2 = {
id: 2, value: '', answers: ['A'], feedback: 'sOmE FeEDBACK oTher FeEdback',
};
const groupFeedbacks0 = [];
const groupFeedbacks1 = [groupFeedback1];
const groupFeedbacks2 = [groupFeedback1, groupFeedback2];
const props = {
groupFeedbacks: groupFeedbacks0,
updateSettings: jest.fn().mockName('args.updateSettings'),
answers,
};
beforeEach(() => initializeMocks());
describe('behavior', () => {
it(' calls groupFeedbacksCardHooks when initialized', () => {
const groupFeedbacksCardHooksProps = {
summary: { message: messages.noGroupFeedbackSummary },
handleAdd: jest.fn().mockName('groupFeedbacksCardHooks.handleAdd'),
};
jest.spyOn(hooks, 'groupFeedbackCardHooks').mockReturnValue(groupFeedbacksCardHooksProps);
render(<GroupFeedbackCard {...props} />);
expect(hooks.groupFeedbackCardHooks).toHaveBeenCalledWith(groupFeedbacks0, props.updateSettings, answers);
});
});
describe('snapshot', () => {
test('renders groupFeedbacks setting card no groupFeedbacks', () => {
const groupFeedbacksCardHooksProps = {
summary: { message: messages.noGroupFeedbackSummary, values: {} },
handleAdd: jest.fn().mockName('groupFeedbacksCardHooks.handleAdd'),
};
jest.spyOn(hooks, 'groupFeedbackCardHooks').mockReturnValue(groupFeedbacksCardHooksProps);
render(<GroupFeedbackCard {...props} />);
expect(screen.getByText('Group Feedback')).toBeInTheDocument();
expect(screen.queryByRole('textbox')).not.toBeInTheDocument();
});
test('renders groupFeedbacks setting card one groupFeedback', () => {
const groupFeedbacksCardHooksProps = {
summary: {
message: messages.groupFeedbackSummary,
values: { groupFeedback: groupFeedback1.value, count: 1 },
},
handleAdd: jest.fn().mockName('groupFeedbacksCardHooks.handleAdd'),
};
jest.spyOn(hooks, 'groupFeedbackCardHooks').mockReturnValue(groupFeedbacksCardHooksProps);
render(<GroupFeedbackCard {...props} groupFeedbacks={groupFeedbacks1} />);
const feedbackOption = screen.getByText('Group Feedback');
fireEvent.click(feedbackOption);
const groupsRendered = screen.queryAllByRole('textbox');
expect(groupsRendered).toHaveLength(1);
expect(groupsRendered[0]).toHaveValue('sOmE FeEDBACK');
});
test('renders groupFeedbacks setting card multiple groupFeedbacks', () => {
const groupFeedbacksCardHooksProps = {
summary: {
message: messages.groupFeedbackSummary,
values: { groupFeedback: groupFeedback2.value, count: 2 },
},
handleAdd: jest.fn().mockName('groupFeedbacksCardHooks.handleAdd'),
};
jest.spyOn(hooks, 'groupFeedbackCardHooks').mockReturnValue(groupFeedbacksCardHooksProps);
render(<GroupFeedbackCard {...props} groupFeedbacks={groupFeedbacks2} />);
const feedbackOption = screen.getByText('Group Feedback');
fireEvent.click(feedbackOption);
const groupsRendered = screen.queryAllByRole('textbox');
expect(groupsRendered).toHaveLength(groupFeedbacks2.length);
groupFeedbacks2.forEach((group, index) => {
expect(groupsRendered[index]).toHaveValue(group.feedback);
});
});
});
});

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import { Button, ButtonGroup, Hyperlink } from '@openedx/paragon';
import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';
@@ -12,9 +12,8 @@ const ResetCard = ({
showResetButton,
defaultValue,
updateSettings,
// inject
intl,
}) => {
const intl = useIntl();
const isLibrary = useSelector(selectors.app.isLibrary);
const { setResetTrue, setResetFalse } = resetCardHooks(updateSettings);
const advancedSettingsLink = `${useSelector(selectors.app.studioEndpointUrl)}/settings/advanced/${useSelector(selectors.app.learningContextId)}#show_reset_button`;
@@ -54,9 +53,6 @@ ResetCard.propTypes = {
showResetButton: PropTypes.bool.isRequired,
defaultValue: PropTypes.bool.isRequired,
updateSettings: PropTypes.func.isRequired,
// injected
intl: intlShape.isRequired,
};
export const ResetCardInternal = ResetCard; // For testing only
export default injectIntl(ResetCard);
export default ResetCard;

View File

@@ -1,27 +1,14 @@
import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { useSelector } from 'react-redux';
import {
render, screen, initializeMocks, fireEvent,
} from '@src/testUtils';
import * as reactredux from 'react-redux';
import { formatMessage } from '../../../../../../testUtils';
import { ResetCardInternal as ResetCard } from './ResetCard';
import { resetCardHooks } from '../hooks';
jest.mock('../hooks', () => ({
resetCardHooks: jest.fn(),
}));
jest.mock('../../../../../../data/redux', () => ({
selectors: {
app: {
studioEndpointUrl: 'sTuDioEndpOintUrl',
learningContextId: 'leArningCoNteXtId',
},
},
}));
useSelector.mockImplementation((args) => args);
import ResetCard from './ResetCard';
import * as hooks from '../hooks';
describe('ResetCard', () => {
const resetText = "Determines whether a 'Reset' button is shown so the user may reset their answer, generally for use in practice or formative assessments.";
const props = {
showResetButton: false,
updateSettings: jest.fn().mockName('args.updateSettings'),
@@ -33,21 +20,50 @@ describe('ResetCard', () => {
setResetFalse: jest.fn().mockName('resetCardHooks.setResetFalse'),
};
resetCardHooks.mockReturnValue(resetCardHooksProps);
beforeEach(() => {
initializeMocks();
jest.spyOn(reactredux, 'useSelector').mockImplementation((args) => args);
});
describe('behavior', () => {
it(' calls resetCardHooks when initialized', () => {
shallow(<ResetCard {...props} />);
expect(resetCardHooks).toHaveBeenCalledWith(props.updateSettings);
it('calls resetCardHooks when initialized', () => {
jest.spyOn(hooks, 'resetCardHooks').mockReturnValue(resetCardHooksProps);
render(<ResetCard {...props} />);
expect(hooks.resetCardHooks).toHaveBeenCalledWith(props.updateSettings);
});
});
describe('snapshot', () => {
test('snapshot: renders reset true setting card', () => {
expect(shallow(<ResetCard {...props} />).snapshot).toMatchSnapshot();
describe('renders', () => {
test('renders reset true setting card', () => {
render(<ResetCard {...props} showResetButton />);
expect(screen.getByText('Show reset option')).toBeInTheDocument();
expect(screen.getByText('True')).toBeInTheDocument();
});
test('snapshot: renders reset true setting card', () => {
expect(shallow(<ResetCard {...props} showResetButton />).snapshot).toMatchSnapshot();
test('renders reset false setting card', () => {
render(<ResetCard {...props} />);
expect(screen.getByText('Show reset option')).toBeInTheDocument();
expect(screen.getByText('False')).toBeInTheDocument();
});
test('renders link when isLibrary is false', () => {
jest.spyOn(reactredux, 'useSelector').mockReturnValueOnce(false); // mock isLibrary value
render(<ResetCard {...props} />);
const resetOption = screen.getByText('Show reset option');
expect(resetOption).toBeInTheDocument();
fireEvent.click(resetOption);
expect(screen.getByText(resetText)).toBeInTheDocument();
expect(screen.getByRole('link', { name: 'Set a default value in advanced settings in a new tab' })).toBeInTheDocument();
});
test('do not render link when isLibrary is true', () => {
jest.spyOn(reactredux, 'useSelector').mockReturnValueOnce(true); // mock isLibrary value
render(<ResetCard {...props} />);
const resetOption = screen.getByText('Show reset option');
expect(resetOption).toBeInTheDocument();
fireEvent.click(resetOption);
expect(screen.getByText(resetText)).toBeInTheDocument();
expect(screen.queryByRole('link', { name: 'Set a default value in advanced settings in a new tab' })).not.toBeInTheDocument();
});
});
});

View File

@@ -1,127 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ResetCard snapshot snapshot: renders reset true setting card 1`] = `
<SettingsOption
className="resetCard"
extraSections={[]}
hasExpandableTextArea={false}
summary="False"
title="Show reset option"
>
<div
className="halfSpacedMessage"
>
<span>
<FormattedMessage
defaultMessage="Determines whether a 'Reset' button is shown so the user may reset their answer, generally for use in practice or formative assessments."
description="Reset settings card text"
id="authoring.problemeditor.settings.reset.text"
/>
</span>
</div>
<div
className="spacedMessage"
>
<Hyperlink
destination="sTuDioEndpOintUrl/settings/advanced/leArningCoNteXtId#show_reset_button"
target="_blank"
>
<FormattedMessage
defaultMessage="Set a default value in advanced settings"
description="Advanced settings link text"
id="authoring.problemeditor.settings.advancedSettingLink.text"
/>
</Hyperlink>
</div>
<ButtonGroup
className="resetSettingsButtons mb-2"
size="sm"
>
<Button
onClick={[MockFunction resetCardHooks.setResetFalse]}
size="sm"
variant="primary"
>
<FormattedMessage
defaultMessage="False"
description="False option for reset"
id="authoring.problemeditor.settings.reset.false"
/>
</Button>
<Button
onClick={[MockFunction resetCardHooks.setResetTrue]}
size="sm"
variant="outline-primary"
>
<FormattedMessage
defaultMessage="True"
description="True option for reset"
id="authoring.problemeditor.settings.reset.true"
/>
</Button>
</ButtonGroup>
</SettingsOption>
`;
exports[`ResetCard snapshot snapshot: renders reset true setting card 2`] = `
<SettingsOption
className="resetCard"
extraSections={[]}
hasExpandableTextArea={false}
summary="True"
title="Show reset option"
>
<div
className="halfSpacedMessage"
>
<span>
<FormattedMessage
defaultMessage="Determines whether a 'Reset' button is shown so the user may reset their answer, generally for use in practice or formative assessments."
description="Reset settings card text"
id="authoring.problemeditor.settings.reset.text"
/>
</span>
</div>
<div
className="spacedMessage"
>
<Hyperlink
destination="sTuDioEndpOintUrl/settings/advanced/leArningCoNteXtId#show_reset_button"
target="_blank"
>
<FormattedMessage
defaultMessage="Set a default value in advanced settings"
description="Advanced settings link text"
id="authoring.problemeditor.settings.advancedSettingLink.text"
/>
</Hyperlink>
</div>
<ButtonGroup
className="resetSettingsButtons mb-2"
size="sm"
>
<Button
onClick={[MockFunction resetCardHooks.setResetFalse]}
size="sm"
variant="outline-primary"
>
<FormattedMessage
defaultMessage="False"
description="False option for reset"
id="authoring.problemeditor.settings.reset.false"
/>
</Button>
<Button
onClick={[MockFunction resetCardHooks.setResetTrue]}
size="sm"
variant="primary"
>
<FormattedMessage
defaultMessage="True"
description="True option for reset"
id="authoring.problemeditor.settings.reset.true"
/>
</Button>
</ButtonGroup>
</SettingsOption>
`;

View File

@@ -2,7 +2,6 @@ import React from 'react';
import PropTypes from 'prop-types';
import {
FormattedMessage,
injectIntl,
} from '@edx/frontend-platform/i18n';
import { Icon } from '@openedx/paragon';
import {
@@ -48,5 +47,4 @@ LicenseBlurb.propTypes = {
}).isRequired,
};
export const LicenseBlurbInternal = LicenseBlurb; // For testing only
export default injectIntl(LicenseBlurb);
export default LicenseBlurb;

View File

@@ -1,45 +0,0 @@
import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { LicenseBlurbInternal as LicenseBlurb } from './LicenseBlurb';
describe('LicenseBlurb', () => {
const props = {
license: 'all-rights-reserved',
details: {},
};
describe('snapshots', () => {
test('snapshots: renders as expected with default props', () => {
expect(
shallow(<LicenseBlurb {...props} />).snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with license equal to Creative Commons', () => {
expect(
shallow(<LicenseBlurb {...props} license="creative-commons" />).snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected when details.attribution equal true', () => {
expect(
shallow(<LicenseBlurb {...props} license="creative-commons" details={{ attribution: true }} />).snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected when details.attribution and details.noncommercial equal true', () => {
expect(
shallow(<LicenseBlurb {...props} license="creative-commons" details={{ attribution: true, noncommercial: true }} />).snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected when details.attribution and details.noDerivatives equal true', () => {
expect(
shallow(<LicenseBlurb {...props} license="creative-commons" details={{ attribution: true, noDerivatives: true }} />).snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected when details.attribution and details.shareAlike equal true', () => {
expect(
shallow(<LicenseBlurb {...props} license="creative-commons" details={{ attribution: true, shareAlike: true }} />).snapshot,
).toMatchSnapshot();
});
});
});

View File

@@ -0,0 +1,55 @@
import React from 'react';
import {
render, screen, initializeMocks,
} from '@src/testUtils';
import LicenseBlurb from './LicenseBlurb';
describe('LicenseBlurb', () => {
const props = {
license: 'all-rights-reserved',
details: {
attribution: false,
noncommercial: false,
noDerivatives: false,
shareAlike: false,
},
};
beforeEach(() => initializeMocks());
describe('snapshots', () => {
test('renders as expected with default props', () => {
const { container } = render(<LicenseBlurb {...props} />);
expect(container.querySelectorAll('span.pgn__icon')).toHaveLength(1);
expect(screen.getByText('All Rights Reserved')).toBeInTheDocument();
});
test('renders as expected with license equal to Creative Commons', () => {
const { container } = render(<LicenseBlurb {...props} license="creative-commons" />);
expect(container.querySelectorAll('span.pgn__icon')).toHaveLength(1);
expect(screen.getByText('Some Rights Reserved')).toBeInTheDocument();
});
test('renders as expected when details.attribution equal true', () => {
const { container } = render(<LicenseBlurb license="" details={{ ...props.details, attribution: true }} />);
expect(container.querySelectorAll('span.pgn__icon')).toHaveLength(1);
});
test('renders as expected when details.attribution and details.noncommercial equal true', () => {
const { container } = render(<LicenseBlurb license="" details={{ ...props.details, attribution: true, noncommercial: true }} />);
expect(container.querySelectorAll('span.pgn__icon')).toHaveLength(2);
});
test('renders as expected when details.attribution and details.noDerivatives equal true', () => {
const { container } = render(<LicenseBlurb license="" details={{ ...props.details, attribution: true, noDerivatives: true }} />);
expect(container.querySelectorAll('span.pgn__icon')).toHaveLength(2);
});
test('renders as expected when details.attribution and details.shareAlike equal true', () => {
const { container } = render(<LicenseBlurb license="" details={{ ...props.details, attribution: true, shareAlike: true }} />);
expect(container.querySelectorAll('span.pgn__icon')).toHaveLength(2);
});
});
});

View File

@@ -1,214 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`LicenseBlurb snapshots snapshots: renders as expected when details.attribution and details.noDerivatives equal true 1`] = `
<div
className="d-flex flex-row align-items-center mt-2"
>
<Icon
className="mr-1"
style={
{
"height": "18px",
"width": "18px",
}
}
/>
<Icon
className="mr-1 text-primary-300"
style={
{
"height": "18px",
"width": "18px",
}
}
/>
<Icon
className="mr-1"
style={
{
"height": "18px",
"width": "18px",
}
}
/>
<div
className="small mx-1.5"
>
<FormattedMessage
defaultMessage="Some Rights Reserved"
description="Label for row of creative common icons"
id="authoring.videoeditor.license.creativeCommonsIcons.label"
/>
</div>
</div>
`;
exports[`LicenseBlurb snapshots snapshots: renders as expected when details.attribution and details.noncommercial equal true 1`] = `
<div
className="d-flex flex-row align-items-center mt-2"
>
<Icon
className="mr-1"
style={
{
"height": "18px",
"width": "18px",
}
}
/>
<Icon
className="mr-1 text-primary-300"
style={
{
"height": "18px",
"width": "18px",
}
}
/>
<Icon
className="mr-1"
style={
{
"height": "18px",
"width": "18px",
}
}
/>
<div
className="small mx-1.5"
>
<FormattedMessage
defaultMessage="Some Rights Reserved"
description="Label for row of creative common icons"
id="authoring.videoeditor.license.creativeCommonsIcons.label"
/>
</div>
</div>
`;
exports[`LicenseBlurb snapshots snapshots: renders as expected when details.attribution and details.shareAlike equal true 1`] = `
<div
className="d-flex flex-row align-items-center mt-2"
>
<Icon
className="mr-1"
style={
{
"height": "18px",
"width": "18px",
}
}
/>
<Icon
className="mr-1 text-primary-300"
style={
{
"height": "18px",
"width": "18px",
}
}
/>
<Icon
className="mr-1"
style={
{
"height": "18px",
"width": "18px",
}
}
/>
<div
className="small mx-1.5"
>
<FormattedMessage
defaultMessage="Some Rights Reserved"
description="Label for row of creative common icons"
id="authoring.videoeditor.license.creativeCommonsIcons.label"
/>
</div>
</div>
`;
exports[`LicenseBlurb snapshots snapshots: renders as expected when details.attribution equal true 1`] = `
<div
className="d-flex flex-row align-items-center mt-2"
>
<Icon
className="mr-1"
style={
{
"height": "18px",
"width": "18px",
}
}
/>
<Icon
className="mr-1 text-primary-300"
style={
{
"height": "18px",
"width": "18px",
}
}
/>
<div
className="small mx-1.5"
>
<FormattedMessage
defaultMessage="Some Rights Reserved"
description="Label for row of creative common icons"
id="authoring.videoeditor.license.creativeCommonsIcons.label"
/>
</div>
</div>
`;
exports[`LicenseBlurb snapshots snapshots: renders as expected with default props 1`] = `
<div
className="d-flex flex-row align-items-center mt-2"
>
<Icon
className="mr-1"
style={
{
"height": "18px",
"width": "18px",
}
}
/>
<div
className="small mx-1.5"
>
<FormattedMessage
defaultMessage="All Rights Reserved"
description="Label for row of all rights reserved icons"
id="authoring.videoeditor.license.allRightsReservedIcons.label"
/>
</div>
</div>
`;
exports[`LicenseBlurb snapshots snapshots: renders as expected with license equal to Creative Commons 1`] = `
<div
className="d-flex flex-row align-items-center mt-2"
>
<Icon
className="mr-1"
style={
{
"height": "18px",
"width": "18px",
}
}
/>
<div
className="small mx-1.5"
>
<FormattedMessage
defaultMessage="Some Rights Reserved"
description="Label for row of creative common icons"
id="authoring.videoeditor.license.creativeCommonsIcons.label"
/>
</div>
</div>
`;

View File

@@ -5,7 +5,7 @@ exports[`LicenseWidget snapshots snapshots: renders as expected with default pro
fontSize=""
subtitle={
<div>
<injectIntl(ShimmedIntlComponent)
<LicenseBlurb
details={{}}
license="all-rights-reserved"
/>
@@ -73,7 +73,7 @@ exports[`LicenseWidget snapshots snapshots: renders as expected with isLibrary t
fontSize=""
subtitle={
<div>
<injectIntl(ShimmedIntlComponent)
<LicenseBlurb
details={{}}
license="all-rights-reserved"
/>
@@ -124,7 +124,7 @@ exports[`LicenseWidget snapshots snapshots: renders as expected with licenseType
fontSize=""
subtitle={
<div>
<injectIntl(ShimmedIntlComponent)
<LicenseBlurb
details={{}}
license="all-rights-reserved"
/>

View File

@@ -1,207 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`TinyMceWidget snapshots ImageUploadModal is not rendered 1`] = `
<Fragment>
<SourceCodeModal
close={[MockFunction modal.closeModal]}
editorRef={
{
"current": {
"value": "something",
},
}
}
isOpen={false}
/>
<Editor
disabled={false}
editorConfig={
{
"clearSelection": [MockFunction hooks.selectedImage.clearSelection],
"content": undefined,
"editorContentHtml": undefined,
"editorRef": {
"current": {
"value": "something",
},
},
"editorType": "text",
"enableImageUpload": false,
"images": {
"current": [
{
"externalUrl": "/assets/sOmEaSsET",
},
],
},
"initializeEditor": undefined,
"learningContextId": "course+org+run",
"lmsEndpointUrl": "sOmEvaLue.cOm",
"minHeight": undefined,
"openImgModal": [MockFunction modal.openModal],
"openSourceCodeModal": [MockFunction modal.openModal],
"placeholder": undefined,
"selection": "hooks.selectedImage.selection",
"setEditorRef": undefined,
"setSelection": [MockFunction hooks.selectedImage.setSelection],
"staticRootUrl": undefined,
"studioEndpointUrl": "sOmEoThERvaLue.cOm",
"updateContent": [Function],
}
}
id="sOMeiD"
onEditorChange={[Function]}
/>
</Fragment>
`;
exports[`TinyMceWidget snapshots SourcecodeModal is not rendered 1`] = `
<Fragment>
<ImageUploadModal
clearSelection={[MockFunction hooks.selectedImage.clearSelection]}
close={[MockFunction modal.closeModal]}
editorRef={
{
"current": {
"value": "something",
},
}
}
editorType="problem"
images={
{
"current": [
{
"externalUrl": "/assets/sOmEaSsET",
},
],
}
}
isLibrary={true}
isOpen={false}
lmsEndpointUrl="http://localhost:18000"
selection="hooks.selectedImage.selection"
setSelection={[MockFunction hooks.selectedImage.setSelection]}
/>
<Editor
disabled={false}
editorConfig={
{
"clearSelection": [MockFunction hooks.selectedImage.clearSelection],
"content": undefined,
"editorContentHtml": undefined,
"editorRef": {
"current": {
"value": "something",
},
},
"editorType": "problem",
"enableImageUpload": true,
"images": {
"current": [
{
"externalUrl": "/assets/sOmEaSsET",
},
],
},
"initializeEditor": undefined,
"learningContextId": "course+org+run",
"lmsEndpointUrl": "sOmEvaLue.cOm",
"minHeight": undefined,
"openImgModal": [MockFunction modal.openModal],
"openSourceCodeModal": [MockFunction modal.openModal],
"placeholder": undefined,
"selection": "hooks.selectedImage.selection",
"setEditorRef": undefined,
"setSelection": [MockFunction hooks.selectedImage.setSelection],
"staticRootUrl": undefined,
"studioEndpointUrl": "sOmEoThERvaLue.cOm",
"updateContent": [Function],
}
}
id="sOMeiD"
onEditorChange={[Function]}
/>
</Fragment>
`;
exports[`TinyMceWidget snapshots renders as expected with default behavior 1`] = `
<Fragment>
<ImageUploadModal
clearSelection={[MockFunction hooks.selectedImage.clearSelection]}
close={[MockFunction modal.closeModal]}
editorRef={
{
"current": {
"value": "something",
},
}
}
editorType="text"
images={
{
"current": [
{
"externalUrl": "/assets/sOmEaSsET",
},
],
}
}
isLibrary={true}
isOpen={false}
lmsEndpointUrl="http://localhost:18000"
selection="hooks.selectedImage.selection"
setSelection={[MockFunction hooks.selectedImage.setSelection]}
/>
<SourceCodeModal
close={[MockFunction modal.closeModal]}
editorRef={
{
"current": {
"value": "something",
},
}
}
isOpen={false}
/>
<Editor
disabled={false}
editorConfig={
{
"clearSelection": [MockFunction hooks.selectedImage.clearSelection],
"content": undefined,
"editorContentHtml": undefined,
"editorRef": {
"current": {
"value": "something",
},
},
"editorType": "text",
"enableImageUpload": true,
"images": {
"current": [
{
"externalUrl": "/assets/sOmEaSsET",
},
],
},
"initializeEditor": undefined,
"learningContextId": "course+org+run",
"lmsEndpointUrl": "sOmEvaLue.cOm",
"minHeight": undefined,
"openImgModal": [MockFunction modal.openModal],
"openSourceCodeModal": [MockFunction modal.openModal],
"placeholder": undefined,
"selection": "hooks.selectedImage.selection",
"setEditorRef": undefined,
"setSelection": [MockFunction hooks.selectedImage.setSelection],
"staticRootUrl": undefined,
"studioEndpointUrl": "sOmEoThERvaLue.cOm",
"updateContent": [Function],
}
}
id="sOMeiD"
onEditorChange={[Function]}
/>
</Fragment>
`;

View File

@@ -1,9 +1,10 @@
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import SourceCodeModal from '../SourceCodeModal';
import ImageUploadModal from '../ImageUploadModal';
import { imgModalToggle, sourceCodeModalToggle } from './hooks';
import { TinyMceWidgetInternal as TinyMceWidget } from '.';
import {
screen, initializeMocks,
} from '@src/testUtils';
import editorRender from '@src/editors/editorTestRender';
import * as hooks from './hooks';
import TinyMceWidget from '.';
const staticUrl = '/assets/sOmEaSsET';
@@ -42,6 +43,8 @@ jest.mock('./hooks', () => ({
}));
describe('TinyMceWidget', () => {
beforeEach(() => initializeMocks());
const props = {
editorType: 'text',
editorRef: { current: { value: 'something' } },
@@ -53,30 +56,41 @@ describe('TinyMceWidget', () => {
id: 'sOMeiD',
updateContent: () => ({}),
learningContextId: 'course+org+run',
editorContentHtml: undefined,
enableImageUpload: undefined,
onChange: undefined,
staticRootUrl: undefined,
};
describe('snapshots', () => {
imgModalToggle.mockReturnValue({
describe('render', () => {
jest.spyOn(hooks, 'imgModalToggle').mockReturnValue({
isImgOpen: false,
openImgModal: jest.fn().mockName('modal.openModal'),
closeImgModal: jest.fn().mockName('modal.closeModal'),
});
sourceCodeModalToggle.mockReturnValue({
jest.spyOn(hooks, 'sourceCodeModalToggle').mockReturnValue({
isSourceCodeOpen: false,
openSourceCodeModal: jest.fn().mockName('modal.openModal'),
closeSourceCodeModal: jest.fn().mockName('modal.closeModal'),
});
test('renders as expected with default behavior', () => {
expect(shallow(<TinyMceWidget {...props} />).snapshot).toMatchSnapshot();
const { container } = editorRender(<TinyMceWidget {...props} />);
expect(screen.getByText('TiNYmCE EDitOR')).toBeInTheDocument();
expect(container.querySelector('sourcecodemodal')).toBeInTheDocument();
expect(container.querySelector('imageuploadmodal')).toBeInTheDocument();
});
test('SourcecodeModal is not rendered', () => {
const wrapper = shallow(<TinyMceWidget {...props} editorType="problem" />);
expect(wrapper.snapshot).toMatchSnapshot();
expect(wrapper.instance.findByType(SourceCodeModal).length).toBe(0);
const { container } = editorRender(<TinyMceWidget {...props} editorType="problem" />);
expect(container.querySelector('imageuploadmodal')).toBeInTheDocument();
expect(container.querySelector('sourcecodemodal')).not.toBeInTheDocument();
});
test('ImageUploadModal is not rendered', () => {
const wrapper = shallow(<TinyMceWidget {...props} enableImageUpload={false} />);
expect(wrapper.snapshot).toMatchSnapshot();
expect(wrapper.instance.findByType(ImageUploadModal).length).toBe(0);
const { container } = editorRender(<TinyMceWidget {...props} enableImageUpload={false} />);
expect(container.querySelector('imageuploadmodal')).not.toBeInTheDocument();
expect(container.querySelector('sourcecodemodal')).toBeInTheDocument();
});
});
});