test: replacing snapshot tests with RTL tests part 12 (#2222)

This commit is contained in:
jacobo-dominguez-wgu
2025-07-07 16:25:27 -06:00
committed by GitHub
parent 8d86433748
commit a969de4d90
14 changed files with 673 additions and 2417 deletions

View File

@@ -1,451 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`SettingsWidget isLibrary snapshot: renders Settings widget for Advanced Problem with correct widgets 1`] = `
<div
className="settingsWidget ml-4"
>
<div
className="mb-3"
>
<TypeCard
problemType="stringresponse"
/>
</div>
<div
className="mt-3"
>
<HintsCard
images={{}}
isLibrary={true}
learningContextId="course+org+run"
problemType="stringresponse"
/>
</div>
<Fragment />
<div>
<Advanced
open={false}
>
<Body
className="collapsible-body small"
>
<Button
className="my-3 px-0 text-info-500"
size="inline"
variant="link"
>
<FormattedMessage
defaultMessage="Show advanced settings"
description="Button text to show advanced settings"
id="authoring.problemeditor.settings.showAdvancedButton"
/>
</Button>
</Body>
</Advanced>
</div>
<Advanced
open={true}
>
<Body
className="collapsible-body"
>
<div
className="my-3"
>
<SwitchEditorCard
editorType="advanced"
problemType="stringresponse"
/>
</div>
</Body>
</Advanced>
</div>
`;
exports[`SettingsWidget isLibrary snapshot: renders Settings widget page 1`] = `
<div
className="settingsWidget ml-4"
>
<div
className="mb-3"
>
<TypeCard
problemType="stringresponse"
/>
</div>
<div
className="mt-3"
>
<HintsCard
images={{}}
isLibrary={true}
learningContextId="course+org+run"
problemType="stringresponse"
/>
</div>
<Fragment />
<div>
<Advanced
open={true}
>
<Body
className="collapsible-body small"
>
<Button
className="my-3 px-0 text-info-500"
size="inline"
variant="link"
>
<FormattedMessage
defaultMessage="Show advanced settings"
description="Button text to show advanced settings"
id="authoring.problemeditor.settings.showAdvancedButton"
/>
</Button>
</Body>
</Advanced>
</div>
<Advanced
open={false}
>
<Body
className="collapsible-body"
>
<div
className="my-3"
>
<SwitchEditorCard
editorType="advanced"
problemType="stringresponse"
/>
</div>
</Body>
</Advanced>
</div>
`;
exports[`SettingsWidget isLibrary snapshot: renders Settings widget page advanced settings visible 1`] = `
<div
className="settingsWidget ml-4"
>
<div
className="mb-3"
>
<TypeCard
problemType="stringresponse"
/>
</div>
<div
className="mt-3"
>
<HintsCard
images={{}}
isLibrary={true}
learningContextId="course+org+run"
problemType="stringresponse"
/>
</div>
<Fragment />
<div>
<Advanced
open={false}
>
<Body
className="collapsible-body small"
>
<Button
className="my-3 px-0 text-info-500"
size="inline"
variant="link"
>
<FormattedMessage
defaultMessage="Show advanced settings"
description="Button text to show advanced settings"
id="authoring.problemeditor.settings.showAdvancedButton"
/>
</Button>
</Body>
</Advanced>
</div>
<Advanced
open={true}
>
<Body
className="collapsible-body"
>
<div
className="my-3"
>
<SwitchEditorCard
editorType="advanced"
problemType="stringresponse"
/>
</div>
</Body>
</Advanced>
</div>
`;
exports[`SettingsWidget snapshot snapshot: renders Settings widget for Advanced Problem with correct widgets 1`] = `
<div
className="settingsWidget ml-4"
>
<div
className="mb-3"
>
<TypeCard
problemType="stringresponse"
/>
</div>
<div
className="my-3"
>
<ScoringCard
defaultValue={2}
/>
</div>
<div
className="mt-3"
>
<HintsCard
images={{}}
isLibrary={false}
learningContextId="course+org+run"
problemType="stringresponse"
/>
</div>
<Fragment />
<div>
<Advanced
open={false}
>
<Body
className="collapsible-body small"
>
<Button
className="my-3 px-0 text-info-500"
size="inline"
variant="link"
>
<FormattedMessage
defaultMessage="Show advanced settings"
description="Button text to show advanced settings"
id="authoring.problemeditor.settings.showAdvancedButton"
/>
</Button>
</Body>
</Advanced>
</div>
<Advanced
open={true}
>
<Body
className="collapsible-body"
>
<div
className="my-3"
>
<ShowAnswerCard
defaultValue="finished"
/>
</div>
<div
className="my-3"
>
<ResetCard
defaultValue={false}
/>
</div>
<div
className="my-3"
>
<TimerCard />
</div>
<div
className="my-3"
>
<SwitchEditorCard
editorType="advanced"
problemType="stringresponse"
/>
</div>
</Body>
</Advanced>
</div>
`;
exports[`SettingsWidget snapshot snapshot: renders Settings widget page 1`] = `
<div
className="settingsWidget ml-4"
>
<div
className="mb-3"
>
<TypeCard
problemType="stringresponse"
/>
</div>
<div
className="my-3"
>
<ScoringCard
defaultValue={2}
/>
</div>
<div
className="mt-3"
>
<HintsCard
images={{}}
isLibrary={false}
learningContextId="course+org+run"
problemType="stringresponse"
/>
</div>
<Fragment />
<div>
<Advanced
open={true}
>
<Body
className="collapsible-body small"
>
<Button
className="my-3 px-0 text-info-500"
size="inline"
variant="link"
>
<FormattedMessage
defaultMessage="Show advanced settings"
description="Button text to show advanced settings"
id="authoring.problemeditor.settings.showAdvancedButton"
/>
</Button>
</Body>
</Advanced>
</div>
<Advanced
open={false}
>
<Body
className="collapsible-body"
>
<div
className="my-3"
>
<ShowAnswerCard
defaultValue="finished"
/>
</div>
<div
className="my-3"
>
<ResetCard
defaultValue={false}
/>
</div>
<div
className="my-3"
>
<TimerCard />
</div>
<div
className="my-3"
>
<SwitchEditorCard
editorType="advanced"
problemType="stringresponse"
/>
</div>
</Body>
</Advanced>
</div>
`;
exports[`SettingsWidget snapshot snapshot: renders Settings widget page advanced settings visible 1`] = `
<div
className="settingsWidget ml-4"
>
<div
className="mb-3"
>
<TypeCard
problemType="stringresponse"
/>
</div>
<div
className="my-3"
>
<ScoringCard
defaultValue={2}
/>
</div>
<div
className="mt-3"
>
<HintsCard
images={{}}
isLibrary={false}
learningContextId="course+org+run"
problemType="stringresponse"
/>
</div>
<Fragment />
<div>
<Advanced
open={false}
>
<Body
className="collapsible-body small"
>
<Button
className="my-3 px-0 text-info-500"
size="inline"
variant="link"
>
<FormattedMessage
defaultMessage="Show advanced settings"
description="Button text to show advanced settings"
id="authoring.problemeditor.settings.showAdvancedButton"
/>
</Button>
</Body>
</Advanced>
</div>
<Advanced
open={true}
>
<Body
className="collapsible-body"
>
<div
className="my-3"
>
<ShowAnswerCard
defaultValue="finished"
/>
</div>
<div
className="my-3"
>
<ResetCard
defaultValue={false}
/>
</div>
<div
className="my-3"
>
<TimerCard />
</div>
<div
className="my-3"
>
<SwitchEditorCard
editorType="advanced"
problemType="stringresponse"
/>
</div>
</Body>
</Advanced>
</div>
`;

View File

@@ -1,133 +0,0 @@
import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { showAdvancedSettingsCards } from './hooks';
import { SettingsWidgetInternal as SettingsWidget, mapDispatchToProps } from '.';
import { ProblemTypeKeys } from '../../../../../data/constants/problem';
import { actions } from '../../../../../data/redux';
jest.mock('./hooks', () => ({
showAdvancedSettingsCards: jest.fn(),
}));
jest.mock('./settingsComponents/GeneralFeedback', () => 'GeneralFeedback');
jest.mock('./settingsComponents/GroupFeedback', () => 'GroupFeedback');
jest.mock('./settingsComponents/Randomization', () => 'Randomization');
jest.mock('./settingsComponents/HintsCard', () => 'HintsCard');
jest.mock('./settingsComponents/ResetCard', () => 'ResetCard');
jest.mock('./settingsComponents/ScoringCard', () => 'ScoringCard');
jest.mock('./settingsComponents/ShowAnswerCard', () => 'ShowAnswerCard');
jest.mock('./settingsComponents/SwitchEditorCard', () => 'SwitchEditorCard');
jest.mock('./settingsComponents/TimerCard', () => 'TimerCard');
jest.mock('./settingsComponents/TypeCard', () => 'TypeCard');
describe('SettingsWidget', () => {
const props = {
problemType: ProblemTypeKeys.TEXTINPUT,
settings: {},
defaultSettings: {
maxAttempts: 2,
showanswer: 'finished',
showResetButton: false,
},
images: {},
isLibrary: false,
learningContextId: 'course+org+run',
};
describe('behavior', () => {
it(' calls showAdvancedSettingsCards when initialized', () => {
const showAdvancedSettingsCardsProps = {
isAdvancedCardsVisible: false,
setResetTrue: jest.fn().mockName('showAdvancedSettingsCards.setResetTrue'),
};
showAdvancedSettingsCards.mockReturnValue(showAdvancedSettingsCardsProps);
shallow(<SettingsWidget {...props} />);
expect(showAdvancedSettingsCards).toHaveBeenCalledWith();
});
});
describe('snapshot', () => {
test('snapshot: renders Settings widget page', () => {
const showAdvancedSettingsCardsProps = {
isAdvancedCardsVisible: false,
setResetTrue: jest.fn().mockName('showAdvancedSettingsCards.setResetTrue'),
};
showAdvancedSettingsCards.mockReturnValue(showAdvancedSettingsCardsProps);
expect(shallow(<SettingsWidget {...props} />).snapshot).toMatchSnapshot();
});
test('snapshot: renders Settings widget page advanced settings visible', () => {
const showAdvancedSettingsCardsProps = {
isAdvancedCardsVisible: true,
setResetTrue: jest.fn().mockName('showAdvancedSettingsCards.setResetTrue'),
};
showAdvancedSettingsCards.mockReturnValue(showAdvancedSettingsCardsProps);
expect(shallow(<SettingsWidget {...props} />).snapshot).toMatchSnapshot();
});
test('snapshot: renders Settings widget for Advanced Problem with correct widgets', () => {
const showAdvancedSettingsCardsProps = {
isAdvancedCardsVisible: true,
setResetTrue: jest.fn().mockName('showAdvancedSettingsCards.setResetTrue'),
};
showAdvancedSettingsCards.mockReturnValue(showAdvancedSettingsCardsProps);
expect(shallow(<SettingsWidget problemType={ProblemTypeKeys.ADVANCED} {...props} />).snapshot).toMatchSnapshot();
});
});
describe('isLibrary', () => {
const libraryProps = {
...props,
isLibrary: true,
};
test('snapshot: renders Settings widget page', () => {
const showAdvancedSettingsCardsProps = {
isAdvancedCardsVisible: false,
setResetTrue: jest.fn().mockName('showAdvancedSettingsCards.setResetTrue'),
};
showAdvancedSettingsCards.mockReturnValue(showAdvancedSettingsCardsProps);
expect(shallow(<SettingsWidget {...libraryProps} />).snapshot).toMatchSnapshot();
});
test('snapshot: renders Settings widget page advanced settings visible', () => {
const showAdvancedSettingsCardsProps = {
isAdvancedCardsVisible: true,
setResetTrue: jest.fn().mockName('showAdvancedSettingsCards.setResetTrue'),
};
showAdvancedSettingsCards.mockReturnValue(showAdvancedSettingsCardsProps);
expect(shallow(<SettingsWidget {...libraryProps} />).snapshot).toMatchSnapshot();
});
test('snapshot: renders Settings widget for Advanced Problem with correct widgets', () => {
const showAdvancedSettingsCardsProps = {
isAdvancedCardsVisible: true,
setResetTrue: jest.fn().mockName('showAdvancedSettingsCards.setResetTrue'),
};
showAdvancedSettingsCards.mockReturnValue(showAdvancedSettingsCardsProps);
expect(shallow(
<SettingsWidget problemType={ProblemTypeKeys.ADVANCED} {...libraryProps} />,
).snapshot).toMatchSnapshot();
});
});
describe('mapDispatchToProps', () => {
test('setBlockTitle from actions.app.setBlockTitle', () => {
expect(mapDispatchToProps.setBlockTitle).toEqual(actions.app.setBlockTitle);
});
});
describe('mapDispatchToProps', () => {
test('updateSettings from actions.problem.updateSettings', () => {
expect(mapDispatchToProps.updateSettings).toEqual(actions.problem.updateSettings);
});
});
describe('mapDispatchToProps', () => {
test('updateField from actions.problem.updateField', () => {
expect(mapDispatchToProps.updateField).toEqual(actions.problem.updateField);
});
});
describe('mapDispatchToProps', () => {
test('updateAnswer from actions.problem.updateAnswer', () => {
expect(mapDispatchToProps.updateAnswer).toEqual(actions.problem.updateAnswer);
});
});
});

View File

@@ -0,0 +1,133 @@
import React from 'react';
import {
render, screen, initializeMocks,
} from '@src/testUtils';
import * as hooks from './hooks';
import { SettingsWidgetInternal as SettingsWidget } from '.';
import { ProblemTypeKeys } from '../../../../../data/constants/problem';
jest.mock('./settingsComponents/GeneralFeedback', () => 'GeneralFeedback');
jest.mock('./settingsComponents/GroupFeedback', () => 'GroupFeedback');
jest.mock('./settingsComponents/Randomization', () => 'Randomization');
jest.mock('./settingsComponents/HintsCard', () => 'HintsCard');
jest.mock('./settingsComponents/ResetCard', () => 'ResetCard');
jest.mock('./settingsComponents/ScoringCard', () => 'ScoringCard');
jest.mock('./settingsComponents/ShowAnswerCard', () => 'ShowAnswerCard');
jest.mock('./settingsComponents/SwitchEditorCard', () => 'SwitchEditorCard');
jest.mock('./settingsComponents/TimerCard', () => 'TimerCard');
jest.mock('./settingsComponents/TypeCard', () => 'TypeCard');
describe('SettingsWidget', () => {
const showAdvancedSettingsCardsBaseProps = {
isAdvancedCardsVisible: false,
showAdvancedCards: jest.fn().mockName('showAdvancedSettingsCards.showAdvancedCards'),
setResetTrue: jest.fn().mockName('showAdvancedSettingsCards.setResetTrue'),
};
const props = {
problemType: ProblemTypeKeys.TEXTINPUT,
settings: {},
defaultSettings: {
maxAttempts: 2,
showanswer: 'finished',
showResetButton: false,
},
images: {},
isLibrary: false,
learningContextId: 'course+org+run',
setBlockTitle: jest.fn().mockName('setBlockTitle'),
blockTitle: '',
updateAnswer: jest.fn().mockName('updateAnswer'),
updateSettings: jest.fn().mockName('updateSettings'),
updateField: jest.fn().mockName('updateField'),
answers: [],
correctAnswerCount: 0,
groupFeedbackList: [],
showMarkdownEditorButton: false,
};
beforeEach(() => {
initializeMocks();
});
describe('behavior', () => {
it('calls showAdvancedSettingsCards when initialized', () => {
jest.spyOn(hooks, 'showAdvancedSettingsCards').mockReturnValue(showAdvancedSettingsCardsBaseProps);
render(<SettingsWidget {...props} />);
expect(hooks.showAdvancedSettingsCards).toHaveBeenCalled();
});
});
describe('renders', () => {
test('renders Settings widget page', () => {
jest.spyOn(hooks, 'showAdvancedSettingsCards').mockReturnValue(showAdvancedSettingsCardsBaseProps);
render(<SettingsWidget {...props} />);
expect(screen.getByText('Show advanced settings')).toBeInTheDocument();
});
test('renders Settings widget page advanced settings visible', () => {
const showAdvancedSettingsCardsProps = {
...showAdvancedSettingsCardsBaseProps,
isAdvancedCardsVisible: true,
};
jest.spyOn(hooks, 'showAdvancedSettingsCards').mockReturnValue(showAdvancedSettingsCardsProps);
const { container } = render(<SettingsWidget {...props} />);
expect(screen.queryByText('Show advanced settings')).not.toBeInTheDocument();
expect(container.querySelector('showanswercard')).toBeInTheDocument();
expect(container.querySelector('resetcard')).toBeInTheDocument();
});
test('renders Settings widget for Advanced Problem with correct widgets', () => {
const showAdvancedSettingsCardsProps = {
...showAdvancedSettingsCardsBaseProps,
isAdvancedCardsVisible: true,
};
jest.spyOn(hooks, 'showAdvancedSettingsCards').mockReturnValue(showAdvancedSettingsCardsProps);
const { container } = render(
<SettingsWidget {...props} problemType={ProblemTypeKeys.ADVANCED} />,
);
expect(container.querySelector('randomization')).toBeInTheDocument();
});
});
describe('isLibrary', () => {
const libraryProps = {
...props,
isLibrary: true,
};
test('renders Settings widget page', () => {
jest.spyOn(hooks, 'showAdvancedSettingsCards').mockReturnValue(showAdvancedSettingsCardsBaseProps);
const { container } = render(<SettingsWidget {...libraryProps} />);
expect(container.querySelector('timercard')).not.toBeInTheDocument();
expect(container.querySelector('resetcard')).not.toBeInTheDocument();
expect(container.querySelector('typecard')).toBeInTheDocument();
expect(container.querySelector('hintscard')).toBeInTheDocument();
expect(screen.getByText('Show advanced settings')).toBeInTheDocument();
});
test('renders Settings widget page advanced settings visible', () => {
const showAdvancedSettingsCardsProps = {
...showAdvancedSettingsCardsBaseProps,
isAdvancedCardsVisible: true,
};
jest.spyOn(hooks, 'showAdvancedSettingsCards').mockReturnValue(showAdvancedSettingsCardsProps);
const { container } = render(<SettingsWidget {...libraryProps} />);
expect(screen.queryByText('Show advanced settings')).not.toBeInTheDocument();
expect(container.querySelector('showanswearscard')).not.toBeInTheDocument();
expect(container.querySelector('resetcard')).not.toBeInTheDocument();
expect(container.querySelector('typecard')).toBeInTheDocument();
expect(container.querySelector('hintscard')).toBeInTheDocument();
});
test('renders Settings widget for Advanced Problem with correct widgets', () => {
const showAdvancedSettingsCardsProps = {
...showAdvancedSettingsCardsBaseProps,
isAdvancedCardsVisible: true,
};
jest.spyOn(hooks, 'showAdvancedSettingsCards').mockReturnValue(showAdvancedSettingsCardsProps);
const { container } = render(<SettingsWidget {...libraryProps} problemType={ProblemTypeKeys.ADVANCED} />);
expect(container.querySelector('randomization')).toBeInTheDocument();
});
});
});

View File

@@ -1,157 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`RandomizationCard snapshot snapshot: renders randomization setting card with default randomization 1`] = `
<SettingsOption
className=""
extraSections={[]}
hasExpandableTextArea={false}
none={true}
summary="sUmmary"
title="Randomization"
>
<div
className="mb-3"
>
{randomization, select,
null {No Python based randomization is present in this problem.}
other {Defines when to randomize the variables specified in the associated Python script. For problems that do not randomize values, specify "Never".}
}
</div>
<Form.Group>
<Form.Control
as="select"
onChange={[MockFunction randomizationCardHooks.handleChange]}
value="default_vAlUE"
>
<option
key="never"
value="never"
>
Never
</option>
<option
key="always"
value="always"
>
Always
</option>
<option
key="onreset"
value="onreset"
>
On Reset
</option>
<option
key="per_student"
value="per_student"
>
Per Student
</option>
</Form.Control>
</Form.Group>
</SettingsOption>
`;
exports[`RandomizationCard snapshot snapshot: renders randomization setting card with randomization defined 1`] = `
<SettingsOption
className=""
extraSections={[]}
hasExpandableTextArea={false}
none={false}
summary="sUmmary"
title="Randomization"
>
<div
className="mb-3"
>
{randomization, select,
null {No Python based randomization is present in this problem.}
other {Defines when to randomize the variables specified in the associated Python script. For problems that do not randomize values, specify "Never".}
}
</div>
<Form.Group>
<Form.Control
as="select"
onChange={[MockFunction randomizationCardHooks.handleChange]}
value="sOmE_vAlUE"
>
<option
key="never"
value="never"
>
Never
</option>
<option
key="always"
value="always"
>
Always
</option>
<option
key="onreset"
value="onreset"
>
On Reset
</option>
<option
key="per_student"
value="per_student"
>
Per Student
</option>
</Form.Control>
</Form.Group>
</SettingsOption>
`;
exports[`RandomizationCard snapshot snapshot: renders randomization setting card with randomization null 1`] = `
<SettingsOption
className=""
extraSections={[]}
hasExpandableTextArea={false}
none={true}
summary="sUmmary"
title="Randomization"
>
<div
className="mb-3"
>
{randomization, select,
null {No Python based randomization is present in this problem.}
other {Defines when to randomize the variables specified in the associated Python script. For problems that do not randomize values, specify "Never".}
}
</div>
<Form.Group>
<Form.Control
as="select"
onChange={[MockFunction randomizationCardHooks.handleChange]}
value={null}
>
<option
key="never"
value="never"
>
Never
</option>
<option
key="always"
value="always"
>
Always
</option>
<option
key="onreset"
value="onreset"
>
On Reset
</option>
<option
key="per_student"
value="per_student"
>
Per Student
</option>
</Form.Control>
</Form.Group>
</SettingsOption>
`;

View File

@@ -1,49 +0,0 @@
import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { formatMessage } from '../../../../../../../testUtils';
import { RandomizationCard } from './index';
import { useRandomizationSettingStatus } from './hooks';
jest.mock('./hooks', () => ({
useRandomizationSettingStatus: jest.fn(),
}));
describe('RandomizationCard', () => {
const props = {
randomization: 'sOmE_vAlUE',
defaultValue: 'default_vAlUE',
updateSettings: jest.fn().mockName('args.updateSettings'),
intl: { formatMessage },
};
const randomizationCardHooksProps = {
summary: { message: { defaultMessage: 'sUmmary' } },
handleChange: jest.fn().mockName('randomizationCardHooks.handleChange'),
};
useRandomizationSettingStatus.mockReturnValue(randomizationCardHooksProps);
describe('behavior', () => {
it(' calls useRandomizationSettingStatus when initialized', () => {
shallow(<RandomizationCard {...props} />);
expect(useRandomizationSettingStatus).toHaveBeenCalledWith(
{ updateSettings: props.updateSettings, randomization: props.randomization },
);
});
});
describe('snapshot', () => {
test('snapshot: renders randomization setting card with randomization defined', () => {
expect(shallow(<RandomizationCard {...props} />).snapshot).toMatchSnapshot();
});
test('snapshot: renders randomization setting card with default randomization', () => {
expect(shallow(<RandomizationCard {...props} randomization={null} />).snapshot).toMatchSnapshot();
});
test('snapshot: renders randomization setting card with randomization null', () => {
expect(
shallow(<RandomizationCard {...props} randomization={null} defaultValue={null} />).snapshot,
).toMatchSnapshot();
});
});
});

View File

@@ -0,0 +1,60 @@
import React from 'react';
import {
render, screen, initializeMocks, fireEvent,
} from '@src/testUtils';
import { formatMessage } from '@src/editors/testUtils';
import { RandomizationCard } from './index';
import * as hooks from './hooks';
describe('RandomizationCard', () => {
const props = {
randomization: 'per_student',
defaultValue: 'always',
updateSettings: jest.fn().mockName('args.updateSettings'),
intl: { formatMessage },
};
const randomizationCardHooksProps = {
summary: { message: { defaultMessage: 'sUmmary' } },
handleChange: jest.fn().mockName('randomizationCardHooks.handleChange'),
};
jest.spyOn(hooks, 'useRandomizationSettingStatus').mockReturnValue(randomizationCardHooksProps);
beforeEach(() => {
initializeMocks();
});
describe('behavior', () => {
it('calls useRandomizationSettingStatus when initialized', () => {
render(<RandomizationCard {...props} />);
expect(hooks.useRandomizationSettingStatus).toHaveBeenCalledWith(
{ updateSettings: props.updateSettings, randomization: props.randomization },
);
});
});
describe('renders', () => {
test('renders randomization setting card with randomization defined', () => {
render(<RandomizationCard {...props} />);
expect(screen.getByText('sUmmary')).toBeInTheDocument();
expect(screen.getByText('Randomization')).toBeInTheDocument();
fireEvent.click(screen.getByRole('button', { name: 'Randomization' }));
expect(screen.getByRole('combobox')).toHaveValue(props.randomization);
});
test('renders randomization setting card with default randomization', () => {
render(<RandomizationCard {...props} randomization="" />);
expect(screen.getByText('sUmmary')).toBeInTheDocument();
expect(screen.getByText('Randomization')).toBeInTheDocument();
fireEvent.click(screen.getByRole('button', { name: 'Randomization' }));
expect(screen.getByRole('combobox')).toHaveValue(props.defaultValue);
});
test('renders randomization setting card with randomization null', () => {
render(<RandomizationCard {...props} randomization="" defaultValue="" />);
fireEvent.click(screen.getByRole('button', { name: 'Randomization' }));
expect(screen.getByRole('combobox')).toHaveValue('never');
});
});
});

View File

@@ -1,72 +0,0 @@
import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { actions } from '../../../../../../data/redux';
import { LicenseDetailsInternal as LicenseDetails, mapStateToProps, mapDispatchToProps } from './LicenseDetails';
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'),
},
},
}));
describe('LicenseDetails', () => {
const props = {
license: null,
details: {},
level: 'course',
updateField: jest.fn().mockName('args.updateField'),
};
describe('snapshots', () => {
test('snapshots: renders as expected with default props', () => {
expect(
shallow(<LicenseDetails {...props} />).snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with level set to library', () => {
expect(
shallow(<LicenseDetails {...props} level="library" />).snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with level set to block and license set to select', () => {
expect(
shallow(<LicenseDetails {...props} level="block" license="select" />).snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with level set to block and license set to all rights reserved', () => {
expect(
shallow(<LicenseDetails {...props} level="block" license="all-rights-reserved" />).snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with level set to block and license set to Creative Commons', () => {
expect(
shallow(<LicenseDetails {...props} level="block" license="creative-commons" />).snapshot,
).toMatchSnapshot();
});
});
describe('mapStateToProps', () => {
const testState = { A: 'pple', B: 'anana', C: 'ucumber' };
test('mapStateToProps equals an empty object', () => {
expect(mapStateToProps(testState)).toEqual({});
});
});
describe('mapDispatchToProps', () => {
const dispatch = jest.fn();
test('updateField from actions.video.updateField', () => {
expect(mapDispatchToProps.updateField).toEqual(dispatch(actions.video.updateField));
});
});
});

View File

@@ -0,0 +1,83 @@
import React from 'react';
import {
render, screen, initializeMocks,
} from '@src/testUtils';
import { actions } from '../../../../../../data/redux';
import { LicenseDetailsInternal as LicenseDetails, mapStateToProps, mapDispatchToProps } from './LicenseDetails';
jest.mock('../../../../../../data/redux', () => ({
actions: {
video: {
updateField: jest.fn().mockName('actions.video.updateField'),
},
},
}));
describe('LicenseDetails', () => {
const props = {
license: '',
details: {
attribution: false,
noncommercial: false,
noDerivatives: false,
shareAlike: false,
},
level: 'course',
updateField: jest.fn().mockName('args.updateField'),
};
beforeEach(() => {
initializeMocks();
});
describe('renders', () => {
test('renders as expected with default props', () => {
const { container } = render(<LicenseDetails {...props} />);
const reduxWrapper = (container.firstChild as HTMLElement);
expect(reduxWrapper?.innerHTML).toBe('');
expect(screen.queryByText('License Details')).not.toBeInTheDocument();
});
test('renders as expected with level set to library', () => {
render(<LicenseDetails {...props} level="library" />);
expect(screen.queryByText('License Details')).toBeInTheDocument();
});
test('renders as expected with level set to block and license set to select', () => {
const { container } = render(<LicenseDetails {...props} level="block" license="select" />);
const reduxWrapper = (container.firstChild as HTMLElement);
expect(reduxWrapper?.innerHTML).toBe('');
expect(screen.queryByText('License Details')).not.toBeInTheDocument();
});
test('renders as expected with level set to block and license set to all rights reserved', () => {
render(<LicenseDetails {...props} level="block" license="all-rights-reserved" />);
expect(screen.queryByText('License Details')).toBeInTheDocument();
expect(screen.queryByText('You reserve all rights for your work.')).toBeInTheDocument();
});
test('renders as expected with level set to block and license set to Creative Commons', () => {
render(<LicenseDetails {...props} level="block" license="creative-commons" />);
expect(screen.queryByText('License Details')).toBeInTheDocument();
expect(screen.getByRole('checkbox', { name: 'Attribution' })).toBeInTheDocument();
expect(screen.getByRole('checkbox', { name: 'Noncommercial' })).toBeInTheDocument();
expect(screen.getByRole('checkbox', { name: 'Share Alike' })).toBeInTheDocument();
expect(screen.getByRole('checkbox', { name: 'No Derivatives' })).toBeInTheDocument();
});
});
describe('mapStateToProps', () => {
const testState = { A: 'pple', B: 'anana', C: 'ucumber' };
test('mapStateToProps equals an empty object', () => {
// @ts-ignore-next-line
expect(mapStateToProps(testState)).toEqual({});
});
});
describe('mapDispatchToProps', () => {
const dispatch = jest.fn();
test('updateField from actions.video.updateField', () => {
// @ts-ignore-next-line
expect(mapDispatchToProps.updateField).toEqual(dispatch(actions.video.updateField));
});
});
});

View File

@@ -1,198 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`LicenseDetails snapshots snapshots: renders as expected with default props 1`] = `false`;
exports[`LicenseDetails snapshots snapshots: renders as expected with level set to block and license set to Creative Commons 1`] = `
<div
className="x-small border-primary-100 border-bottom m-0 pr-1"
>
<Form.Group
className="pb-2"
>
<div
className="mb-3"
>
<FormattedMessage
defaultMessage="License Details"
description="Title for license detatils subsection"
id="authoring.videoeditor.license.detailsSubsection.title"
/>
</div>
<Stack
gap={4}
>
<div
className="border-primary-100 border-bottom pb-4"
>
<Form.Group>
<ActionRow>
<Icon
className="text-primary-500"
/>
<Form.Label
className="my-0 text-primary-500"
>
<FormattedMessage
defaultMessage="Attribution"
description="Label for attribution checkbox"
id="authoring.videoeditor.license.attributionCheckboxLabel"
/>
</Form.Label>
<ActionRow.Spacer />
<CheckboxControl
checked={true}
disabled={true}
/>
</ActionRow>
</Form.Group>
<div>
<FormattedMessage
defaultMessage="Allow others to copy, distribute, display and perform your copyrighted work but only if they give credit the way you request. Currently, this option is required."
description="Attribution card section defining attribution license"
id="authoring.videoeditor.license.attributionSectionDescription"
/>
</div>
</div>
<div
className="border-primary-100 border-bottom pb-4"
>
<Form.Group>
<ActionRow>
<Icon />
<Form.Label
className="my-0 text-primary-500"
>
<FormattedMessage
defaultMessage="Noncommercial"
description="Label for noncommercial checkbox"
id="authoring.videoeditor.license.noncommercialCheckboxLabel"
/>
</Form.Label>
<ActionRow.Spacer />
<CheckboxControl
disabled={false}
onChange={[Function]}
/>
</ActionRow>
</Form.Group>
<div>
<FormattedMessage
defaultMessage="Allow others to copy, distribute, display and perform your work - and derivative works based upon it - but for noncommercial purposes only."
description="Noncommercial card section defining noncommercial license"
id="authoring.videoeditor.license.noncommercialSectionDescription"
/>
</div>
</div>
<div
className="border-primary-100 border-bottom pb-4"
>
<Form.Group>
<ActionRow>
<Icon />
<Form.Label
className="my-0 text-primary-500"
>
<FormattedMessage
defaultMessage="No Derivatives"
description="Label for No Derivatives checkbox"
id="authoring.videoeditor.license.noDerivativesCheckboxLabel"
/>
</Form.Label>
<ActionRow.Spacer />
<CheckboxControl
disabled={false}
onChange={[Function]}
/>
</ActionRow>
</Form.Group>
<div>
<FormattedMessage
defaultMessage="Allow others to copy, distribute, display and perform only verbatim copies of your work, not derivative works based upon it. This option is incompatible with "Share Alike"."
description="No Derivatives card section defining no derivatives license"
id="authoring.videoeditor.license.noDerivativesSectionDescription"
/>
</div>
</div>
<div>
<Form.Group>
<ActionRow>
<Icon />
<Form.Label
className="my-0 text-primary-500"
>
<FormattedMessage
defaultMessage="Share Alike"
description="Label for Share Alike checkbox"
id="authoring.videoeditor.license.shareAlikeCheckboxLabel"
/>
</Form.Label>
<ActionRow.Spacer />
<CheckboxControl
disabled={false}
onChange={[Function]}
/>
</ActionRow>
</Form.Group>
<div>
<FormattedMessage
defaultMessage="Allow others to distribute derivative works only under a license identical to the license that governs your work. This option is incompatible with "No Derivatives"."
description="Share Alike card section defining no derivatives license"
id="authoring.videoeditor.license.shareAlikeSectionDescription"
/>
</div>
</div>
</Stack>
</Form.Group>
</div>
`;
exports[`LicenseDetails snapshots snapshots: renders as expected with level set to block and license set to all rights reserved 1`] = `
<div
className="x-small border-primary-100 border-bottom m-0 pr-1"
>
<Form.Group
className="pb-2"
>
<div
className="mb-3"
>
<FormattedMessage
defaultMessage="License Details"
description="Title for license detatils subsection"
id="authoring.videoeditor.license.detailsSubsection.title"
/>
</div>
<div
className="mt-2"
>
<FormattedMessage
defaultMessage="You reserve all rights for your work."
description="All Rights Reserved section message"
id="authoring.videoeditor.license.allRightsReservedSectionMessage"
/>
</div>
</Form.Group>
</div>
`;
exports[`LicenseDetails snapshots snapshots: renders as expected with level set to block and license set to select 1`] = `false`;
exports[`LicenseDetails snapshots snapshots: renders as expected with level set to library 1`] = `
<div
className="x-small border-primary-100 border-bottom m-0 pr-1"
>
<Form.Group
className="pb-2"
>
<div
className="mb-3"
>
<FormattedMessage
defaultMessage="License Details"
description="Title for license detatils subsection"
id="authoring.videoeditor.license.detailsSubsection.title"
/>
</div>
</Form.Group>
</div>
`;

View File

@@ -1,85 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`SocialShareWidget rendered with videoSharingEnabled false with default props should return null 1`] = `null`;
exports[`SocialShareWidget rendered with videoSharingEnabled false with videoSharingEnabledForAll false and isLibrary true should return null 1`] = `null`;
exports[`SocialShareWidget rendered with videoSharingEnabled false with videoSharingEnabledForCourse and isLibrary false and videoSharingEnabledForAll true should return null 1`] = `null`;
exports[`SocialShareWidget rendered with videoSharingEnabled true and allowVideoSharing value equals false should have subtitle with text that reads Enabled 1`] = `
<CollapsibleFormWidget
fontSize="x-small"
subtitle="Disabled"
title="Social Sharing"
>
<div>
<FormattedMessage
defaultMessage="Allow this video to be shareable to social media"
description="Description for sociail sharing setting"
id="authoring.videoeditor.socialShare.description"
/>
</div>
<Form.Checkbox
checked={false}
className="mt-3"
disabled={false}
onChange={[Function]}
>
<div
className="small text-gray-700"
>
This video is shareable to social media
</div>
</Form.Checkbox>
<div
className="mt-3"
>
<Hyperlink
className="text-primary-500"
destination="sOMeURl.cOM"
target="_blank"
>
Learn more about social sharing
</Hyperlink>
</div>
</CollapsibleFormWidget>
`;
exports[`SocialShareWidget rendered with videoSharingEnabled true and allowVideoSharing value equals true should have subtitle with text that reads Enabled 1`] = `
<CollapsibleFormWidget
fontSize="x-small"
subtitle="Enabled"
title="Social Sharing"
>
<div>
<FormattedMessage
defaultMessage="Allow this video to be shareable to social media"
description="Description for sociail sharing setting"
id="authoring.videoeditor.socialShare.description"
/>
</div>
<Form.Checkbox
checked={true}
className="mt-3"
disabled={false}
onChange={[Function]}
>
<div
className="small text-gray-700"
>
This video is shareable to social media
</div>
</Form.Checkbox>
<div
className="mt-3"
>
<Hyperlink
className="text-primary-500"
destination="sOMeURl.cOM"
target="_blank"
>
Learn more about social sharing
</Hyperlink>
</div>
</CollapsibleFormWidget>
`;

View File

@@ -1,274 +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 { SocialShareWidgetInternal as SocialShareWidget, mapStateToProps, mapDispatchToProps } from '.';
import messages from './messages';
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: {
allowVideoSharing: jest.fn(state => ({ allowVideoSharing: state })),
videoSharingEnabledForAll: jest.fn(state => ({ videoSharingEnabledForAll: state })),
videoSharingEnabledForCourse: jest.fn(state => ({ videoSharingEnabledForCourse: state })),
videoSharingLearnMoreLink: jest.fn(state => ({ videoSharingLearnMoreLink: state })),
},
},
}));
describe('SocialShareWidget', () => {
const props = {
title: 'tiTLE',
intl: { formatMessage },
videoSharingEnabledForCourse: false,
videoSharingEnabledForAll: false,
isLibrary: false,
allowVideoSharing: {
level: 'block',
value: false,
},
videoSharingLearnMoreLink: 'sOMeURl.cOM',
updateField: jest.fn().mockName('args.updateField'),
};
describe('rendered with videoSharingEnabled false', () => {
describe('with default props', () => {
it('should return null', () => {
const wrapper = shallow(<SocialShareWidget {...props} />);
expect(wrapper.snapshot).toMatchSnapshot();
});
});
describe('with videoSharingEnabledForAll false and isLibrary true', () => {
it('should return null', () => {
const wrapper = shallow(<SocialShareWidget {...props} isLibrary />);
expect(wrapper.snapshot).toMatchSnapshot();
});
});
describe('with videoSharingEnabledForCourse and isLibrary false and videoSharingEnabledForAll true', () => {
it('should return null', () => {
const wrapper = shallow(<SocialShareWidget {...props} videoSharingEnabledForAll />);
expect(wrapper.snapshot).toMatchSnapshot();
});
});
});
describe('rendered with videoSharingEnabled true', () => {
describe('and allowVideoSharing value equals true', () => {
describe(' with level equal to course', () => {
const wrapper = shallow(<SocialShareWidget
{...props}
videoSharingEnabledForCourse
allowVideoSharing={{
level: 'course',
value: true,
}}
/>);
it('should have setting location message', () => {
const settingLocationDisclaimer = wrapper.instance.findByType('FormattedMessage')[2].props.defaultMessage;
expect(settingLocationDisclaimer).toEqual(messages.disclaimerSettingLocation.defaultMessage);
});
it('should have checkbox disabled prop equal true', () => {
const disabledCheckbox = wrapper.shallowWrapper.props.children[1].props.disabled;
expect(disabledCheckbox).toEqual(true);
});
});
describe(' with level equal to block', () => {
const wrapper = shallow(<SocialShareWidget
{...props}
videoSharingEnabledForCourse
allowVideoSharing={{
level: 'block',
value: true,
}}
/>);
it('should not have setting location message', () => {
const formattedMessages = wrapper.instance.findByType('FormattedMessage');
expect(formattedMessages.length).toEqual(1);
expect(formattedMessages[0]).not.toEqual(messages.disclaimerSettingLocation.defaultMessage);
});
it('should not have override note', () => {
const formattedMessages = wrapper.instance.findByType('FormattedMessage');
expect(formattedMessages.length).toEqual(1);
expect(formattedMessages[0]).not.toEqual(messages.overrideSocialSharingNote.defaultMessage);
});
it('should have checkbox disabled prop equal false', () => {
const disabledCheckbox = wrapper.shallowWrapper.props.children[1].props.disabled;
expect(disabledCheckbox).toEqual(false);
});
});
describe('isLibrary equals true', () => {
const wrapper = shallow(<SocialShareWidget
{...props}
videoSharingEnabledForAll
isLibrary
allowVideoSharing={{
level: 'block',
value: true,
}}
/>);
it('should not have setting location message', () => {
const formattedMessages = wrapper.instance.findByType('FormattedMessage');
expect(formattedMessages.length).toEqual(1);
expect(formattedMessages[0]).not.toEqual(messages.disclaimerSettingLocation.defaultMessage);
});
it('should not have override note', () => {
const formattedMessages = wrapper.instance.findByType('FormattedMessage');
expect(formattedMessages.length).toEqual(1);
expect(formattedMessages[0]).not.toEqual(messages.overrideSocialSharingNote.defaultMessage);
});
it('should have checkbox disabled prop equal false', () => {
const disabledCheckbox = wrapper.shallowWrapper.props.children[1].props.disabled;
expect(disabledCheckbox).toEqual(false);
});
});
it('should have subtitle with text that reads Enabled', () => {
const wrapper = shallow(<SocialShareWidget
{...props}
videoSharingEnabledForCourse
allowVideoSharing={{
level: 'block',
value: true,
}}
/>);
const { subtitle } = wrapper.shallowWrapper.props;
expect(wrapper.snapshot).toMatchSnapshot();
expect(subtitle).toEqual('Enabled');
});
});
describe('and allowVideoSharing value equals false', () => {
describe(' with level equal to course', () => {
const wrapper = shallow(<SocialShareWidget
{...props}
videoSharingEnabledForCourse
allowVideoSharing={{
level: 'course',
value: false,
}}
/>);
it('should have setting location message', () => {
const settingLocationDisclaimer = wrapper.instance.findByType('FormattedMessage')[2].props.defaultMessage;
expect(settingLocationDisclaimer).toEqual(messages.disclaimerSettingLocation.defaultMessage);
});
it('should have checkbox disabled prop equal true', () => {
const disabledCheckbox = wrapper.shallowWrapper.props.children[1].props.disabled;
expect(disabledCheckbox).toEqual(true);
});
});
describe(' with level equal to block', () => {
const wrapper = shallow(<SocialShareWidget
{...props}
videoSharingEnabledForCourse
allowVideoSharing={{
level: 'block',
value: false,
}}
/>);
it('should not have setting location message', () => {
const formattedMessages = wrapper.instance.findByType('FormattedMessage');
expect(formattedMessages.length).toEqual(1);
expect(formattedMessages.at(0)).not.toEqual(messages.disclaimerSettingLocation.defaultMessage);
});
it('should not have override note', () => {
const formattedMessages = wrapper.instance.findByType('FormattedMessage');
expect(formattedMessages.length).toEqual(1);
expect(formattedMessages.at(0)).not.toEqual(messages.overrideSocialSharingNote.defaultMessage);
});
it('should have checkbox disabled prop equal false', () => {
const disabledCheckbox = wrapper.shallowWrapper.props.children[1].props.disabled;
expect(disabledCheckbox).toEqual(false);
});
});
describe('isLibrary equals true', () => {
const wrapper = shallow(<SocialShareWidget
{...props}
videoSharingEnabledForAll
isLibrary
allowVideoSharing={{
level: 'block',
value: false,
}}
/>);
it('should not have setting location message', () => {
const formattedMessages = wrapper.instance.findByType('FormattedMessage');
expect(formattedMessages.length).toEqual(1);
expect(formattedMessages.at(0)).not.toEqual(messages.disclaimerSettingLocation.defaultMessage);
});
it('should not have override note', () => {
const formattedMessages = wrapper.instance.findByType('FormattedMessage');
expect(formattedMessages.length).toEqual(1);
expect(formattedMessages.at(0)).not.toEqual(messages.overrideSocialSharingNote.defaultMessage);
});
it('should have checkbox disabled prop equal false', () => {
const disabledCheckbox = wrapper.shallowWrapper.props.children[1].props.disabled;
expect(disabledCheckbox).toEqual(false);
});
});
it('should have subtitle with text that reads Enabled', () => {
const wrapper = shallow(<SocialShareWidget
{...props}
videoSharingEnabledForCourse
allowVideoSharing={{
level: 'block',
value: false,
}}
/>);
const { subtitle } = wrapper.shallowWrapper.props;
expect(wrapper.snapshot).toMatchSnapshot();
expect(subtitle).toEqual('Disabled');
});
});
});
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('allowVideoSharing from video.allowVideoSharing', () => {
expect(
mapStateToProps(testState).allowVideoSharing,
).toEqual(selectors.video.allowVideoSharing(testState));
});
test('videoSharingEnabledForCourse from video.videoSharingEnabledForCourse', () => {
expect(
mapStateToProps(testState).videoSharingEnabledForCourse,
).toEqual(selectors.video.videoSharingEnabledForCourse(testState));
});
test('videoSharingEnabledForAll from video.videoSharingEnabledForAll', () => {
expect(
mapStateToProps(testState).videoSharingEnabledForAll,
).toEqual(selectors.video.videoSharingEnabledForAll(testState));
});
test('videoSharingLearnMoreLink from video.videoSharingLearnMoreLink', () => {
expect(
mapStateToProps(testState).videoSharingLearnMoreLink,
).toEqual(selectors.video.videoSharingLearnMoreLink(testState));
});
});
describe('mapDispatchToProps', () => {
const dispatch = jest.fn();
test('updateField from actions.video.updateField', () => {
expect(mapDispatchToProps.updateField).toEqual(dispatch(actions.video.updateField));
});
});
});

View File

@@ -0,0 +1,318 @@
import React from 'react';
import {
render, screen, initializeMocks,
fireEvent,
} from '@src/testUtils';
import { formatMessage } from '../../../../../../testUtils';
import { SocialShareWidgetInternal as SocialShareWidget } from '.';
import * as hooks from './hooks';
jest.mock('../../../../../../data/redux', () => ({
actions: {
video: {
updateField: jest.fn().mockName('actions.video.updateField'),
},
},
selectors: {
app: {
isLibrary: jest.fn(state => ({ isLibrary: state })),
},
video: {
allowVideoSharing: jest.fn(state => ({ allowVideoSharing: state })),
videoSharingEnabledForAll: jest.fn(state => ({ videoSharingEnabledForAll: state })),
videoSharingEnabledForCourse: jest.fn(state => ({ videoSharingEnabledForCourse: state })),
videoSharingLearnMoreLink: jest.fn(state => ({ videoSharingLearnMoreLink: state })),
},
},
}));
describe('SocialShareWidget', () => {
const props = {
intl: { formatMessage },
videoSharingEnabledForCourse: false,
videoSharingEnabledForAll: false,
isLibrary: false,
allowVideoSharing: {
level: 'block',
value: false,
},
videoSharingLearnMoreLink: 'sOMeURl.cOM',
updateField: jest.fn().mockName('args.updateField'),
};
beforeEach(() => {
initializeMocks();
jest.spyOn(hooks, 'useTrackSocialSharingChange').mockReturnValue(jest.fn());
});
describe('rendered with videoSharingEnabled false', () => {
describe('with default props', () => {
it('should return null', () => {
const { container } = render(<SocialShareWidget {...props} />);
const reduxWrapper = container.firstChild;
expect(reduxWrapper?.textContent).toBe('');
});
});
describe('with videoSharingEnabledForAll false and isLibrary true', () => {
it('should return null', () => {
const { container } = render(<SocialShareWidget {...props} isLibrary />);
const reduxWrapper = container.firstChild;
expect(reduxWrapper?.textContent).toBe('');
});
});
describe('with videoSharingEnabledForCourse and isLibrary false and videoSharingEnabledForAll true', () => {
it('should return null', () => {
const { container } = render(<SocialShareWidget {...props} videoSharingEnabledForAll />);
const reduxWrapper = container.firstChild;
expect(reduxWrapper?.textContent).toBe('');
});
});
});
describe('rendered with videoSharingEnabled true', () => {
describe('and allowVideoSharing value equals true', () => {
describe(' with level equal to course', () => {
it('should have setting location message', () => {
render(<SocialShareWidget
{...props}
videoSharingEnabledForCourse
allowVideoSharing={{
level: 'course',
value: true,
}}
/>);
expect(screen.getByText('Change this setting on the course outline page.')).toBeInTheDocument();
});
it('should have checkbox disabled prop equal true', () => {
render(<SocialShareWidget
{...props}
videoSharingEnabledForCourse
allowVideoSharing={{
level: 'course',
value: true,
}}
/>);
const checkbox = screen.getByRole('checkbox', { name: 'This video is shareable to social media' });
expect(checkbox).toBeInTheDocument();
expect(checkbox).toBeDisabled();
});
});
describe(' with level equal to block', () => {
it('should not have setting location message', () => {
render(<SocialShareWidget
{...props}
videoSharingEnabledForCourse
allowVideoSharing={{
level: 'block',
value: true,
}}
/>);
expect(screen.queryByText('Change this setting on the course outline page.')).not.toBeInTheDocument();
});
it('should not have override note', () => {
render(<SocialShareWidget
{...props}
videoSharingEnabledForCourse
allowVideoSharing={{
level: 'block',
value: true,
}}
/>);
expect(screen.queryByText('Note: This setting is overridden by the course outline page.')).not.toBeInTheDocument();
});
it('should have checkbox disabled prop equal false', () => {
render(<SocialShareWidget
{...props}
videoSharingEnabledForCourse
allowVideoSharing={{
level: 'block',
value: true,
}}
/>);
const checkbox = screen.getByRole('checkbox', { name: 'This video is shareable to social media' });
expect(checkbox).toBeInTheDocument();
expect(checkbox).not.toBeDisabled();
});
});
describe('isLibrary equals true', () => {
it('should not have setting location message', () => {
render(<SocialShareWidget
{...props}
videoSharingEnabledForAll
isLibrary
allowVideoSharing={{
level: 'block',
value: true,
}}
/>);
expect(screen.queryByText('Change this setting on the course outline page.')).not.toBeInTheDocument();
});
it('should not have override note', () => {
render(<SocialShareWidget
{...props}
videoSharingEnabledForAll
isLibrary
allowVideoSharing={{
level: 'block',
value: true,
}}
/>);
expect(screen.queryByText('Note: This setting is overridden by the course outline page.')).not.toBeInTheDocument();
});
it('should have checkbox disabled prop equal false', () => {
render(<SocialShareWidget
{...props}
videoSharingEnabledForAll
isLibrary
allowVideoSharing={{
level: 'block',
value: true,
}}
/>);
const checkbox = screen.getByRole('checkbox', { name: 'This video is shareable to social media' });
expect(checkbox).toBeInTheDocument();
expect(checkbox).not.toBeDisabled();
});
});
it('should have subtitle with text that reads Enabled', () => {
render(<SocialShareWidget
{...props}
videoSharingEnabledForCourse
allowVideoSharing={{
level: 'block',
value: true,
}}
/>);
expect(screen.getByText('Social Sharing')).toBeInTheDocument();
fireEvent.click(screen.getByText('Social Sharing'));
const subtitle = screen.getByText('Enabled');
expect(subtitle).toBeInTheDocument();
});
});
describe('and allowVideoSharing value equals false', () => {
describe(' with level equal to course', () => {
it('should have setting location message', () => {
render(<SocialShareWidget
{...props}
videoSharingEnabledForCourse
allowVideoSharing={{
level: 'course',
value: false,
}}
/>);
expect(screen.getByText('Change this setting on the course outline page.')).toBeInTheDocument();
});
it('should have checkbox disabled prop equal true', () => {
render(<SocialShareWidget
{...props}
videoSharingEnabledForCourse
allowVideoSharing={{
level: 'course',
value: false,
}}
/>);
const checkbox = screen.getByRole('checkbox', { name: 'This video is shareable to social media' });
expect(checkbox).toBeInTheDocument();
expect(checkbox).toBeDisabled();
});
});
describe(' with level equal to block', () => {
it('should not have setting location message', () => {
render(<SocialShareWidget
{...props}
videoSharingEnabledForCourse
allowVideoSharing={{
level: 'block',
value: false,
}}
/>);
expect(screen.queryByText('Change this setting on the course outline page.')).not.toBeInTheDocument();
});
it('should not have override note', () => {
render(<SocialShareWidget
{...props}
videoSharingEnabledForCourse
allowVideoSharing={{
level: 'block',
value: false,
}}
/>);
expect(screen.queryByText('Note: This setting is overridden by the course outline page.')).not.toBeInTheDocument();
});
it('should have checkbox disabled prop equal false', () => {
render(<SocialShareWidget
{...props}
videoSharingEnabledForCourse
allowVideoSharing={{
level: 'block',
value: false,
}}
/>);
const checkbox = screen.getByRole('checkbox', { name: 'This video is shareable to social media' });
expect(checkbox).toBeInTheDocument();
expect(checkbox).toBeEnabled();
});
});
describe('isLibrary equals true', () => {
it('should not have setting location message', () => {
render(<SocialShareWidget
{...props}
videoSharingEnabledForAll
isLibrary
allowVideoSharing={{
level: 'block',
value: false,
}}
/>);
expect(screen.queryByText('Change this setting on the course outline page.')).not.toBeInTheDocument();
});
it('should not have override note', () => {
render(<SocialShareWidget
{...props}
videoSharingEnabledForAll
isLibrary
allowVideoSharing={{
level: 'block',
value: false,
}}
/>);
expect(screen.queryByText('Note: This setting is overridden by the course outline page.')).not.toBeInTheDocument();
});
it('should have checkbox disabled prop equal false', () => {
render(<SocialShareWidget
{...props}
videoSharingEnabledForAll
isLibrary
allowVideoSharing={{
level: 'block',
value: false,
}}
/>);
const checkbox = screen.getByRole('checkbox', { name: 'This video is shareable to social media' });
expect(checkbox).toBeInTheDocument();
expect(checkbox).toBeEnabled();
});
});
it('should have subtitle with text that reads Enabled', () => {
render(<SocialShareWidget
{...props}
videoSharingEnabledForCourse
allowVideoSharing={{
level: 'block',
value: false,
}}
/>);
expect(screen.getByText('Social Sharing')).toBeInTheDocument();
fireEvent.click(screen.getByText('Social Sharing'));
const subtitle = screen.getByText('Disabled');
expect(subtitle).toBeInTheDocument();
});
});
});
});

View File

@@ -1,925 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`TranscriptWidget component snapshots snapshot: render when \`isCreateWorkflow\` is \`True\` 1`] = `
<div
className="mr-4 ml-4"
>
<Card
className="bg-light-200"
>
<Card.Section
title={
<div
className="text-gray-500"
>
Transcripts
</div>
}
>
<div
className="d-flex justify-content-around text-gray-700 pb-4 x-small"
>
To add transcripts, save and reopen this video
</div>
</Card.Section>
</Card>
</div>
`;
exports[`TranscriptWidget component snapshots snapshot: renders ErrorAlert with delete error message 1`] = `
<CollapsibleFormWidget
fontSize="x-small"
isError={true}
subtitle="English"
title="Transcripts"
>
<ErrorAlert
dismissError={null}
hideHeading={true}
isError={false}
>
<FormattedMessage
defaultMessage="Failed to upload transcript. Please try again."
description="Message presented to user when transcript fails to upload"
id="authoring.videoeditor.transcript.error.uploadTranscriptError"
/>
</ErrorAlert>
<ErrorAlert
dismissError={null}
hideHeading={true}
isError={true}
>
<FormattedMessage
defaultMessage="Failed to delete transcript. Please try again."
description="Message presented to user when transcript fails to delete"
id="authoring.videoeditor.transcript.error.deleteTranscriptError"
/>
</ErrorAlert>
<Stack
gap={3}
>
<Form.Group
className="border-primary-100 border-bottom"
>
<Transcript
index={0}
language="en"
/>
<ActionRow
className="mt-3.5"
>
<Form.Checkbox
checked={false}
className="decorative-control-label"
onChange={[Function]}
>
<div
className="small text-gray-700"
>
<FormattedMessage
defaultMessage="Allow transcript downloads"
description="Label for allow transcript downloads checkbox"
id="authoring.videoeditor.transcripts.allowDownloadCheckboxLabel"
/>
</div>
</Form.Checkbox>
<OverlayTrigger
key="top"
overlay={
<Tooltip
id="tooltip-top"
>
<FormattedMessage
defaultMessage="Learners will see a link to download the transcript below the video."
description="Message for show by default checkbox"
id="authoring.videoeditor.transcripts.upload.allowDownloadTooltipMessage"
/>
</Tooltip>
}
placement="top"
>
<Icon
style={
{
"height": "16px",
"width": "16px",
}
}
/>
</OverlayTrigger>
<ActionRow.Spacer />
</ActionRow>
<Form.Checkbox
checked={false}
className="mt-3 decorative-control-label"
onChange={[Function]}
>
<div
className="small text-gray-700"
>
<FormattedMessage
defaultMessage="Show transcript in the video player by default"
description="Label for show by default checkbox"
id="authoring.videoeditor.transcripts.upload.showByDefaultCheckboxLabel"
/>
</div>
</Form.Checkbox>
</Form.Group>
<div
className="mt-2"
>
<Button
className="text-primary-500 font-weight-bold justify-content-start pl-0"
onClick={[Function]}
size="sm"
variant="link"
>
<FormattedMessage
defaultMessage="Add a transcript"
description="Label for upload button"
id="authoring.videoeditor.transcripts.upload.label"
/>
</Button>
</div>
</Stack>
</CollapsibleFormWidget>
`;
exports[`TranscriptWidget component snapshots snapshot: renders ErrorAlert with upload error message 1`] = `
<CollapsibleFormWidget
fontSize="x-small"
isError={true}
subtitle="English, French"
title="Transcripts"
>
<ErrorAlert
dismissError={null}
hideHeading={true}
isError={true}
>
<FormattedMessage
defaultMessage="Failed to upload transcript. Please try again."
description="Message presented to user when transcript fails to upload"
id="authoring.videoeditor.transcript.error.uploadTranscriptError"
/>
</ErrorAlert>
<ErrorAlert
dismissError={null}
hideHeading={true}
isError={false}
>
<FormattedMessage
defaultMessage="Failed to delete transcript. Please try again."
description="Message presented to user when transcript fails to delete"
id="authoring.videoeditor.transcript.error.deleteTranscriptError"
/>
</ErrorAlert>
<Stack
gap={3}
>
<Form.Group
className="border-primary-100 border-bottom"
>
<Transcript
index={0}
language="en"
/>
<Transcript
index={1}
language="fr"
/>
<ActionRow
className="mt-3.5"
>
<Form.Checkbox
checked={false}
className="decorative-control-label"
onChange={[Function]}
>
<div
className="small text-gray-700"
>
<FormattedMessage
defaultMessage="Allow transcript downloads"
description="Label for allow transcript downloads checkbox"
id="authoring.videoeditor.transcripts.allowDownloadCheckboxLabel"
/>
</div>
</Form.Checkbox>
<OverlayTrigger
key="top"
overlay={
<Tooltip
id="tooltip-top"
>
<FormattedMessage
defaultMessage="Learners will see a link to download the transcript below the video."
description="Message for show by default checkbox"
id="authoring.videoeditor.transcripts.upload.allowDownloadTooltipMessage"
/>
</Tooltip>
}
placement="top"
>
<Icon
style={
{
"height": "16px",
"width": "16px",
}
}
/>
</OverlayTrigger>
<ActionRow.Spacer />
</ActionRow>
<Form.Checkbox
checked={false}
className="mt-3 decorative-control-label"
onChange={[Function]}
>
<div
className="small text-gray-700"
>
<FormattedMessage
defaultMessage="Show transcript in the video player by default"
description="Label for show by default checkbox"
id="authoring.videoeditor.transcripts.upload.showByDefaultCheckboxLabel"
/>
</div>
</Form.Checkbox>
</Form.Group>
<div
className="mt-2"
>
<Button
className="text-primary-500 font-weight-bold justify-content-start pl-0"
onClick={[Function]}
size="sm"
variant="link"
>
<FormattedMessage
defaultMessage="Add a transcript"
description="Label for upload button"
id="authoring.videoeditor.transcripts.upload.label"
/>
</Button>
</div>
</Stack>
</CollapsibleFormWidget>
`;
exports[`TranscriptWidget component snapshots snapshots: renders as expected with allowTranscriptDownloads true 1`] = `
<CollapsibleFormWidget
fontSize="x-small"
isError={true}
subtitle="English"
title="Transcripts"
>
<ErrorAlert
dismissError={null}
hideHeading={true}
isError={false}
>
<FormattedMessage
defaultMessage="Failed to upload transcript. Please try again."
description="Message presented to user when transcript fails to upload"
id="authoring.videoeditor.transcript.error.uploadTranscriptError"
/>
</ErrorAlert>
<ErrorAlert
dismissError={null}
hideHeading={true}
isError={false}
>
<FormattedMessage
defaultMessage="Failed to delete transcript. Please try again."
description="Message presented to user when transcript fails to delete"
id="authoring.videoeditor.transcript.error.deleteTranscriptError"
/>
</ErrorAlert>
<Stack
gap={3}
>
<Form.Group
className="border-primary-100 border-bottom"
>
<Transcript
index={0}
language="en"
/>
<ActionRow
className="mt-3.5"
>
<Form.Checkbox
checked={true}
className="decorative-control-label"
onChange={[Function]}
>
<div
className="small text-gray-700"
>
<FormattedMessage
defaultMessage="Allow transcript downloads"
description="Label for allow transcript downloads checkbox"
id="authoring.videoeditor.transcripts.allowDownloadCheckboxLabel"
/>
</div>
</Form.Checkbox>
<OverlayTrigger
key="top"
overlay={
<Tooltip
id="tooltip-top"
>
<FormattedMessage
defaultMessage="Learners will see a link to download the transcript below the video."
description="Message for show by default checkbox"
id="authoring.videoeditor.transcripts.upload.allowDownloadTooltipMessage"
/>
</Tooltip>
}
placement="top"
>
<Icon
style={
{
"height": "16px",
"width": "16px",
}
}
/>
</OverlayTrigger>
<ActionRow.Spacer />
</ActionRow>
<Form.Checkbox
checked={false}
className="mt-3 decorative-control-label"
onChange={[Function]}
>
<div
className="small text-gray-700"
>
<FormattedMessage
defaultMessage="Show transcript in the video player by default"
description="Label for show by default checkbox"
id="authoring.videoeditor.transcripts.upload.showByDefaultCheckboxLabel"
/>
</div>
</Form.Checkbox>
</Form.Group>
<div
className="mt-2"
>
<Button
className="text-primary-500 font-weight-bold justify-content-start pl-0"
onClick={[Function]}
size="sm"
variant="link"
>
<FormattedMessage
defaultMessage="Add a transcript"
description="Label for upload button"
id="authoring.videoeditor.transcripts.upload.label"
/>
</Button>
</div>
</Stack>
</CollapsibleFormWidget>
`;
exports[`TranscriptWidget component snapshots snapshots: renders as expected with allowTranscriptImport true 1`] = `
<CollapsibleFormWidget
fontSize="x-small"
isError={true}
subtitle="None"
title="Transcripts"
>
<ErrorAlert
dismissError={null}
hideHeading={true}
isError={false}
>
<FormattedMessage
defaultMessage="Failed to upload transcript. Please try again."
description="Message presented to user when transcript fails to upload"
id="authoring.videoeditor.transcript.error.uploadTranscriptError"
/>
</ErrorAlert>
<ErrorAlert
dismissError={null}
hideHeading={true}
isError={false}
>
<FormattedMessage
defaultMessage="Failed to delete transcript. Please try again."
description="Message presented to user when transcript fails to delete"
id="authoring.videoeditor.transcript.error.deleteTranscriptError"
/>
</ErrorAlert>
<Stack
gap={3}
>
<Fragment>
<FormattedMessage
defaultMessage="Add video transcripts (.srt files only) for improved accessibility."
description="Message for adding first transcript"
id="authoring.videoeditor.transcripts.upload.firstTranscriptMessage"
/>
<injectIntl(ShimmedIntlComponent)
setOpen={[Function]}
/>
</Fragment>
<div
className="mt-2"
>
<Button
className="text-primary-500 font-weight-bold justify-content-start pl-0"
onClick={[Function]}
size="sm"
variant="link"
>
<FormattedMessage
defaultMessage="Add a transcript"
description="Label for upload button"
id="authoring.videoeditor.transcripts.upload.label"
/>
</Button>
</div>
</Stack>
</CollapsibleFormWidget>
`;
exports[`TranscriptWidget component snapshots snapshots: renders as expected with default props 1`] = `
<CollapsibleFormWidget
fontSize="x-small"
isError={true}
subtitle="None"
title="Transcripts"
>
<ErrorAlert
dismissError={null}
hideHeading={true}
isError={false}
>
<FormattedMessage
defaultMessage="Failed to upload transcript. Please try again."
description="Message presented to user when transcript fails to upload"
id="authoring.videoeditor.transcript.error.uploadTranscriptError"
/>
</ErrorAlert>
<ErrorAlert
dismissError={null}
hideHeading={true}
isError={false}
>
<FormattedMessage
defaultMessage="Failed to delete transcript. Please try again."
description="Message presented to user when transcript fails to delete"
id="authoring.videoeditor.transcript.error.deleteTranscriptError"
/>
</ErrorAlert>
<Stack
gap={3}
>
<Fragment>
<FormattedMessage
defaultMessage="Add video transcripts (.srt files only) for improved accessibility."
description="Message for adding first transcript"
id="authoring.videoeditor.transcripts.upload.firstTranscriptMessage"
/>
</Fragment>
<div
className="mt-2"
>
<Button
className="text-primary-500 font-weight-bold justify-content-start pl-0"
onClick={[Function]}
size="sm"
variant="link"
>
<FormattedMessage
defaultMessage="Add a transcript"
description="Label for upload button"
id="authoring.videoeditor.transcripts.upload.label"
/>
</Button>
</div>
</Stack>
</CollapsibleFormWidget>
`;
exports[`TranscriptWidget component snapshots snapshots: renders as expected with showTranscriptByDefault true 1`] = `
<CollapsibleFormWidget
fontSize="x-small"
isError={true}
subtitle="English"
title="Transcripts"
>
<ErrorAlert
dismissError={null}
hideHeading={true}
isError={false}
>
<FormattedMessage
defaultMessage="Failed to upload transcript. Please try again."
description="Message presented to user when transcript fails to upload"
id="authoring.videoeditor.transcript.error.uploadTranscriptError"
/>
</ErrorAlert>
<ErrorAlert
dismissError={null}
hideHeading={true}
isError={false}
>
<FormattedMessage
defaultMessage="Failed to delete transcript. Please try again."
description="Message presented to user when transcript fails to delete"
id="authoring.videoeditor.transcript.error.deleteTranscriptError"
/>
</ErrorAlert>
<Stack
gap={3}
>
<Form.Group
className="border-primary-100 border-bottom"
>
<Transcript
index={0}
language="en"
/>
<ActionRow
className="mt-3.5"
>
<Form.Checkbox
checked={false}
className="decorative-control-label"
onChange={[Function]}
>
<div
className="small text-gray-700"
>
<FormattedMessage
defaultMessage="Allow transcript downloads"
description="Label for allow transcript downloads checkbox"
id="authoring.videoeditor.transcripts.allowDownloadCheckboxLabel"
/>
</div>
</Form.Checkbox>
<OverlayTrigger
key="top"
overlay={
<Tooltip
id="tooltip-top"
>
<FormattedMessage
defaultMessage="Learners will see a link to download the transcript below the video."
description="Message for show by default checkbox"
id="authoring.videoeditor.transcripts.upload.allowDownloadTooltipMessage"
/>
</Tooltip>
}
placement="top"
>
<Icon
style={
{
"height": "16px",
"width": "16px",
}
}
/>
</OverlayTrigger>
<ActionRow.Spacer />
</ActionRow>
<Form.Checkbox
checked={true}
className="mt-3 decorative-control-label"
onChange={[Function]}
>
<div
className="small text-gray-700"
>
<FormattedMessage
defaultMessage="Show transcript in the video player by default"
description="Label for show by default checkbox"
id="authoring.videoeditor.transcripts.upload.showByDefaultCheckboxLabel"
/>
</div>
</Form.Checkbox>
</Form.Group>
<div
className="mt-2"
>
<Button
className="text-primary-500 font-weight-bold justify-content-start pl-0"
onClick={[Function]}
size="sm"
variant="link"
>
<FormattedMessage
defaultMessage="Add a transcript"
description="Label for upload button"
id="authoring.videoeditor.transcripts.upload.label"
/>
</Button>
</div>
</Stack>
</CollapsibleFormWidget>
`;
exports[`TranscriptWidget component snapshots snapshots: renders as expected with transcript urls 1`] = `
<CollapsibleFormWidget
fontSize="x-small"
isError={true}
subtitle="None"
title="Transcripts"
>
<ErrorAlert
dismissError={null}
hideHeading={true}
isError={false}
>
<FormattedMessage
defaultMessage="Failed to upload transcript. Please try again."
description="Message presented to user when transcript fails to upload"
id="authoring.videoeditor.transcript.error.uploadTranscriptError"
/>
</ErrorAlert>
<ErrorAlert
dismissError={null}
hideHeading={true}
isError={false}
>
<FormattedMessage
defaultMessage="Failed to delete transcript. Please try again."
description="Message presented to user when transcript fails to delete"
id="authoring.videoeditor.transcript.error.deleteTranscriptError"
/>
</ErrorAlert>
<Stack
gap={3}
>
<Fragment>
<FormattedMessage
defaultMessage="Add video transcripts (.srt files only) for improved accessibility."
description="Message for adding first transcript"
id="authoring.videoeditor.transcripts.upload.firstTranscriptMessage"
/>
</Fragment>
<div
className="mt-2"
>
<Button
className="text-primary-500 font-weight-bold justify-content-start pl-0"
onClick={[Function]}
size="sm"
variant="link"
>
<FormattedMessage
defaultMessage="Add a transcript"
description="Label for upload button"
id="authoring.videoeditor.transcripts.upload.label"
/>
</Button>
</div>
</Stack>
</CollapsibleFormWidget>
`;
exports[`TranscriptWidget component snapshots snapshots: renders as expected with transcripts 1`] = `
<CollapsibleFormWidget
fontSize="x-small"
isError={true}
subtitle="English"
title="Transcripts"
>
<ErrorAlert
dismissError={null}
hideHeading={true}
isError={false}
>
<FormattedMessage
defaultMessage="Failed to upload transcript. Please try again."
description="Message presented to user when transcript fails to upload"
id="authoring.videoeditor.transcript.error.uploadTranscriptError"
/>
</ErrorAlert>
<ErrorAlert
dismissError={null}
hideHeading={true}
isError={false}
>
<FormattedMessage
defaultMessage="Failed to delete transcript. Please try again."
description="Message presented to user when transcript fails to delete"
id="authoring.videoeditor.transcript.error.deleteTranscriptError"
/>
</ErrorAlert>
<Stack
gap={3}
>
<Form.Group
className="border-primary-100 border-bottom"
>
<Transcript
index={0}
language="en"
/>
<ActionRow
className="mt-3.5"
>
<Form.Checkbox
checked={false}
className="decorative-control-label"
onChange={[Function]}
>
<div
className="small text-gray-700"
>
<FormattedMessage
defaultMessage="Allow transcript downloads"
description="Label for allow transcript downloads checkbox"
id="authoring.videoeditor.transcripts.allowDownloadCheckboxLabel"
/>
</div>
</Form.Checkbox>
<OverlayTrigger
key="top"
overlay={
<Tooltip
id="tooltip-top"
>
<FormattedMessage
defaultMessage="Learners will see a link to download the transcript below the video."
description="Message for show by default checkbox"
id="authoring.videoeditor.transcripts.upload.allowDownloadTooltipMessage"
/>
</Tooltip>
}
placement="top"
>
<Icon
style={
{
"height": "16px",
"width": "16px",
}
}
/>
</OverlayTrigger>
<ActionRow.Spacer />
</ActionRow>
<Form.Checkbox
checked={false}
className="mt-3 decorative-control-label"
onChange={[Function]}
>
<div
className="small text-gray-700"
>
<FormattedMessage
defaultMessage="Show transcript in the video player by default"
description="Label for show by default checkbox"
id="authoring.videoeditor.transcripts.upload.showByDefaultCheckboxLabel"
/>
</div>
</Form.Checkbox>
</Form.Group>
<div
className="mt-2"
>
<Button
className="text-primary-500 font-weight-bold justify-content-start pl-0"
onClick={[Function]}
size="sm"
variant="link"
>
<FormattedMessage
defaultMessage="Add a transcript"
description="Label for upload button"
id="authoring.videoeditor.transcripts.upload.label"
/>
</Button>
</div>
</Stack>
</CollapsibleFormWidget>
`;
exports[`TranscriptWidget component snapshots snapshots: renders as expected with transcripts and urls 1`] = `
<CollapsibleFormWidget
fontSize="x-small"
isError={true}
subtitle="Spanish"
title="Transcripts"
>
<ErrorAlert
dismissError={null}
hideHeading={true}
isError={false}
>
<FormattedMessage
defaultMessage="Failed to upload transcript. Please try again."
description="Message presented to user when transcript fails to upload"
id="authoring.videoeditor.transcript.error.uploadTranscriptError"
/>
</ErrorAlert>
<ErrorAlert
dismissError={null}
hideHeading={true}
isError={false}
>
<FormattedMessage
defaultMessage="Failed to delete transcript. Please try again."
description="Message presented to user when transcript fails to delete"
id="authoring.videoeditor.transcript.error.deleteTranscriptError"
/>
</ErrorAlert>
<Stack
gap={3}
>
<Form.Group
className="border-primary-100 border-bottom"
>
<Transcript
index={0}
language="es"
/>
<ActionRow
className="mt-3.5"
>
<Form.Checkbox
checked={false}
className="decorative-control-label"
onChange={[Function]}
>
<div
className="small text-gray-700"
>
<FormattedMessage
defaultMessage="Allow transcript downloads"
description="Label for allow transcript downloads checkbox"
id="authoring.videoeditor.transcripts.allowDownloadCheckboxLabel"
/>
</div>
</Form.Checkbox>
<OverlayTrigger
key="top"
overlay={
<Tooltip
id="tooltip-top"
>
<FormattedMessage
defaultMessage="Learners will see a link to download the transcript below the video."
description="Message for show by default checkbox"
id="authoring.videoeditor.transcripts.upload.allowDownloadTooltipMessage"
/>
</Tooltip>
}
placement="top"
>
<Icon
style={
{
"height": "16px",
"width": "16px",
}
}
/>
</OverlayTrigger>
<ActionRow.Spacer />
</ActionRow>
<Form.Checkbox
checked={false}
className="mt-3 decorative-control-label"
onChange={[Function]}
>
<div
className="small text-gray-700"
>
<FormattedMessage
defaultMessage="Show transcript in the video player by default"
description="Label for show by default checkbox"
id="authoring.videoeditor.transcripts.upload.showByDefaultCheckboxLabel"
/>
</div>
</Form.Checkbox>
</Form.Group>
<div
className="mt-2"
>
<Button
className="text-primary-500 font-weight-bold justify-content-start pl-0"
onClick={[Function]}
size="sm"
variant="link"
>
<FormattedMessage
defaultMessage="Add a transcript"
description="Label for upload button"
id="authoring.videoeditor.transcripts.upload.label"
/>
</Button>
</div>
</Stack>
</CollapsibleFormWidget>
`;

View File

@@ -1,24 +1,16 @@
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,
} from '@src/testUtils';
import * as reactredux from 'react-redux';
import { RequestKeys } from '../../../../../../data/constants/requests';
import { formatMessage } from '../../../../../../testUtils';
import { actions, selectors } from '../../../../../../data/redux';
// This 'module' self-import hack enables mocking during tests.
// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
// should be re-thought and cleaned up to avoid this pattern.
// eslint-disable-next-line import/no-self-import
import * as module from './index';
const TranscriptWidget = module.TranscriptWidgetInternal;
jest.mock('react', () => ({
...jest.requireActual('react'),
useContext: jest.fn(() => ({ transcripts: ['error.transcripts', jest.fn().mockName('error.setTranscripts')] })),
}));
import {
TranscriptWidgetInternal as TranscriptWidget, mapStateToProps, mapDispatchToProps, hooks,
} from './index';
jest.mock('../../../../../../data/redux', () => ({
actions: {
@@ -59,48 +51,48 @@ jest.mock('react-redux', () => ({
useSelector: jest.fn(),
}));
useSelector.mockImplementation((selectorFn) => selectorFn({}));
jest.spyOn(reactredux, 'useSelector').mockImplementation((selectorFn) => selectorFn({}));
describe('TranscriptWidget', () => {
beforeEach(() => {
selectors.app.shouldCreateBlock.mockReset();
jest.spyOn(selectors.app, 'shouldCreateBlock').mockReset();
});
describe('hooks', () => {
describe('transcriptLanguages', () => {
test('empty list of transcripts returns ', () => {
expect(module.hooks.transcriptLanguages([])).toEqual('None');
expect(hooks.transcriptLanguages([])).toEqual('None');
});
test('unset gives none', () => {
expect(module.hooks.transcriptLanguages(['', ''])).toEqual('');
expect(hooks.transcriptLanguages(['', ''])).toEqual('');
});
test('en gives English', () => {
expect(module.hooks.transcriptLanguages(['en'])).toEqual('English');
expect(hooks.transcriptLanguages(['en'])).toEqual('English');
});
test('en, FR gives English, French', () => {
expect(module.hooks.transcriptLanguages(['en', 'fr'])).toEqual('English, French');
expect(hooks.transcriptLanguages(['en', 'fr'])).toEqual('English, French');
});
});
describe('hasTranscripts', () => {
test('null returns false ', () => {
expect(module.hooks.hasTranscripts(null)).toEqual(false);
expect(hooks.hasTranscripts(null)).toEqual(false);
});
test('empty list returns false', () => {
expect(module.hooks.hasTranscripts([])).toEqual(false);
expect(hooks.hasTranscripts([])).toEqual(false);
});
test('content returns true', () => {
expect(module.hooks.hasTranscripts(['en'])).toEqual(true);
expect(hooks.hasTranscripts(['en'])).toEqual(true);
});
});
describe('onAddNewTranscript', () => {
const mockUpdateField = jest.fn();
test('null returns [empty string] ', () => {
module.hooks.onAddNewTranscript({ transcripts: null, updateField: mockUpdateField });
hooks.onAddNewTranscript({ transcripts: null, updateField: mockUpdateField });
expect(mockUpdateField).toHaveBeenCalledWith({ transcripts: [''] });
});
test(' transcripts return list with blank added', () => {
const mocklist = ['en', 'fr', 3];
module.hooks.onAddNewTranscript({ transcripts: mocklist, updateField: mockUpdateField });
hooks.onAddNewTranscript({ transcripts: mocklist, updateField: mockUpdateField });
expect(mockUpdateField).toHaveBeenCalledWith({ transcripts: ['en', 'fr', 3, ''] });
});
@@ -123,96 +115,110 @@ describe('TranscriptWidget', () => {
isDeleteError: false,
};
describe('snapshots', () => {
test('snapshots: renders as expected with default props', () => {
expect(
shallow(<TranscriptWidget {...props} />).snapshot,
).toMatchSnapshot();
beforeEach(() => {
initializeMocks();
});
describe('render component', () => {
test('renders as expected with default props', () => {
const { container } = render(<TranscriptWidget {...props} />);
expect(container.querySelector('collapsibleformwidget')).toBeInTheDocument();
expect(screen.getByText('Add video transcripts (.srt files only) for improved accessibility.')).toBeInTheDocument();
});
test('snapshots: renders as expected with allowTranscriptImport true', () => {
expect(
shallow(<TranscriptWidget {...props} allowTranscriptImport />).snapshot,
).toMatchSnapshot();
test('renders as expected with allowTranscriptImport true', () => {
render(<TranscriptWidget {...props} allowTranscriptImport />);
expect(screen.getByText('We found transcript for this video on YouTube. Would you like to import it now?')).toBeInTheDocument();
});
test('snapshots: renders as expected with transcripts', () => {
expect(
shallow(<TranscriptWidget {...props} transcripts={['en']} />).snapshot,
).toMatchSnapshot();
test('renders as expected with transcripts', () => {
const { container } = render(<TranscriptWidget {...props} transcripts={['en']} />);
expect(container.querySelector('transcript')).toBeInTheDocument();
expect(container.querySelector('transcript')).toHaveAttribute('language', 'en');
});
test('snapshots: renders as expected with transcript urls', () => {
expect(
shallow(<TranscriptWidget {...props} selectedVideoTranscriptUrls={{ en: 'url' }} />).snapshot,
).toMatchSnapshot();
test('renders as expected with transcripts and urls', () => {
const { container } = render(<TranscriptWidget {...props} transcripts={['en']} selectedVideoTranscriptUrls={{ en: 'url' }} />);
expect(container.querySelector('transcript')).toBeInTheDocument();
expect(container.querySelector('transcript')).toHaveAttribute('language', 'en');
expect(container.querySelector('transcript')).toHaveAttribute('transcriptUrl', 'url');
});
test('snapshots: renders as expected with transcripts and urls', () => {
expect(
shallow(<TranscriptWidget {...props} transcripts={['es']} selectedVideoTranscriptUrls={{ en: 'url' }} />).snapshot,
).toMatchSnapshot();
test('renders as expected with allowTranscriptDownloads true', () => {
const { container } = render(<TranscriptWidget {...props} allowTranscriptDownloads transcripts={['en']} />);
expect(container.querySelector('transcript')).toBeInTheDocument();
expect(container.querySelector('transcript')).toHaveAttribute('language', 'en');
const checkbox = screen.getByRole('checkbox', { name: 'Allow transcript downloads' });
expect(checkbox).toBeInTheDocument();
expect(checkbox).toBeChecked();
});
test('snapshots: renders as expected with allowTranscriptDownloads true', () => {
expect(
shallow(<TranscriptWidget {...props} allowTranscriptDownloads transcripts={['en']} />).snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with showTranscriptByDefault true', () => {
expect(
shallow(<TranscriptWidget {...props} showTranscriptByDefault transcripts={['en']} />).snapshot,
).toMatchSnapshot();
test('renders as expected with showTranscriptByDefault true', () => {
render(<TranscriptWidget {...props} showTranscriptByDefault transcripts={['en']} />);
const checkbox = screen.getByRole('checkbox', { name: 'Show transcript in the video player by default' });
expect(checkbox).toBeInTheDocument();
expect(checkbox).toBeChecked();
});
test('snapshot: renders ErrorAlert with upload error message', () => {
expect(
shallow(<TranscriptWidget {...props} isUploadError transcripts={['en', 'fr']} />).snapshot,
).toMatchSnapshot();
render(<TranscriptWidget {...props} isUploadError transcripts={['en', 'fr']} />);
expect(screen.getByText('Failed to upload transcript. Please try again.')).toBeInTheDocument();
});
test('snapshot: renders ErrorAlert with delete error message', () => {
expect(
shallow(<TranscriptWidget {...props} isDeleteError transcripts={['en']} />).snapshot,
).toMatchSnapshot();
render(<TranscriptWidget {...props} isDeleteError transcripts={['en']} />);
expect(screen.getByText('Failed to delete transcript. Please try again.')).toBeInTheDocument();
});
test('snapshot: render when `isCreateWorkflow` is `True`', () => {
selectors.app.shouldCreateBlock.mockReturnValue(true);
expect(
shallow(<TranscriptWidget {...props} />).snapshot,
).toMatchSnapshot();
jest.spyOn(selectors.app, 'shouldCreateBlock').mockReturnValue(true);
render(<TranscriptWidget {...props} />);
expect(screen.getByText('Transcripts')).toBeInTheDocument();
expect(screen.getByText('To add transcripts, save and reopen this video')).toBeInTheDocument();
});
});
describe('mapStateToProps', () => {
const testState = { A: 'pple', B: 'anana', C: 'ucumber' };
test('transcripts from video.transcript', () => {
expect(
module.mapStateToProps(testState).transcripts,
mapStateToProps(testState).transcripts,
// @ts-ignore
).toEqual(selectors.video.transcripts(testState));
});
test('allowTranscriptDownloads from video.allowTranscriptDownloads', () => {
expect(
module.mapStateToProps(testState).allowTranscriptDownloads,
mapStateToProps(testState).allowTranscriptDownloads,
// @ts-ignore
).toEqual(selectors.video.allowTranscriptDownloads(testState));
});
test('showTranscriptByDefault from video.showTranscriptByDefault', () => {
expect(
module.mapStateToProps(testState).showTranscriptByDefault,
mapStateToProps(testState).showTranscriptByDefault,
// @ts-ignore
).toEqual(selectors.video.showTranscriptByDefault(testState));
});
test('allowTranscriptImport from video.allowTranscriptImport', () => {
expect(
module.mapStateToProps(testState).allowTranscriptImport,
mapStateToProps(testState).allowTranscriptImport,
// @ts-ignore
).toEqual(selectors.video.allowTranscriptImport(testState));
});
test('isUploadError from requests.isFinished', () => {
expect(
module.mapStateToProps(testState).isUploadError,
mapStateToProps(testState).isUploadError,
).toEqual(selectors.requests.isFailed(testState, { requestKey: RequestKeys.uploadTranscript }));
});
test('isDeleteError from requests.isFinished', () => {
expect(
module.mapStateToProps(testState).isDeleteError,
mapStateToProps(testState).isDeleteError,
).toEqual(selectors.requests.isFailed(testState, { requestKey: RequestKeys.deleteTranscript }));
});
});
describe('mapDispatchToProps', () => {
const dispatch = jest.fn();
test('updateField from actions.video.updateField', () => {
expect(module.mapDispatchToProps.updateField).toEqual(dispatch(actions.video.updateField));
// @ts-ignore
expect(mapDispatchToProps.updateField).toEqual(dispatch(actions.video.updateField));
});
});
});