test: replacing snapshot tests with RTL tests part 15 (#2248)
This commit is contained in:
committed by
GitHub
parent
e8e5a3c4ce
commit
c4f565bf76
@@ -1,43 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`SolutionWidget render snapshot: renders correct default 1`] = `
|
||||
<div
|
||||
className="tinyMceWidget mt-4 text-primary-500"
|
||||
>
|
||||
<div
|
||||
className="h4 mb-3"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Explanation"
|
||||
description="Explanation Title"
|
||||
id="authoring.problemEditor.explanationwidget.explanationWidgetTitle"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="small mb-3"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Provide an explanation for the correct answer"
|
||||
description="Description of the solution widget"
|
||||
id="authoring.problemEditor.explanationwidget.solutionDescriptionText"
|
||||
/>
|
||||
</div>
|
||||
<TinyMceWidget
|
||||
disabled={false}
|
||||
editorContentHtml="This is my solution"
|
||||
editorRef={null}
|
||||
editorType="solution"
|
||||
enableImageUpload={true}
|
||||
id="solution"
|
||||
images={{}}
|
||||
isLibrary={false}
|
||||
learningContextId="course+org+run"
|
||||
lmsEndpointUrl=""
|
||||
minHeight={150}
|
||||
onChange={[Function]}
|
||||
placeholder="Enter your explanation"
|
||||
setEditorRef={[MockFunction prepareEditorRef.setEditorRef]}
|
||||
studioEndpointUrl=""
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { injectIntl, FormattedMessage, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { useIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
|
||||
import { selectors } from '../../../../../data/redux';
|
||||
@@ -16,9 +16,8 @@ const ExplanationWidget = ({
|
||||
images,
|
||||
isLibrary,
|
||||
blockId,
|
||||
// injected
|
||||
intl,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const { editorRef, refReady, setEditorRef } = prepareEditorRef();
|
||||
const initialContent = settings?.solutionExplanation || '';
|
||||
const newContent = replaceStaticWithAsset({
|
||||
@@ -66,8 +65,6 @@ ExplanationWidget.propTypes = {
|
||||
images: PropTypes.shape({}).isRequired,
|
||||
isLibrary: PropTypes.bool.isRequired,
|
||||
blockId: PropTypes.string.isRequired,
|
||||
// injected
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
export const mapStateToProps = (state) => ({
|
||||
settings: selectors.problem.settings(state),
|
||||
@@ -78,4 +75,4 @@ export const mapStateToProps = (state) => ({
|
||||
});
|
||||
|
||||
export const ExplanationWidgetInternal = ExplanationWidget; // For testing only
|
||||
export default injectIntl(connect(mapStateToProps)(ExplanationWidget));
|
||||
export default connect(mapStateToProps)(ExplanationWidget);
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
import 'CourseAuthoring/editors/setupEditorTest';
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
import { formatMessage } from '../../../../../testUtils';
|
||||
import { selectors } from '../../../../../data/redux';
|
||||
import { ExplanationWidgetInternal as ExplanationWidget, mapStateToProps } from '.';
|
||||
|
||||
jest.mock('../../../../../data/redux', () => ({
|
||||
__esModule: true,
|
||||
default: jest.fn(),
|
||||
selectors: {
|
||||
problem: {
|
||||
settings: jest.fn(state => ({ question: state })),
|
||||
},
|
||||
app: {
|
||||
learningContextId: jest.fn(state => ({ learningContextId: state })),
|
||||
images: jest.fn(state => ({ images: state })),
|
||||
isLibrary: jest.fn(state => ({ isLibrary: state })),
|
||||
blockId: jest.fn(state => ({ blockId: state })),
|
||||
},
|
||||
},
|
||||
thunkActions: {
|
||||
video: {
|
||||
importTranscript: jest.fn(),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('../../../../../sharedComponents/TinyMceWidget/hooks', () => ({
|
||||
...jest.requireActual('../../../../../sharedComponents/TinyMceWidget/hooks'),
|
||||
prepareEditorRef: jest.fn(() => ({
|
||||
refReady: true,
|
||||
setEditorRef: jest.fn().mockName('prepareEditorRef.setEditorRef'),
|
||||
})),
|
||||
}));
|
||||
|
||||
describe('SolutionWidget', () => {
|
||||
const props = {
|
||||
settings: { solutionExplanation: 'This is my solution' },
|
||||
learningContextId: 'course+org+run',
|
||||
images: {},
|
||||
isLibrary: false,
|
||||
// injected
|
||||
intl: { formatMessage },
|
||||
};
|
||||
describe('render', () => {
|
||||
test('snapshot: renders correct default', () => {
|
||||
expect(shallow(<ExplanationWidget {...props} />).snapshot).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
describe('mapStateToProps', () => {
|
||||
const testState = { A: 'pple', B: 'anana', C: 'ucumber' };
|
||||
test('settings from problem.settings', () => {
|
||||
expect(mapStateToProps(testState).settings).toEqual(selectors.problem.settings(testState));
|
||||
});
|
||||
test('learningContextId from app.learningContextId', () => {
|
||||
expect(mapStateToProps(testState).learningContextId).toEqual(selectors.app.learningContextId(testState));
|
||||
});
|
||||
test('images from app.images', () => {
|
||||
expect(
|
||||
mapStateToProps(testState).images,
|
||||
).toEqual(selectors.app.images(testState));
|
||||
});
|
||||
test('isLibrary from app.isLibrary', () => {
|
||||
expect(
|
||||
mapStateToProps(testState).isLibrary,
|
||||
).toEqual(selectors.app.isLibrary(testState));
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,56 @@
|
||||
import React from 'react';
|
||||
import { render, screen, initializeMocks } from '@src/testUtils';
|
||||
import ExplanationWidget from '.';
|
||||
|
||||
jest.mock('../../../../../data/redux', () => ({
|
||||
__esModule: true,
|
||||
default: jest.fn(),
|
||||
selectors: {
|
||||
problem: {
|
||||
settings: jest.fn(state => ({ question: state })),
|
||||
},
|
||||
app: {
|
||||
learningContextId: jest.fn(state => ({ learningContextId: state })),
|
||||
images: jest.fn(state => ({ images: state })),
|
||||
isLibrary: jest.fn(state => ({ isLibrary: state })),
|
||||
blockId: jest.fn(state => ({ blockId: state })),
|
||||
},
|
||||
},
|
||||
thunkActions: {
|
||||
video: {
|
||||
importTranscript: jest.fn(),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('../../../../../sharedComponents/TinyMceWidget/hooks', () => ({
|
||||
...jest.requireActual('../../../../../sharedComponents/TinyMceWidget/hooks'),
|
||||
prepareEditorRef: jest.fn(() => ({
|
||||
refReady: true,
|
||||
setEditorRef: jest.fn().mockName('prepareEditorRef.setEditorRef'),
|
||||
})),
|
||||
}));
|
||||
|
||||
jest.mock('../../../../../sharedComponents/TinyMceWidget', () => ({
|
||||
__esModule: true,
|
||||
default: () => <div>TinyMceWidget</div>,
|
||||
}));
|
||||
|
||||
describe('SolutionWidget', () => {
|
||||
const props = {
|
||||
settings: { solutionExplanation: 'This is my solution' },
|
||||
learningContextId: 'course+org+run',
|
||||
images: {},
|
||||
isLibrary: false,
|
||||
blockId: 'block-v1:Org+TS100+24+type@html+block@12345',
|
||||
};
|
||||
beforeEach(() => {
|
||||
initializeMocks();
|
||||
});
|
||||
test('renders correct default', () => {
|
||||
render(<ExplanationWidget {...props} />);
|
||||
expect(screen.getByText('Explanation')).toBeInTheDocument();
|
||||
expect(screen.getByText('Provide an explanation for the correct answer')).toBeInTheDocument();
|
||||
expect(screen.getByText('TinyMceWidget')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -1,35 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`RandomizationCard snapshot snapshot: renders general feedback setting card 1`] = `
|
||||
<SettingsOption
|
||||
className=""
|
||||
extraSections={[]}
|
||||
hasExpandableTextArea={false}
|
||||
none={false}
|
||||
summary={
|
||||
{
|
||||
"defaultMessage": "sUmmary",
|
||||
}
|
||||
}
|
||||
title="General Feedback"
|
||||
>
|
||||
<div
|
||||
className="halfSpacedMessage"
|
||||
>
|
||||
<span>
|
||||
<FormattedMessage
|
||||
defaultMessage="Enter the feedback to appear when a student submits a wrong answer. This will be overridden if you add answer-specific feedback."
|
||||
description="description for general feedback input, clariying useage"
|
||||
id="authoring.problemeditor.settings.generalFeedbackInputDescription"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<Form.Group>
|
||||
<Form.Control
|
||||
floatingLabel="Enter General Feedback"
|
||||
onChange={[MockFunction randomizationCardHooks.handleChange]}
|
||||
value="sOmE_vAlUE"
|
||||
/>
|
||||
</Form.Group>
|
||||
</SettingsOption>
|
||||
`;
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { injectIntl, FormattedMessage, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Form } from '@openedx/paragon';
|
||||
import PropTypes from 'prop-types';
|
||||
import SettingsOption from '../../SettingsOption';
|
||||
@@ -9,9 +9,8 @@ import { generalFeedbackHooks } from './hooks';
|
||||
export const GeneralFeedbackCard = ({
|
||||
generalFeedback,
|
||||
updateSettings,
|
||||
// inject
|
||||
intl,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const { summary, handleChange } = generalFeedbackHooks(generalFeedback, updateSettings);
|
||||
return (
|
||||
<SettingsOption
|
||||
@@ -38,7 +37,6 @@ export const GeneralFeedbackCard = ({
|
||||
GeneralFeedbackCard.propTypes = {
|
||||
generalFeedback: PropTypes.string.isRequired,
|
||||
updateSettings: PropTypes.func.isRequired,
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(GeneralFeedbackCard);
|
||||
export default GeneralFeedbackCard;
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
import 'CourseAuthoring/editors/setupEditorTest';
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
import { formatMessage } from '../../../../../../../testUtils';
|
||||
import { GeneralFeedbackCard } from './index';
|
||||
import { generalFeedbackHooks } from './hooks';
|
||||
|
||||
jest.mock('./hooks', () => ({
|
||||
generalFeedbackHooks: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('RandomizationCard', () => {
|
||||
const props = {
|
||||
generalFeedback: 'sOmE_vAlUE',
|
||||
updateSettings: jest.fn().mockName('args.updateSettings'),
|
||||
intl: { formatMessage },
|
||||
};
|
||||
|
||||
const randomizationCardHooksProps = {
|
||||
summary: { message: { defaultMessage: 'sUmmary' } },
|
||||
handleChange: jest.fn().mockName('randomizationCardHooks.handleChange'),
|
||||
};
|
||||
|
||||
generalFeedbackHooks.mockReturnValue(randomizationCardHooksProps);
|
||||
|
||||
describe('behavior', () => {
|
||||
it(' calls generalFeedbackHooks with props when initialized', () => {
|
||||
shallow(<GeneralFeedbackCard {...props} />);
|
||||
expect(generalFeedbackHooks).toHaveBeenCalledWith(props.generalFeedback, props.updateSettings);
|
||||
});
|
||||
});
|
||||
|
||||
describe('snapshot', () => {
|
||||
test('snapshot: renders general feedback setting card', () => {
|
||||
expect(shallow(<GeneralFeedbackCard {...props} />).snapshot).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
render, screen, initializeMocks, fireEvent,
|
||||
} from '@src/testUtils';
|
||||
import { GeneralFeedbackCard } from './index';
|
||||
import * as hooks from './hooks';
|
||||
|
||||
describe('GeneralFeedbackCard', () => {
|
||||
const props = {
|
||||
generalFeedback: 'sOmE_vAlUE',
|
||||
updateSettings: jest.fn().mockName('args.updateSettings'),
|
||||
};
|
||||
|
||||
const randomizationCardHooksProps = {
|
||||
summary: { message: { defaultMessage: 'sUmmary' } },
|
||||
handleChange: jest.fn().mockName('randomizationCardHooks.handleChange'),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
initializeMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('behavior', () => {
|
||||
it('calls generalFeedbackHooks with props when initialized', () => {
|
||||
jest.spyOn(hooks, 'generalFeedbackHooks').mockImplementation(() => randomizationCardHooksProps);
|
||||
render(<GeneralFeedbackCard {...props} />);
|
||||
expect(hooks.generalFeedbackHooks).toHaveBeenCalledWith(props.generalFeedback, props.updateSettings);
|
||||
});
|
||||
});
|
||||
|
||||
describe('render', () => {
|
||||
test('renders general feedback setting card', () => {
|
||||
render(<GeneralFeedbackCard {...props} />);
|
||||
expect(screen.getByText('General Feedback')).toBeInTheDocument();
|
||||
expect(screen.getByText('sOmE_vAlUE')).toBeInTheDocument();
|
||||
fireEvent.click(screen.getByText('General Feedback'));
|
||||
expect(screen.getByText('Enter General Feedback')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,171 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`LicenseWidget snapshots snapshots: renders as expected with default props 1`] = `
|
||||
<CollapsibleFormWidget
|
||||
fontSize=""
|
||||
subtitle={
|
||||
<div>
|
||||
<LicenseBlurb
|
||||
details={{}}
|
||||
license="all-rights-reserved"
|
||||
/>
|
||||
<div
|
||||
className="x-small mt-2"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="This license currently set at the course level"
|
||||
description="Helper text for license type when using course license"
|
||||
id="authoring.videoeditor.license.courseLevelDescription.helperText"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
title="License"
|
||||
>
|
||||
<Stack
|
||||
gap={4}
|
||||
>
|
||||
<Fragment>
|
||||
<[object Object]
|
||||
level="course"
|
||||
license="all-rights-reserved"
|
||||
/>
|
||||
<injectIntl(ShimmedIntlComponent)
|
||||
details={{}}
|
||||
level="course"
|
||||
license="all-rights-reserved"
|
||||
/>
|
||||
<LicenseDisplay
|
||||
details={{}}
|
||||
license="all-rights-reserved"
|
||||
licenseDescription={
|
||||
<FormattedMessage
|
||||
defaultMessage="Licenses set at the course level appear at the bottom of courseware pages within your course."
|
||||
description="Message explaining where course level licenses are set"
|
||||
id="authoring.videoeditor.license.courseLicenseDescription.message"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Fragment>
|
||||
<Fragment>
|
||||
<div
|
||||
className="border-primary-100 border-bottom my-2"
|
||||
/>
|
||||
<Button
|
||||
className="text-primary-500 font-weight-bold justify-content-start pl-0"
|
||||
onClick={[Function]}
|
||||
size="sm"
|
||||
variant="link"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Add a license for this video"
|
||||
description="Label for add license button"
|
||||
id="authoring.videoeditor.license.add.label"
|
||||
/>
|
||||
</Button>
|
||||
</Fragment>
|
||||
</Stack>
|
||||
</CollapsibleFormWidget>
|
||||
`;
|
||||
|
||||
exports[`LicenseWidget snapshots snapshots: renders as expected with isLibrary true 1`] = `
|
||||
<CollapsibleFormWidget
|
||||
fontSize=""
|
||||
subtitle={
|
||||
<div>
|
||||
<LicenseBlurb
|
||||
details={{}}
|
||||
license="all-rights-reserved"
|
||||
/>
|
||||
<div
|
||||
className="x-small mt-2"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="This license currently set at the library level"
|
||||
description="Helper text for license type when using library license"
|
||||
id="authoring.videoeditor.license.libraryLevelDescription.helperText"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
title="License"
|
||||
>
|
||||
<Stack
|
||||
gap={4}
|
||||
>
|
||||
<Fragment>
|
||||
<[object Object]
|
||||
level="library"
|
||||
license="all-rights-reserved"
|
||||
/>
|
||||
<injectIntl(ShimmedIntlComponent)
|
||||
details={{}}
|
||||
level="library"
|
||||
license="all-rights-reserved"
|
||||
/>
|
||||
<LicenseDisplay
|
||||
details={{}}
|
||||
license="all-rights-reserved"
|
||||
licenseDescription={
|
||||
<FormattedMessage
|
||||
defaultMessage="Licenses set at the library level appear at the specific library video."
|
||||
description="Message explaining where library level licenses are set"
|
||||
id="authoring.videoeditor.license.libraryLicenseDescription.message"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Fragment>
|
||||
</Stack>
|
||||
</CollapsibleFormWidget>
|
||||
`;
|
||||
|
||||
exports[`LicenseWidget snapshots snapshots: renders as expected with licenseType defined 1`] = `
|
||||
<CollapsibleFormWidget
|
||||
fontSize=""
|
||||
subtitle={
|
||||
<div>
|
||||
<LicenseBlurb
|
||||
details={{}}
|
||||
license="all-rights-reserved"
|
||||
/>
|
||||
<div
|
||||
className="x-small mt-2"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="This license is set specifically for this video"
|
||||
description="Helper text for license type when choosing for a spcific video"
|
||||
id="authoring.videoeditor.license.defaultLevelDescription.helperText"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
title="License"
|
||||
>
|
||||
<Stack
|
||||
gap={4}
|
||||
>
|
||||
<Fragment>
|
||||
<[object Object]
|
||||
level="block"
|
||||
license="all-rights-reserved"
|
||||
/>
|
||||
<injectIntl(ShimmedIntlComponent)
|
||||
details={{}}
|
||||
level="block"
|
||||
license="all-rights-reserved"
|
||||
/>
|
||||
<LicenseDisplay
|
||||
details={{}}
|
||||
license="all-rights-reserved"
|
||||
licenseDescription={
|
||||
<FormattedMessage
|
||||
defaultMessage="When a video has a different license than the course as a whole, learners see the license at the bottom right of the video player."
|
||||
description="Message explaining where video specific licenses are seen by users"
|
||||
id="authoring.videoeditor.license.defaultLicenseDescription.message"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Fragment>
|
||||
</Stack>
|
||||
</CollapsibleFormWidget>
|
||||
`;
|
||||
@@ -1,112 +0,0 @@
|
||||
import 'CourseAuthoring/editors/setupEditorTest';
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
|
||||
import { formatMessage } from '../../../../../../testUtils';
|
||||
import { actions, selectors } from '../../../../../../data/redux';
|
||||
import { LicenseWidgetInternal as LicenseWidget, mapStateToProps, mapDispatchToProps } from '.';
|
||||
|
||||
jest.mock('react', () => {
|
||||
const updateState = jest.fn();
|
||||
return {
|
||||
...jest.requireActual('react'),
|
||||
updateState,
|
||||
useContext: jest.fn(() => ({ license: ['error.license', jest.fn().mockName('error.setLicense')] })),
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('../../../../../../data/redux', () => ({
|
||||
actions: {
|
||||
video: {
|
||||
updateField: jest.fn().mockName('actions.video.updateField'),
|
||||
},
|
||||
},
|
||||
selectors: {
|
||||
app: {
|
||||
isLibrary: jest.fn(state => ({ isLibrary: state })),
|
||||
},
|
||||
video: {
|
||||
licenseType: jest.fn(state => ({ licenseType: state })),
|
||||
licenseDetails: jest.fn(state => ({ licenseDetails: state })),
|
||||
courseLicenseType: jest.fn(state => ({ courseLicenseType: state })),
|
||||
courseLicenseDetails: jest.fn(state => ({ courseLicenseDetails: state })),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
describe('LicenseWidget', () => {
|
||||
const props = {
|
||||
error: {},
|
||||
subtitle: 'SuBTItle',
|
||||
title: 'tiTLE',
|
||||
intl: { formatMessage },
|
||||
isLibrary: false,
|
||||
licenseType: null,
|
||||
licenseDetails: {},
|
||||
courseLicenseType: 'all-rights-reserved',
|
||||
courseLicenseDetails: {},
|
||||
updateField: jest.fn().mockName('args.updateField'),
|
||||
};
|
||||
|
||||
describe('snapshots', () => {
|
||||
// determineLicense.mockReturnValue({
|
||||
// license: false,
|
||||
// details: jest.fn().mockName('modal.openModal'),
|
||||
// level: 'course',
|
||||
// });
|
||||
// determineText.mockReturnValue({
|
||||
// isSourceCodeOpen: false,
|
||||
// openSourceCodeModal: jest.fn().mockName('modal.openModal'),
|
||||
// closeSourceCodeModal: jest.fn().mockName('modal.closeModal'),
|
||||
// });
|
||||
test('snapshots: renders as expected with default props', () => {
|
||||
expect(
|
||||
shallow(<LicenseWidget {...props} />).snapshot,
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
test('snapshots: renders as expected with isLibrary true', () => {
|
||||
expect(
|
||||
shallow(<LicenseWidget {...props} isLibrary licenseType="all-rights-reserved" />).snapshot,
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
test('snapshots: renders as expected with licenseType defined', () => {
|
||||
expect(
|
||||
shallow(<LicenseWidget {...props} licenseType="all-rights-reserved" />).snapshot,
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
describe('mapStateToProps', () => {
|
||||
const testState = { A: 'pple', B: 'anana', C: 'ucumber' };
|
||||
test('isLibrary from app.isLibrary', () => {
|
||||
expect(
|
||||
mapStateToProps(testState).isLibrary,
|
||||
).toEqual(selectors.app.isLibrary(testState));
|
||||
});
|
||||
test('licenseType from video.licenseType', () => {
|
||||
expect(
|
||||
mapStateToProps(testState).licenseType,
|
||||
).toEqual(selectors.video.licenseType(testState));
|
||||
});
|
||||
test('licenseDetails from video.licenseDetails', () => {
|
||||
expect(
|
||||
mapStateToProps(testState).licenseDetails,
|
||||
).toEqual(selectors.video.licenseDetails(testState));
|
||||
});
|
||||
test('courseLicenseType from video.courseLicenseType', () => {
|
||||
expect(
|
||||
mapStateToProps(testState).courseLicenseType,
|
||||
).toEqual(selectors.video.courseLicenseType(testState));
|
||||
});
|
||||
test('courseLicenseDetails from video.courseLicenseDetails', () => {
|
||||
expect(
|
||||
mapStateToProps(testState).courseLicenseDetails,
|
||||
).toEqual(selectors.video.courseLicenseDetails(testState));
|
||||
});
|
||||
});
|
||||
describe('mapDispatchToProps', () => {
|
||||
const dispatch = jest.fn();
|
||||
test('updateField from actions.video.updateField', () => {
|
||||
expect(mapDispatchToProps.updateField).toEqual(dispatch(actions.video.updateField));
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,55 @@
|
||||
import React from 'react';
|
||||
import { render, screen, initializeMocks } from '@src/testUtils';
|
||||
import { formatMessage } from '../../../../../../testUtils';
|
||||
import { LicenseWidgetInternal as LicenseWidget } from '.';
|
||||
|
||||
jest.mock('../../../../../../data/redux', () => ({
|
||||
actions: {
|
||||
video: {
|
||||
updateField: jest.fn().mockName('actions.video.updateField'),
|
||||
},
|
||||
},
|
||||
selectors: {
|
||||
app: {
|
||||
isLibrary: jest.fn(state => ({ isLibrary: state })),
|
||||
},
|
||||
video: {
|
||||
licenseType: jest.fn(state => ({ licenseType: state })),
|
||||
licenseDetails: jest.fn(state => ({ licenseDetails: state })),
|
||||
courseLicenseType: jest.fn(state => ({ courseLicenseType: state })),
|
||||
courseLicenseDetails: jest.fn(state => ({ courseLicenseDetails: state })),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
describe('LicenseWidget', () => {
|
||||
const props = {
|
||||
intl: { formatMessage },
|
||||
isLibrary: false,
|
||||
licenseType: '',
|
||||
licenseDetails: {},
|
||||
courseLicenseType: 'all-rights-reserved',
|
||||
courseLicenseDetails: {},
|
||||
updateField: jest.fn().mockName('args.updateField'),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
initializeMocks();
|
||||
});
|
||||
|
||||
test('renders as expected with default props', () => {
|
||||
render(<LicenseWidget {...props} />);
|
||||
expect(screen.getByText('License')).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: 'Add a license for this video' })).toBeInTheDocument();
|
||||
});
|
||||
test('renders as expected with isLibrary true', () => {
|
||||
render(<LicenseWidget {...props} isLibrary licenseType="all-rights-reserved" />);
|
||||
expect(screen.getByText('License')).toBeInTheDocument();
|
||||
expect(screen.queryByRole('button', { name: 'Add a license for this video' })).not.toBeInTheDocument();
|
||||
});
|
||||
test('renders as expected with licenseType defined', () => {
|
||||
render(<LicenseWidget {...props} licenseType="all-rights-reserved" />);
|
||||
expect(screen.getByText('License')).toBeInTheDocument();
|
||||
expect(screen.queryByRole('button', { name: 'Add a license for this video' })).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -1,156 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ThumbnailWidget snapshots snapshots: renders as expected where thumbnail uploads are allowed 1`] = `null`;
|
||||
|
||||
exports[`ThumbnailWidget snapshots snapshots: renders as expected where videoId is valid 1`] = `
|
||||
<CollapsibleFormWidget
|
||||
fontSize="x-small"
|
||||
isError={true}
|
||||
subtitle="Yes"
|
||||
title="Thumbnail"
|
||||
>
|
||||
<ErrorAlert
|
||||
dismissError={[Function]}
|
||||
hideHeading={true}
|
||||
isError={false}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="The file size for thumbnails must be larger than 2 KB or less than 2 MB. Please resize your image and try again."
|
||||
description=" Message presented to user when file size of image is less than 2 KB or larger than 2 MB"
|
||||
id="authoring.videoeditor.thumbnail.error.fileSizeError"
|
||||
/>
|
||||
</ErrorAlert>
|
||||
<Stack
|
||||
direction="horizontal"
|
||||
gap={3}
|
||||
>
|
||||
<Image
|
||||
alt="Image used as thumbnail for video"
|
||||
className="w-75"
|
||||
fluid={true}
|
||||
src="sOMeUrl"
|
||||
thumbnail={true}
|
||||
/>
|
||||
<IconButtonWithTooltip
|
||||
iconAs="Icon"
|
||||
onClick={[Function]}
|
||||
tooltipContent="Delete"
|
||||
tooltipPlacement="top"
|
||||
/>
|
||||
</Stack>
|
||||
</CollapsibleFormWidget>
|
||||
`;
|
||||
|
||||
exports[`ThumbnailWidget snapshots snapshots: renders as expected where videoId is valid and no thumbnail 1`] = `
|
||||
<CollapsibleFormWidget
|
||||
fontSize="x-small"
|
||||
isError={true}
|
||||
subtitle="None"
|
||||
title="Thumbnail"
|
||||
>
|
||||
<ErrorAlert
|
||||
dismissError={[Function]}
|
||||
hideHeading={true}
|
||||
isError={false}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="The file size for thumbnails must be larger than 2 KB or less than 2 MB. Please resize your image and try again."
|
||||
description=" Message presented to user when file size of image is less than 2 KB or larger than 2 MB"
|
||||
id="authoring.videoeditor.thumbnail.error.fileSizeError"
|
||||
/>
|
||||
</ErrorAlert>
|
||||
<Stack
|
||||
gap={4}
|
||||
>
|
||||
<div
|
||||
className="text-center"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Upload an image for learners to see before playing the video."
|
||||
description="Message for adding thumbnail"
|
||||
id="authoring.videoeditor.thumbnail.upload.message"
|
||||
/>
|
||||
<div
|
||||
className="text-primary-300"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Images must have an aspect ratio of 16:9 (1280x720 px recommended)"
|
||||
description="Message for thumbnail aspectRequirements"
|
||||
id="authoring.videoeditor.thumbnail.upload.aspectRequirements"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<FileInput
|
||||
acceptedFiles=".gif,.jpg,.jpeg,.png,.bmp,.bmp2"
|
||||
fileInput={
|
||||
{
|
||||
"addFile": [Function],
|
||||
"click": [Function],
|
||||
"ref": {
|
||||
"current": undefined,
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
className="text-primary-500 font-weight-bold justify-content-start pl-0"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
size="sm"
|
||||
variant="link"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Upload thumbnail"
|
||||
description="Label for upload button"
|
||||
id="authoring.videoeditor.thumbnail.upload.label"
|
||||
/>
|
||||
</Button>
|
||||
</Stack>
|
||||
</CollapsibleFormWidget>
|
||||
`;
|
||||
|
||||
exports[`ThumbnailWidget snapshots snapshots: renders as expected with a thumbnail provided 1`] = `
|
||||
<CollapsibleFormWidget
|
||||
fontSize="x-small"
|
||||
isError={true}
|
||||
subtitle="Yes"
|
||||
title="Thumbnail"
|
||||
>
|
||||
<ErrorAlert
|
||||
dismissError={[Function]}
|
||||
hideHeading={true}
|
||||
isError={false}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="The file size for thumbnails must be larger than 2 KB or less than 2 MB. Please resize your image and try again."
|
||||
description=" Message presented to user when file size of image is less than 2 KB or larger than 2 MB"
|
||||
id="authoring.videoeditor.thumbnail.error.fileSizeError"
|
||||
/>
|
||||
</ErrorAlert>
|
||||
<Alert
|
||||
variant="light"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Select a video from your library to enable this feature (applies only to courses that run on the edx.org site)."
|
||||
description="Message for unavailable thumbnail widget"
|
||||
id="authoring.videoeditor.thumbnail.unavailable.message"
|
||||
/>
|
||||
</Alert>
|
||||
<Stack
|
||||
direction="horizontal"
|
||||
gap={3}
|
||||
>
|
||||
<Image
|
||||
alt="Image used as thumbnail for video"
|
||||
className="w-75"
|
||||
fluid={true}
|
||||
src="sOMeUrl"
|
||||
thumbnail={true}
|
||||
/>
|
||||
</Stack>
|
||||
</CollapsibleFormWidget>
|
||||
`;
|
||||
|
||||
exports[`ThumbnailWidget snapshots snapshots: renders as expected with default props 1`] = `null`;
|
||||
|
||||
exports[`ThumbnailWidget snapshots snapshots: renders as expected with isLibrary true 1`] = `null`;
|
||||
@@ -1,106 +0,0 @@
|
||||
import 'CourseAuthoring/editors/setupEditorTest';
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
|
||||
import { formatMessage } from '../../../../../../testUtils';
|
||||
import { selectors } from '../../../../../../data/redux';
|
||||
import { ThumbnailWidgetInternal as ThumbnailWidget, mapStateToProps, mapDispatchToProps } from '.';
|
||||
|
||||
jest.mock('react', () => ({
|
||||
...jest.requireActual('react'),
|
||||
useContext: jest.fn(() => ({ thumbnail: ['error.thumbnail', jest.fn().mockName('error.setThumbnail')] })),
|
||||
}));
|
||||
jest.mock('../../../../../../data/redux', () => ({
|
||||
actions: {
|
||||
video: {
|
||||
updateField: jest.fn().mockName('actions.video.updateField'),
|
||||
},
|
||||
},
|
||||
selectors: {
|
||||
video: {
|
||||
allowThumbnailUpload: jest.fn(state => ({ allowThumbnailUpload: state })),
|
||||
thumbnail: jest.fn(state => ({ thumbnail: state })),
|
||||
videoId: jest.fn(state => ({ videoId: state })),
|
||||
},
|
||||
app: {
|
||||
isLibrary: jest.fn(state => ({ isLibrary: state })),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('../../../../../../data/services/cms/api', () => ({
|
||||
isEdxVideo: (args) => (args),
|
||||
}));
|
||||
|
||||
describe('ThumbnailWidget', () => {
|
||||
const props = {
|
||||
error: {},
|
||||
title: 'tiTLE',
|
||||
intl: { formatMessage },
|
||||
isLibrary: false,
|
||||
allowThumbnailUpload: false,
|
||||
thumbnail: null,
|
||||
videoId: '',
|
||||
updateField: jest.fn().mockName('args.updateField'),
|
||||
};
|
||||
describe('snapshots', () => {
|
||||
test('snapshots: renders as expected with default props', () => {
|
||||
expect(
|
||||
shallow(<ThumbnailWidget {...props} />).snapshot,
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
test('snapshots: renders as expected with isLibrary true', () => {
|
||||
expect(
|
||||
shallow(<ThumbnailWidget {...props} isLibrary />).snapshot,
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
test('snapshots: renders as expected with a thumbnail provided', () => {
|
||||
expect(
|
||||
shallow(<ThumbnailWidget {...props} thumbnail="sOMeUrl" videoId="sOMeViDEoID" />).snapshot,
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
test('snapshots: renders as expected where thumbnail uploads are allowed', () => {
|
||||
expect(
|
||||
shallow(<ThumbnailWidget {...props} thumbnail="sOMeUrl" allowThumbnailUpload />).snapshot,
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
test('snapshots: renders as expected where videoId is valid', () => {
|
||||
expect(
|
||||
shallow(<ThumbnailWidget {...props} thumbnail="sOMeUrl" allowThumbnailUpload videoId="sOMeViDEoID" />).snapshot,
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
test('snapshots: renders as expected where videoId is valid and no thumbnail', () => {
|
||||
expect(
|
||||
shallow(<ThumbnailWidget {...props} allowThumbnailUpload videoId="sOMeViDEoID" />).snapshot,
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
describe('mapStateToProps', () => {
|
||||
const testState = { A: 'pple', B: 'anana', C: 'ucumber' };
|
||||
test('isLibrary from app.isLibrary', () => {
|
||||
expect(
|
||||
mapStateToProps(testState).isLibrary,
|
||||
).toEqual(selectors.app.isLibrary(testState));
|
||||
});
|
||||
test('allowThumbnailUpload from video.allowThumbnailUpload', () => {
|
||||
expect(
|
||||
mapStateToProps(testState).allowThumbnailUpload,
|
||||
).toEqual(selectors.video.allowThumbnailUpload(testState));
|
||||
});
|
||||
test('thumbnail from video.thumbnail', () => {
|
||||
expect(
|
||||
mapStateToProps(testState).thumbnail,
|
||||
).toEqual(selectors.video.thumbnail(testState));
|
||||
});
|
||||
test('videoId from video.videoId', () => {
|
||||
expect(
|
||||
mapStateToProps(testState).videoId,
|
||||
).toEqual(selectors.video.videoId(testState));
|
||||
});
|
||||
});
|
||||
describe('mapDispatchToProps', () => {
|
||||
test('mapDispatchToProps to equal an empty object', () => {
|
||||
expect(mapDispatchToProps).toEqual({});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,75 @@
|
||||
import React from 'react';
|
||||
import { render, screen, initializeMocks } from '@src/testUtils';
|
||||
import { formatMessage } from '../../../../../../testUtils';
|
||||
import { ThumbnailWidgetInternal as ThumbnailWidget } from '.';
|
||||
|
||||
jest.mock('../../../../../../data/redux', () => ({
|
||||
actions: {
|
||||
video: {
|
||||
updateField: jest.fn().mockName('actions.video.updateField'),
|
||||
},
|
||||
},
|
||||
selectors: {
|
||||
video: {
|
||||
allowThumbnailUpload: jest.fn(state => ({ allowThumbnailUpload: state })),
|
||||
thumbnail: jest.fn(state => ({ thumbnail: state })),
|
||||
videoId: jest.fn(state => ({ videoId: state })),
|
||||
},
|
||||
app: {
|
||||
isLibrary: jest.fn(state => ({ isLibrary: state })),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('../../../../../../data/services/cms/api', () => ({
|
||||
isEdxVideo: (args) => (args),
|
||||
}));
|
||||
|
||||
describe('ThumbnailWidget', () => {
|
||||
const props = {
|
||||
error: {},
|
||||
title: 'tiTLE',
|
||||
intl: { formatMessage },
|
||||
isLibrary: false,
|
||||
allowThumbnailUpload: false,
|
||||
thumbnail: '',
|
||||
videoId: '',
|
||||
updateField: jest.fn().mockName('args.updateField'),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
initializeMocks();
|
||||
});
|
||||
|
||||
describe('snapshots', () => {
|
||||
test('snapshots: renders as expected with default props', () => {
|
||||
const { container } = render(<ThumbnailWidget {...props} />);
|
||||
const reduxWrapper = container.getRootNode();
|
||||
expect(reduxWrapper.textContent).toBe(null);
|
||||
});
|
||||
test('snapshots: renders as expected with isLibrary true', () => {
|
||||
const { container } = render(<ThumbnailWidget {...props} isLibrary />);
|
||||
const reduxWrapper = container.getRootNode();
|
||||
expect(reduxWrapper.textContent).toBe(null);
|
||||
});
|
||||
test('snapshots: renders as expected with a thumbnail provided', () => {
|
||||
render(<ThumbnailWidget {...props} thumbnail="sOMeUrl" videoId="sOMeViDEoID" />);
|
||||
expect(screen.getByRole('img', { name: 'Image used as thumbnail for video' })).toBeInTheDocument();
|
||||
});
|
||||
test('snapshots: renders as expected where thumbnail uploads are allowed', () => {
|
||||
const { container } = render(<ThumbnailWidget {...props} thumbnail="sOMeUrl" videoId="sOMeViDEoID" allowThumbnailUpload />);
|
||||
const reduxWrapper = container.getRootNode();
|
||||
expect(reduxWrapper.textContent).toBe(null);
|
||||
});
|
||||
test('snapshots: renders as expected where videoId is valid', () => {
|
||||
render(<ThumbnailWidget {...props} thumbnail="sOMeUrl" allowThumbnailUpload videoId="sOMeViDEoID" />);
|
||||
expect(screen.getByRole('img', { name: 'Image used as thumbnail for video' })).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: 'Thumbnail' })).toBeInTheDocument();
|
||||
});
|
||||
test('snapshots: renders as expected where videoId is valid and no thumbnail', () => {
|
||||
render(<ThumbnailWidget {...props} allowThumbnailUpload videoId="sOMeViDEoID" />);
|
||||
expect(screen.getByRole('button', { name: 'Thumbnail' })).toBeInTheDocument();
|
||||
expect(screen.queryByRole('img', { name: 'Image used as thumbnail for video' })).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,317 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`VideoSourceWidget snapshots snapshots: renders as expected with default props 1`] = `
|
||||
<CollapsibleFormWidget
|
||||
fontSize="x-small"
|
||||
subtitle={null}
|
||||
title="Video source"
|
||||
>
|
||||
<ErrorAlert
|
||||
dismissError={[Function]}
|
||||
hideHeading={true}
|
||||
isError={false}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="The Video ID field has changed, please check the Video URL and fallback URL values and update them if necessary."
|
||||
description="Body message for the alert that appears when the video id has been changed."
|
||||
id="authoring.videoeditor.videoIdChangeAlert.message"
|
||||
/>
|
||||
</ErrorAlert>
|
||||
<div
|
||||
className="border-primary-100 border-bottom pb-4"
|
||||
>
|
||||
<Form.Group>
|
||||
<Form.Control
|
||||
floatingLabel="Video ID"
|
||||
onBlur={[Function]}
|
||||
onChange={[MockFunction]}
|
||||
value=""
|
||||
/>
|
||||
<Form.Control.Feedback
|
||||
className="text-primary-300 mb-4"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="If you were assigned a video ID by edX, enter the ID here."
|
||||
description="Feedback for video ID field"
|
||||
id="authoring.videoeditor.videoSource.videoId.feedback"
|
||||
/>
|
||||
</Form.Control.Feedback>
|
||||
</Form.Group>
|
||||
<Form.Group>
|
||||
<Form.Control
|
||||
floatingLabel="Video URL"
|
||||
onBlur={[Function]}
|
||||
onChange={[MockFunction]}
|
||||
value=""
|
||||
/>
|
||||
<Form.Control.Feedback
|
||||
className="text-primary-300"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="The URL for your video. This can be a YouTube URL, or a link
|
||||
to an .mp4, .ogg, or .webm video file hosted elsewhere on the internet."
|
||||
description="Feedback for video URL field"
|
||||
id="authoring.videoeditor.videoSource.videoUrl.feedback"
|
||||
/>
|
||||
</Form.Control.Feedback>
|
||||
</Form.Group>
|
||||
</div>
|
||||
<div
|
||||
className="mt-4"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Fallback videos"
|
||||
description="Title for the fallback videos section"
|
||||
id="authoring.videoeditor.videoSource.fallbackVideo.title"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="mt-3"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="To be sure all learners can access the video, it is recommended to provide additional videos in both .mp4 and
|
||||
.webm formats. The first listed video compatible with the learner's device will play."
|
||||
description="Test explaining reason for fallback videos"
|
||||
id="authoring.videoeditor.videoSource.fallbackVideo.message"
|
||||
/>
|
||||
</div>
|
||||
<Form.Row
|
||||
className="mt-3.5 mx-0 flex-nowrap"
|
||||
>
|
||||
<Form.Group>
|
||||
<Form.Control
|
||||
floatingLabel="Video URL"
|
||||
/>
|
||||
<IconButtonWithTooltip
|
||||
alt="Delete"
|
||||
iconAs="Icon"
|
||||
key="top-delete-somEUrL"
|
||||
onClick={[Function]}
|
||||
tooltipContent="Delete"
|
||||
tooltipPlacement="top"
|
||||
/>
|
||||
</Form.Group>
|
||||
</Form.Row>
|
||||
<ActionRow
|
||||
className="mt-4.5"
|
||||
>
|
||||
<Form.Group>
|
||||
<Form.Checkbox
|
||||
checked={false}
|
||||
className="decorative-control-label"
|
||||
onChange={[MockFunction]}
|
||||
>
|
||||
<div
|
||||
className="small text-gray-700"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Allow video downloads"
|
||||
description="Label for allow video downloads checkbox"
|
||||
id="authoring.videoeditor.videoSource.allowDownloadCheckboxLabel"
|
||||
/>
|
||||
</div>
|
||||
</Form.Checkbox>
|
||||
<OverlayTrigger
|
||||
key="top"
|
||||
overlay={
|
||||
<Tooltip
|
||||
id="tooltip-top"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Allow learners to download versions of this video in
|
||||
different formats if they cannot use the edX video player or do not have
|
||||
access to YouTube."
|
||||
description="Message for allow video downloads checkbox"
|
||||
id="authoring.videoeditor.videoSource.allowDownloadTooltipMessage"
|
||||
/>
|
||||
</Tooltip>
|
||||
}
|
||||
placement="top"
|
||||
>
|
||||
<Icon
|
||||
style={
|
||||
{
|
||||
"height": "16px",
|
||||
"width": "16px",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
</Form.Group>
|
||||
<ActionRow.Spacer />
|
||||
</ActionRow>
|
||||
<div
|
||||
className="my-4 border-primary-100 border-bottom"
|
||||
/>
|
||||
<Button
|
||||
className="text-primary-500 font-weight-bold pl-0"
|
||||
onClick={[Function]}
|
||||
size="sm"
|
||||
variant="link"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Add a video URL"
|
||||
description="Label for add a video URL button"
|
||||
id="authoring.videoeditor.videoSource.fallbackVideo.addButtonLabel"
|
||||
/>
|
||||
</Button>
|
||||
</CollapsibleFormWidget>
|
||||
`;
|
||||
|
||||
exports[`VideoSourceWidget snapshots snapshots: renders as expected with videoSharingEnabledForCourse=true 1`] = `
|
||||
<CollapsibleFormWidget
|
||||
fontSize="x-small"
|
||||
subtitle={null}
|
||||
title="Video source"
|
||||
>
|
||||
<ErrorAlert
|
||||
dismissError={[Function]}
|
||||
hideHeading={true}
|
||||
isError={false}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="The Video ID field has changed, please check the Video URL and fallback URL values and update them if necessary."
|
||||
description="Body message for the alert that appears when the video id has been changed."
|
||||
id="authoring.videoeditor.videoIdChangeAlert.message"
|
||||
/>
|
||||
</ErrorAlert>
|
||||
<div
|
||||
className="border-primary-100 border-bottom pb-4"
|
||||
>
|
||||
<Form.Group>
|
||||
<Form.Control
|
||||
floatingLabel="Video ID"
|
||||
onBlur={[Function]}
|
||||
onChange={[MockFunction]}
|
||||
value=""
|
||||
/>
|
||||
<Form.Control.Feedback
|
||||
className="text-primary-300 mb-4"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="If you were assigned a video ID by edX, enter the ID here."
|
||||
description="Feedback for video ID field"
|
||||
id="authoring.videoeditor.videoSource.videoId.feedback"
|
||||
/>
|
||||
</Form.Control.Feedback>
|
||||
</Form.Group>
|
||||
<Form.Group>
|
||||
<Form.Control
|
||||
floatingLabel="Video URL"
|
||||
onBlur={[Function]}
|
||||
onChange={[MockFunction]}
|
||||
value=""
|
||||
/>
|
||||
<Form.Control.Feedback
|
||||
className="text-primary-300"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="The URL for your video. This can be a YouTube URL, or a link
|
||||
to an .mp4, .ogg, or .webm video file hosted elsewhere on the internet."
|
||||
description="Feedback for video URL field"
|
||||
id="authoring.videoeditor.videoSource.videoUrl.feedback"
|
||||
/>
|
||||
</Form.Control.Feedback>
|
||||
</Form.Group>
|
||||
</div>
|
||||
<div
|
||||
className="mt-4"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Fallback videos"
|
||||
description="Title for the fallback videos section"
|
||||
id="authoring.videoeditor.videoSource.fallbackVideo.title"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="mt-3"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="To be sure all learners can access the video, it is recommended to provide additional videos in both .mp4 and
|
||||
.webm formats. The first listed video compatible with the learner's device will play."
|
||||
description="Test explaining reason for fallback videos"
|
||||
id="authoring.videoeditor.videoSource.fallbackVideo.message"
|
||||
/>
|
||||
</div>
|
||||
<Form.Row
|
||||
className="mt-3.5 mx-0 flex-nowrap"
|
||||
>
|
||||
<Form.Group>
|
||||
<Form.Control
|
||||
floatingLabel="Video URL"
|
||||
/>
|
||||
<IconButtonWithTooltip
|
||||
alt="Delete"
|
||||
iconAs="Icon"
|
||||
key="top-delete-somEUrL"
|
||||
onClick={[Function]}
|
||||
tooltipContent="Delete"
|
||||
tooltipPlacement="top"
|
||||
/>
|
||||
</Form.Group>
|
||||
</Form.Row>
|
||||
<ActionRow
|
||||
className="mt-4.5"
|
||||
>
|
||||
<Form.Group>
|
||||
<Form.Checkbox
|
||||
checked={false}
|
||||
className="decorative-control-label"
|
||||
onChange={[MockFunction]}
|
||||
>
|
||||
<div
|
||||
className="small text-gray-700"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Allow video downloads"
|
||||
description="Label for allow video downloads checkbox"
|
||||
id="authoring.videoeditor.videoSource.allowDownloadCheckboxLabel"
|
||||
/>
|
||||
</div>
|
||||
</Form.Checkbox>
|
||||
<OverlayTrigger
|
||||
key="top"
|
||||
overlay={
|
||||
<Tooltip
|
||||
id="tooltip-top"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Allow learners to download versions of this video in
|
||||
different formats if they cannot use the edX video player or do not have
|
||||
access to YouTube."
|
||||
description="Message for allow video downloads checkbox"
|
||||
id="authoring.videoeditor.videoSource.allowDownloadTooltipMessage"
|
||||
/>
|
||||
</Tooltip>
|
||||
}
|
||||
placement="top"
|
||||
>
|
||||
<Icon
|
||||
style={
|
||||
{
|
||||
"height": "16px",
|
||||
"width": "16px",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
</Form.Group>
|
||||
<ActionRow.Spacer />
|
||||
</ActionRow>
|
||||
<div
|
||||
className="my-4 border-primary-100 border-bottom"
|
||||
/>
|
||||
<Button
|
||||
className="text-primary-500 font-weight-bold pl-0"
|
||||
onClick={[Function]}
|
||||
size="sm"
|
||||
variant="link"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Add a video URL"
|
||||
description="Label for add a video URL button"
|
||||
id="authoring.videoeditor.videoSource.fallbackVideo.addButtonLabel"
|
||||
/>
|
||||
</Button>
|
||||
</CollapsibleFormWidget>
|
||||
`;
|
||||
@@ -13,8 +13,7 @@ import {
|
||||
import { DeleteOutline, InfoOutline, Add } from '@openedx/paragon/icons';
|
||||
import {
|
||||
FormattedMessage,
|
||||
injectIntl,
|
||||
intlShape,
|
||||
useIntl,
|
||||
} from '@edx/frontend-platform/i18n';
|
||||
|
||||
import * as widgetHooks from '../hooks';
|
||||
@@ -27,10 +26,8 @@ import CollapsibleFormWidget from '../CollapsibleFormWidget';
|
||||
/**
|
||||
* Collapsible Form widget controlling video source as well as fallback sources
|
||||
*/
|
||||
const VideoSourceWidget = ({
|
||||
// injected
|
||||
intl,
|
||||
}) => {
|
||||
const VideoSourceWidget = () => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useDispatch();
|
||||
const {
|
||||
videoId,
|
||||
@@ -160,10 +157,5 @@ const VideoSourceWidget = ({
|
||||
</CollapsibleFormWidget>
|
||||
);
|
||||
};
|
||||
VideoSourceWidget.propTypes = {
|
||||
// injected
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export const VideoSourceWidgetInternal = VideoSourceWidget; // For testing only
|
||||
export default injectIntl(VideoSourceWidget);
|
||||
export default VideoSourceWidget;
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
import 'CourseAuthoring/editors/setupEditorTest';
|
||||
import React from 'react';
|
||||
import { dispatch } from 'react-redux';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
|
||||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
import { formatMessage } from '../../../../../../testUtils';
|
||||
import { VideoSourceWidgetInternal as VideoSourceWidget } from '.';
|
||||
import * as hooks from './hooks';
|
||||
import messages from './messages';
|
||||
|
||||
jest.mock('react-redux', () => {
|
||||
const dispatchFn = jest.fn();
|
||||
return {
|
||||
...jest.requireActual('react-redux'),
|
||||
dispatch: dispatchFn,
|
||||
useDispatch: jest.fn(() => dispatchFn),
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('../hooks', () => ({
|
||||
selectorKeys: ['soMEkEy'],
|
||||
widgetValues: jest.fn().mockReturnValue({
|
||||
videoId: { onChange: jest.fn(), onBlur: jest.fn(), local: '' },
|
||||
videoSource: { onChange: jest.fn(), onBlur: jest.fn(), local: '' },
|
||||
fallbackVideos: {
|
||||
formValue: ['somEUrL'],
|
||||
onChange: jest.fn(),
|
||||
onBlur: jest.fn(),
|
||||
local: '',
|
||||
},
|
||||
allowVideoDownloads: { local: false, onCheckedChange: jest.fn() },
|
||||
allowVideoSharing: { local: false, onCheckedChange: jest.fn() },
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('./hooks', () => ({
|
||||
videoIdChangeAlert: jest.fn().mockReturnValue({
|
||||
videoIdChangeAlert: {
|
||||
set: (args) => ({ set: args }),
|
||||
show: false,
|
||||
dismiss: (args) => ({ dismiss: args }),
|
||||
},
|
||||
}),
|
||||
sourceHooks: jest.fn().mockReturnValue({
|
||||
updateVideoId: (args) => ({ updateVideoId: args }),
|
||||
updateVideoURL: jest.fn().mockName('updateVideoURL'),
|
||||
}),
|
||||
fallbackHooks: jest.fn().mockReturnValue({
|
||||
addFallbackVideo: jest.fn().mockName('addFallbackVideo'),
|
||||
deleteFallbackVideo: jest.fn().mockName('deleteFallbackVideo'),
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('../../../../../../data/redux', () => ({
|
||||
selectors: {
|
||||
video: {
|
||||
allow: jest.fn(state => ({ allowTranscriptImport: state })),
|
||||
},
|
||||
requests: {
|
||||
isFailed: jest.fn(state => ({ isFailed: state })),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
describe('VideoSourceWidget', () => {
|
||||
const props = {
|
||||
// inject
|
||||
intl: { formatMessage },
|
||||
// redux
|
||||
videoSharingEnabledForCourse: false,
|
||||
};
|
||||
|
||||
describe('snapshots', () => {
|
||||
describe('snapshots: renders as expected with', () => {
|
||||
it('default props', () => {
|
||||
expect(
|
||||
shallow(<VideoSourceWidget {...props} />).snapshot,
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
it('videoSharingEnabledForCourse=true', () => {
|
||||
const newProps = { ...props, videoSharingEnabledForCourse: true };
|
||||
expect(
|
||||
shallow(<VideoSourceWidget {...newProps} />).snapshot,
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('behavior inspection', () => {
|
||||
let el;
|
||||
let hook;
|
||||
beforeEach(() => {
|
||||
hook = hooks.sourceHooks({ dispatch, previousVideoId: 'someVideoId', setAlert: jest.fn() });
|
||||
el = shallow(<VideoSourceWidget {...props} />);
|
||||
});
|
||||
test('updateVideoId is tied to id field onBlur', () => {
|
||||
const expected = hook.updateVideoId;
|
||||
expect(el
|
||||
// eslint-disable-next-line
|
||||
.shallowWrapper.props.children[1].props.children[0].props.children[0]
|
||||
.props.onBlur).toEqual(expected);
|
||||
});
|
||||
test('updateVideoURL is tied to url field onBlur', () => {
|
||||
const control = el.shallowWrapper.props.children[1].props.children[1].props.children[0];
|
||||
expect(control.props.floatingLabel).toEqual('Video URL');
|
||||
control.props.onBlur('onBlur event');
|
||||
expect(hook.updateVideoURL).toHaveBeenCalledWith('onBlur event', '');
|
||||
});
|
||||
});
|
||||
|
||||
describe('VideoSourceWidget', () => {
|
||||
it('calls addFallbackVideo when the add button is clicked', () => {
|
||||
// eslint-disable-next-line global-require
|
||||
const { fallbackHooks } = require('./hooks');
|
||||
const { addFallbackVideo } = fallbackHooks();
|
||||
|
||||
render(
|
||||
<IntlProvider locale="en" messages={messages}>
|
||||
<VideoSourceWidget intl={{ formatMessage: ({ defaultMessage }) => defaultMessage }} />
|
||||
</IntlProvider>,
|
||||
);
|
||||
|
||||
// Find the button by its text (from messages.addButtonLabel)
|
||||
const addButton = screen.getByRole('button');
|
||||
|
||||
fireEvent.click(addButton);
|
||||
|
||||
expect(addFallbackVideo).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,248 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
render, screen, fireEvent, initializeMocks,
|
||||
} from '@src/testUtils';
|
||||
import VideoSourceWidget from '.';
|
||||
import * as hooks from './hooks';
|
||||
import * as widgetHooks from '../hooks';
|
||||
|
||||
describe('VideoSourceWidget', () => {
|
||||
let widgetValuesSpy;
|
||||
let videoIdChangeAlertSpy;
|
||||
let sourceHooksSpy;
|
||||
let fallbackHooksSpy;
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
widgetValuesSpy = jest.spyOn(widgetHooks, 'widgetValues');
|
||||
videoIdChangeAlertSpy = jest.spyOn(hooks, 'videoIdChangeAlert');
|
||||
sourceHooksSpy = jest.spyOn(hooks, 'sourceHooks');
|
||||
fallbackHooksSpy = jest.spyOn(hooks, 'fallbackHooks');
|
||||
initializeMocks();
|
||||
});
|
||||
|
||||
it('renders all main fields and labels', () => {
|
||||
widgetValuesSpy.mockReturnValue({
|
||||
videoId: {
|
||||
onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
|
||||
},
|
||||
videoSource: {
|
||||
onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
|
||||
},
|
||||
fallbackVideos: {
|
||||
formValue: [], onChange: jest.fn(), onBlur: jest.fn(), local: [],
|
||||
},
|
||||
allowVideoDownloads: { local: false, onCheckedChange: jest.fn() },
|
||||
});
|
||||
videoIdChangeAlertSpy.mockReturnValue({
|
||||
videoIdChangeAlert: { set: jest.fn(), show: false, dismiss: jest.fn() },
|
||||
});
|
||||
sourceHooksSpy.mockReturnValue({
|
||||
updateVideoId: jest.fn(),
|
||||
updateVideoURL: jest.fn(),
|
||||
});
|
||||
fallbackHooksSpy.mockReturnValue({
|
||||
addFallbackVideo: jest.fn(),
|
||||
deleteFallbackVideo: jest.fn(),
|
||||
});
|
||||
|
||||
render(<VideoSourceWidget />);
|
||||
expect(screen.getByText('Video source')).toBeInTheDocument();
|
||||
expect(screen.getByLabelText('Video ID')).toBeInTheDocument();
|
||||
expect(screen.getByLabelText('Video URL')).toBeInTheDocument();
|
||||
expect(screen.getByText('Allow video downloads')).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: /add/i })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('calls updateVideoId on videoId field blur', () => {
|
||||
const updateVideoId = jest.fn();
|
||||
widgetValuesSpy.mockReturnValue({
|
||||
videoId: {
|
||||
onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
|
||||
},
|
||||
videoSource: {
|
||||
onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
|
||||
},
|
||||
fallbackVideos: {
|
||||
formValue: [], onChange: jest.fn(), onBlur: jest.fn(), local: [],
|
||||
},
|
||||
allowVideoDownloads: { local: false, onCheckedChange: jest.fn() },
|
||||
});
|
||||
videoIdChangeAlertSpy.mockReturnValue({
|
||||
videoIdChangeAlert: { set: jest.fn(), show: false, dismiss: jest.fn() },
|
||||
});
|
||||
sourceHooksSpy.mockReturnValue({
|
||||
updateVideoId,
|
||||
updateVideoURL: jest.fn(),
|
||||
});
|
||||
fallbackHooksSpy.mockReturnValue({
|
||||
addFallbackVideo: jest.fn(),
|
||||
deleteFallbackVideo: jest.fn(),
|
||||
});
|
||||
|
||||
render(<VideoSourceWidget />);
|
||||
const videoIdInput = screen.getByLabelText('Video ID');
|
||||
fireEvent.blur(videoIdInput);
|
||||
expect(updateVideoId).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls updateVideoURL on videoSource field blur', () => {
|
||||
const updateVideoURL = jest.fn();
|
||||
widgetValuesSpy.mockReturnValue({
|
||||
videoId: {
|
||||
onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
|
||||
},
|
||||
videoSource: {
|
||||
onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
|
||||
},
|
||||
fallbackVideos: {
|
||||
formValue: [], onChange: jest.fn(), onBlur: jest.fn(), local: [],
|
||||
},
|
||||
allowVideoDownloads: { local: false, onCheckedChange: jest.fn() },
|
||||
});
|
||||
videoIdChangeAlertSpy.mockReturnValue({
|
||||
videoIdChangeAlert: { set: jest.fn(), show: false, dismiss: jest.fn() },
|
||||
});
|
||||
sourceHooksSpy.mockReturnValue({
|
||||
updateVideoId: jest.fn(),
|
||||
updateVideoURL,
|
||||
});
|
||||
fallbackHooksSpy.mockReturnValue({
|
||||
addFallbackVideo: jest.fn(),
|
||||
deleteFallbackVideo: jest.fn(),
|
||||
});
|
||||
|
||||
render(<VideoSourceWidget />);
|
||||
const videoUrlInput = screen.getByLabelText('Video URL');
|
||||
fireEvent.blur(videoUrlInput);
|
||||
expect(updateVideoURL).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('renders fallback video fields and calls deleteFallbackVideo on delete', () => {
|
||||
const deleteFallbackVideo = jest.fn();
|
||||
widgetValuesSpy.mockReturnValue({
|
||||
videoId: {
|
||||
onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
|
||||
},
|
||||
videoSource: {
|
||||
onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
|
||||
},
|
||||
fallbackVideos: {
|
||||
formValue: ['url1', 'url2'],
|
||||
onChange: () => jest.fn(),
|
||||
onBlur: () => jest.fn(),
|
||||
local: ['url1', 'url2'],
|
||||
},
|
||||
allowVideoDownloads: { local: false, onCheckedChange: jest.fn() },
|
||||
});
|
||||
videoIdChangeAlertSpy.mockReturnValue({
|
||||
videoIdChangeAlert: { set: jest.fn(), show: false, dismiss: jest.fn() },
|
||||
});
|
||||
sourceHooksSpy.mockReturnValue({
|
||||
updateVideoId: jest.fn(),
|
||||
updateVideoURL: jest.fn(),
|
||||
});
|
||||
fallbackHooksSpy.mockReturnValue({
|
||||
addFallbackVideo: jest.fn(),
|
||||
deleteFallbackVideo,
|
||||
});
|
||||
|
||||
render(<VideoSourceWidget />);
|
||||
expect(screen.getAllByText('Video URL').length).toBe(3); // 1 main + 2 fallback
|
||||
const deleteButtons = screen.getAllByRole('button', { name: /delete/i });
|
||||
fireEvent.click(deleteButtons[0]);
|
||||
expect(deleteFallbackVideo).toHaveBeenCalledWith('url1');
|
||||
});
|
||||
|
||||
it('calls addFallbackVideo when add button is clicked', () => {
|
||||
const addFallbackVideo = jest.fn();
|
||||
widgetValuesSpy.mockReturnValue({
|
||||
videoId: {
|
||||
onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
|
||||
},
|
||||
videoSource: {
|
||||
onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
|
||||
},
|
||||
fallbackVideos: {
|
||||
formValue: [], onChange: jest.fn(), onBlur: jest.fn(), local: [],
|
||||
},
|
||||
allowVideoDownloads: { local: false, onCheckedChange: jest.fn() },
|
||||
});
|
||||
videoIdChangeAlertSpy.mockReturnValue({
|
||||
videoIdChangeAlert: { set: jest.fn(), show: false, dismiss: jest.fn() },
|
||||
});
|
||||
sourceHooksSpy.mockReturnValue({
|
||||
updateVideoId: jest.fn(),
|
||||
updateVideoURL: jest.fn(),
|
||||
});
|
||||
fallbackHooksSpy.mockReturnValue({
|
||||
addFallbackVideo,
|
||||
deleteFallbackVideo: jest.fn(),
|
||||
});
|
||||
|
||||
render(<VideoSourceWidget />);
|
||||
const addButton = screen.getByRole('button', { name: /add/i });
|
||||
fireEvent.click(addButton);
|
||||
expect(addFallbackVideo).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls allowDownload.onCheckedChange when checkbox is clicked', () => {
|
||||
const onCheckedChange = jest.fn();
|
||||
widgetValuesSpy.mockReturnValue({
|
||||
videoId: {
|
||||
onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
|
||||
},
|
||||
videoSource: {
|
||||
onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
|
||||
},
|
||||
fallbackVideos: {
|
||||
formValue: [], onChange: jest.fn(), onBlur: jest.fn(), local: [],
|
||||
},
|
||||
allowVideoDownloads: { local: false, onCheckedChange },
|
||||
});
|
||||
videoIdChangeAlertSpy.mockReturnValue({
|
||||
videoIdChangeAlert: { set: jest.fn(), show: false, dismiss: jest.fn() },
|
||||
});
|
||||
sourceHooksSpy.mockReturnValue({
|
||||
updateVideoId: jest.fn(),
|
||||
updateVideoURL: jest.fn(),
|
||||
});
|
||||
fallbackHooksSpy.mockReturnValue({
|
||||
addFallbackVideo: jest.fn(),
|
||||
deleteFallbackVideo: jest.fn(),
|
||||
});
|
||||
|
||||
render(<VideoSourceWidget />);
|
||||
const checkbox = screen.getByLabelText('Allow video downloads');
|
||||
fireEvent.click(checkbox);
|
||||
expect(onCheckedChange).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('shows error alert when videoIdChangeAlert.show is true', () => {
|
||||
widgetValuesSpy.mockReturnValue({
|
||||
videoId: {
|
||||
onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
|
||||
},
|
||||
videoSource: {
|
||||
onChange: jest.fn(), onBlur: jest.fn(), local: '', formValue: '',
|
||||
},
|
||||
fallbackVideos: {
|
||||
formValue: [], onChange: jest.fn(), onBlur: jest.fn(), local: [],
|
||||
},
|
||||
allowVideoDownloads: { local: false, onCheckedChange: jest.fn() },
|
||||
});
|
||||
videoIdChangeAlertSpy.mockReturnValue({
|
||||
videoIdChangeAlert: { set: jest.fn(), show: true, dismiss: jest.fn() },
|
||||
});
|
||||
sourceHooksSpy.mockReturnValue({
|
||||
updateVideoId: jest.fn(),
|
||||
updateVideoURL: jest.fn(),
|
||||
});
|
||||
fallbackHooksSpy.mockReturnValue({
|
||||
addFallbackVideo: jest.fn(),
|
||||
deleteFallbackVideo: jest.fn(),
|
||||
});
|
||||
|
||||
render(<VideoSourceWidget />);
|
||||
expect(screen.getByRole('alert')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -1,12 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`AdditionalCourseContentPluginSlot renders 1`] = `
|
||||
<PluginSlot
|
||||
id="org.openedx.frontend.authoring.additional_course_content_plugin.v1"
|
||||
idAliases={
|
||||
[
|
||||
"additional_course_content_plugin",
|
||||
]
|
||||
}
|
||||
/>
|
||||
`;
|
||||
@@ -1,15 +0,0 @@
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
import { AdditionalCourseContentPluginSlot } from '.';
|
||||
|
||||
jest.mock('@openedx/frontend-plugin-framework', () => ({
|
||||
PluginSlot: 'PluginSlot',
|
||||
}));
|
||||
|
||||
describe('AdditionalCourseContentPluginSlot', () => {
|
||||
beforeEach(() => jest.resetAllMocks());
|
||||
|
||||
it('renders', () => {
|
||||
const wrapper = shallow(<AdditionalCourseContentPluginSlot />);
|
||||
expect(wrapper.snapshot).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
import { render, initializeMocks } from '@src/testUtils';
|
||||
import { AdditionalCourseContentPluginSlot } from '.';
|
||||
|
||||
jest.mock('@openedx/frontend-plugin-framework', () => ({
|
||||
PluginSlot: 'PluginSlot',
|
||||
}));
|
||||
|
||||
describe('AdditionalCourseContentPluginSlot', () => {
|
||||
beforeEach(() => initializeMocks());
|
||||
|
||||
it('renders', () => {
|
||||
const expectedId = 'org.openedx.frontend.authoring.additional_course_content_plugin.v1';
|
||||
const { container } = render(<AdditionalCourseContentPluginSlot />);
|
||||
expect(container.querySelector('pluginslot')).toBeInTheDocument();
|
||||
expect(container.querySelector('pluginslot')).toHaveProperty('id', expectedId);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user