feat: program card tests
This commit is contained in:
@@ -129,11 +129,11 @@ exports[`EmailSettingsModal render snapshot: emails enabled, show: true 1`] = `
|
||||
/>
|
||||
</h4>
|
||||
<Form.Switch
|
||||
checked={true}
|
||||
checked={false}
|
||||
onChange={[MockFunction hooks.onToggle]}
|
||||
>
|
||||
<formatMessage
|
||||
msg="Course emails are on"
|
||||
msg="Course emails are off"
|
||||
/>
|
||||
</Form.Switch>
|
||||
<p>
|
||||
|
||||
@@ -27,10 +27,10 @@ const dispatch = useDispatch();
|
||||
describe('EmailSettingsModal', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
hooks.mockReturnValueOnce(hookProps);
|
||||
});
|
||||
describe('behavior', () => {
|
||||
beforeEach(() => {
|
||||
hooks.mockReturnValueOnce(hookProps);
|
||||
shallow(<EmailSettingsModal {...props} />);
|
||||
});
|
||||
it('calls hook w/ dispatch from redux hook, and closeModal, courseNumber from props', () => {
|
||||
@@ -43,9 +43,11 @@ describe('EmailSettingsModal', () => {
|
||||
});
|
||||
describe('render', () => {
|
||||
test('snapshot: emails disabled, show: false', () => {
|
||||
hooks.mockReturnValueOnce(hookProps);
|
||||
expect(shallow(<EmailSettingsModal {...props} show={false} />)).toMatchSnapshot();
|
||||
});
|
||||
test('snapshot: emails disabled, show: true', () => {
|
||||
hooks.mockReturnValueOnce(hookProps);
|
||||
expect(shallow(<EmailSettingsModal {...props} />)).toMatchSnapshot();
|
||||
});
|
||||
test('snapshot: emails enabled, show: true', () => {
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`RelatedProgramsModal snapshot: closed 1`] = `
|
||||
<ModalDialog
|
||||
className="related-programs-modal p-4"
|
||||
hasCloseButton={true}
|
||||
isFullscreenOnMobile={true}
|
||||
isOpen={false}
|
||||
onClose={[MockFunction props.closeModal]}
|
||||
size="lg"
|
||||
title={
|
||||
<formatMessage
|
||||
msg="Related Programs"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<ModalDialog.Header
|
||||
as="h3"
|
||||
className="programs-title m-0 p-0"
|
||||
>
|
||||
<formatMessage
|
||||
msg="Related Programs"
|
||||
/>
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Header
|
||||
as="h4"
|
||||
className="programs-header p-0"
|
||||
>
|
||||
hookProps.courseTitle
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Body
|
||||
className="pl-0"
|
||||
>
|
||||
<p>
|
||||
<formatMessage
|
||||
msg="Are you looking to expand your knowledge? Enrolling in a Program lets you take a series of courses in the subject that you're interested in"
|
||||
/>
|
||||
</p>
|
||||
<CardGrid
|
||||
columnSizes={
|
||||
Object {
|
||||
"lg": 6,
|
||||
"xlg": 4,
|
||||
"xs": 12,
|
||||
}
|
||||
}
|
||||
>
|
||||
<ProgramCard
|
||||
data={
|
||||
Object {
|
||||
"programData": Object {
|
||||
"dataFor": "program1",
|
||||
},
|
||||
"programUrl": "program-1-url",
|
||||
}
|
||||
}
|
||||
key="program-1-url"
|
||||
/>
|
||||
<ProgramCard
|
||||
data={
|
||||
Object {
|
||||
"programData": Object {
|
||||
"dataFor": "program2",
|
||||
},
|
||||
"programUrl": "program-2-url",
|
||||
}
|
||||
}
|
||||
key="program-2-url"
|
||||
/>
|
||||
<ProgramCard
|
||||
data={
|
||||
Object {
|
||||
"programData": Object {
|
||||
"dataFor": "program3",
|
||||
},
|
||||
"programUrl": "program-3-url",
|
||||
}
|
||||
}
|
||||
key="program-3-url"
|
||||
/>
|
||||
</CardGrid>
|
||||
</ModalDialog.Body>
|
||||
</ModalDialog>
|
||||
`;
|
||||
|
||||
exports[`RelatedProgramsModal snapshot: open 1`] = `
|
||||
<ModalDialog
|
||||
className="related-programs-modal p-4"
|
||||
hasCloseButton={true}
|
||||
isFullscreenOnMobile={true}
|
||||
isOpen={true}
|
||||
onClose={[MockFunction props.closeModal]}
|
||||
size="lg"
|
||||
title={
|
||||
<formatMessage
|
||||
msg="Related Programs"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<ModalDialog.Header
|
||||
as="h3"
|
||||
className="programs-title m-0 p-0"
|
||||
>
|
||||
<formatMessage
|
||||
msg="Related Programs"
|
||||
/>
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Header
|
||||
as="h4"
|
||||
className="programs-header p-0"
|
||||
>
|
||||
hookProps.courseTitle
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Body
|
||||
className="pl-0"
|
||||
>
|
||||
<p>
|
||||
<formatMessage
|
||||
msg="Are you looking to expand your knowledge? Enrolling in a Program lets you take a series of courses in the subject that you're interested in"
|
||||
/>
|
||||
</p>
|
||||
<CardGrid
|
||||
columnSizes={
|
||||
Object {
|
||||
"lg": 6,
|
||||
"xlg": 4,
|
||||
"xs": 12,
|
||||
}
|
||||
}
|
||||
>
|
||||
<ProgramCard
|
||||
data={
|
||||
Object {
|
||||
"programData": Object {
|
||||
"dataFor": "program1",
|
||||
},
|
||||
"programUrl": "program-1-url",
|
||||
}
|
||||
}
|
||||
key="program-1-url"
|
||||
/>
|
||||
<ProgramCard
|
||||
data={
|
||||
Object {
|
||||
"programData": Object {
|
||||
"dataFor": "program2",
|
||||
},
|
||||
"programUrl": "program-2-url",
|
||||
}
|
||||
}
|
||||
key="program-2-url"
|
||||
/>
|
||||
<ProgramCard
|
||||
data={
|
||||
Object {
|
||||
"programData": Object {
|
||||
"dataFor": "program3",
|
||||
},
|
||||
"programUrl": "program-3-url",
|
||||
}
|
||||
}
|
||||
key="program-3-url"
|
||||
/>
|
||||
</CardGrid>
|
||||
</ModalDialog.Body>
|
||||
</ModalDialog>
|
||||
`;
|
||||
@@ -10,23 +10,11 @@ import {
|
||||
} from '@edx/paragon';
|
||||
import { Program } from '@edx/paragon/icons';
|
||||
|
||||
import messages from './messages';
|
||||
import './index.scss';
|
||||
|
||||
export const whiteFontWrapper = (node) => (<span className="text-white">{node}</span>);
|
||||
|
||||
export const messages = {
|
||||
courses: {
|
||||
id: 'learnerDashboard.programCard.courses',
|
||||
defaultMessage: '{numCourses} Courses',
|
||||
description: 'Number of courses in a program, displayed at the bottom of program card',
|
||||
},
|
||||
duration: {
|
||||
id: 'learnerDashboard.programCard.duration',
|
||||
defaultMessage: '{numWeeks} Weeks',
|
||||
description: 'Number of weeks in a program, displayed at the bottom of program card',
|
||||
},
|
||||
};
|
||||
|
||||
export const ProgramCard = ({ data }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const numCoursesMessage = formatMessage(
|
||||
@@ -45,9 +33,9 @@ export const ProgramCard = ({ data }) => {
|
||||
<Card.ImageCap
|
||||
className="program-card-banner"
|
||||
src={data.bannerUrl}
|
||||
srcAlt="Program banner"
|
||||
srcAlt={formatMessage(messages.bannerAlt)}
|
||||
logoSrc={data.logoUrl}
|
||||
logoAlt="Provider logo"
|
||||
logoAlt={formatMessage(messages.logoAlt)}
|
||||
/>
|
||||
<Card.Header
|
||||
title={whiteFontWrapper(data.title)}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import ProgramCard from './ProgramCard';
|
||||
|
||||
const props = {
|
||||
data: {
|
||||
estimatedNumberOfWeeks: 1,
|
||||
numberOfCourses: 2,
|
||||
bannerUrl: 'props.data.bannerUrl',
|
||||
logoUrl: 'props.data.logoUrl',
|
||||
title: 'props.data.title',
|
||||
provider: 'props.data.provider',
|
||||
programType: 'props.data.programType',
|
||||
programUrl: 'props.data.programUrl',
|
||||
programTypeUrl: 'props.data.programTypeUrl',
|
||||
},
|
||||
};
|
||||
|
||||
describe('RelatedProgramsModal ProgramCard', () => {
|
||||
test('snapshot', () => {
|
||||
expect(shallow(<ProgramCard {...props} />)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,70 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`RelatedProgramsModal ProgramCard snapshot 1`] = `
|
||||
<Card
|
||||
className="program-card d-inline-block bg-primary-500 text-white pb-3.5"
|
||||
style={
|
||||
Object {
|
||||
"color": "white",
|
||||
"width": "18rem",
|
||||
}
|
||||
}
|
||||
>
|
||||
<Card.ImageCap
|
||||
className="program-card-banner"
|
||||
logoAlt={
|
||||
<formatMessage
|
||||
msg="Provider logo"
|
||||
/>
|
||||
}
|
||||
logoSrc="props.data.logoUrl"
|
||||
src="props.data.bannerUrl"
|
||||
srcAlt={
|
||||
<formatMessage
|
||||
msg="Programm banner"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Card.Header
|
||||
subtitle={
|
||||
<span
|
||||
className="text-white"
|
||||
>
|
||||
props.data.provider
|
||||
</span>
|
||||
}
|
||||
title={
|
||||
<span
|
||||
className="text-white"
|
||||
>
|
||||
props.data.title
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="ml-4"
|
||||
>
|
||||
<Badge
|
||||
className="program-type-badge"
|
||||
variant="light"
|
||||
>
|
||||
<Icon
|
||||
className="d-inline-block"
|
||||
/>
|
||||
|
||||
props.data.programType
|
||||
</Badge>
|
||||
<div
|
||||
className="program-summary mt-2"
|
||||
>
|
||||
<formatMessage
|
||||
msg="{numCourses} Courses"
|
||||
/>
|
||||
•
|
||||
<formatMessage
|
||||
msg="{numWeeks} Weeks"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
`;
|
||||
24
src/containers/RelatedProgramsModal/components/messages.js
Normal file
24
src/containers/RelatedProgramsModal/components/messages.js
Normal file
@@ -0,0 +1,24 @@
|
||||
export const messages = {
|
||||
courses: {
|
||||
id: 'learnerDashboard.programCard.courses',
|
||||
defaultMessage: '{numCourses} Courses',
|
||||
description: 'Number of courses in a program, displayed at the bottom of program card',
|
||||
},
|
||||
duration: {
|
||||
id: 'learnerDashboard.programCard.duration',
|
||||
defaultMessage: '{numWeeks} Weeks',
|
||||
description: 'Number of weeks in a program, displayed at the bottom of program card',
|
||||
},
|
||||
logoAlt: {
|
||||
id: 'learnerDashboard.programCard.logoAlt',
|
||||
defaultMessage: 'Provider logo',
|
||||
description: 'Program provider logo alt-text',
|
||||
},
|
||||
bannerAlt: {
|
||||
id: 'learnerDashboard.programCard.bannerAlt',
|
||||
defaultMessage: 'Programm banner',
|
||||
description: 'Program banner logo alt-text',
|
||||
},
|
||||
};
|
||||
|
||||
export default messages;
|
||||
@@ -1,16 +1,19 @@
|
||||
import { selectors } from 'data/redux';
|
||||
import { getCardValue } from 'hooks';
|
||||
import { getCardValues } from 'hooks';
|
||||
|
||||
const { cardData } = selectors;
|
||||
const { programs } = cardData;
|
||||
|
||||
export const programsModalData = ({
|
||||
export const modalData = ({
|
||||
courseNumber,
|
||||
}) => {
|
||||
const cardValue = getCardValue(courseNumber);
|
||||
const data = getCardValues(courseNumber, {
|
||||
courseTitle: cardData.courseTitle,
|
||||
relatedPrograms: cardData.relatedPrograms,
|
||||
});
|
||||
return {
|
||||
courseTitle: cardValue(cardData.courseTitle),
|
||||
relatedPrograms: cardValue(cardData.relatedPrograms).map(program => ({
|
||||
courseTitle: data.courseTitle,
|
||||
relatedPrograms: data.relatedPrograms.map(program => ({
|
||||
estimatedNumberOfWeeks: programs.estimatedNumberOfWeeks(program),
|
||||
numberOfCourses: programs.numberOfCourses(program),
|
||||
programType: programs.programType(program),
|
||||
@@ -21,4 +24,4 @@ export const programsModalData = ({
|
||||
};
|
||||
};
|
||||
|
||||
export default programsModalData;
|
||||
export default modalData;
|
||||
|
||||
67
src/containers/RelatedProgramsModal/hooks.test.js
Normal file
67
src/containers/RelatedProgramsModal/hooks.test.js
Normal file
@@ -0,0 +1,67 @@
|
||||
import { testCardValues } from 'testUtils';
|
||||
import * as appHooks from 'hooks';
|
||||
import { selectors } from 'data/redux';
|
||||
|
||||
import * as hooks from './hooks';
|
||||
|
||||
jest.mock('data/redux/cardData/selectors', () => ({
|
||||
...jest.requireActual('data/redux/cardData/selectors'),
|
||||
programs: {
|
||||
estimatedNumberOfWeeks: (p) => p.estimatedNumberOfWeeks,
|
||||
numberOfCourses: (p) => p.numberOfCourses,
|
||||
programType: (p) => p.programType,
|
||||
programTypeUrl: (p) => p.programTypeUrl,
|
||||
provider: (p) => p.provider,
|
||||
title: (p) => p.title,
|
||||
},
|
||||
}));
|
||||
|
||||
const { fieldKeys } = selectors.cardData;
|
||||
|
||||
const courseNumber = 'test-course-number';
|
||||
|
||||
const courseTitle = 'test-course-title';
|
||||
const relatedPrograms = [
|
||||
{
|
||||
estimatedNumberOfWeeks: 1,
|
||||
numberOfCourses: 2,
|
||||
programType: 'test-program-type-1',
|
||||
programTypeUrl: 'test-program-type-1-url',
|
||||
provider: 'test-provider-1',
|
||||
title: 'test-program-title-1',
|
||||
},
|
||||
{
|
||||
estimatedNumberOfWeeks: 2,
|
||||
numberOfCourses: 3,
|
||||
programType: 'test-program-type-2',
|
||||
programTypeUrl: 'test-program-type-2-url',
|
||||
provider: 'test-provider-2',
|
||||
title: 'test-program-title-2',
|
||||
},
|
||||
{
|
||||
estimatedNumberOfWeeks: 3,
|
||||
numberOfCourses: 5,
|
||||
programType: 'test-program-type-3',
|
||||
programTypeUrl: 'test-program-type-3-url',
|
||||
provider: 'test-provider-3',
|
||||
title: 'test-program-title-3',
|
||||
},
|
||||
];
|
||||
|
||||
describe('RelatedProgramsModal hooks', () => {
|
||||
let out;
|
||||
beforeEach(() => {
|
||||
appHooks.getCardValues.mockReturnValueOnce({ courseTitle, relatedPrograms });
|
||||
out = hooks.modalData({ courseNumber });
|
||||
});
|
||||
testCardValues(courseNumber, {
|
||||
courseTitle: fieldKeys.courseTitle,
|
||||
relatedPrograms: fieldKeys.relatedPrograms,
|
||||
});
|
||||
test('courseTitle loads course title', () => {
|
||||
expect(out.courseTitle).toEqual(courseTitle);
|
||||
});
|
||||
test('relatedPrograms loads from course run related programs', () => {
|
||||
expect(out.relatedPrograms).toEqual(relatedPrograms);
|
||||
});
|
||||
});
|
||||
@@ -7,7 +7,7 @@ import { CardGrid, ModalDialog } from '@edx/paragon';
|
||||
|
||||
import ProgramCard from './components/ProgramCard';
|
||||
import messages from './messages';
|
||||
import programsData from './hooks';
|
||||
import { modalData } from './hooks';
|
||||
import './index.scss';
|
||||
|
||||
export const RelatedProgramsModal = ({
|
||||
@@ -16,7 +16,7 @@ export const RelatedProgramsModal = ({
|
||||
courseNumber,
|
||||
}) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const { courseTitle, relatedPrograms } = programsData({ courseNumber });
|
||||
const { courseTitle, relatedPrograms } = modalData({ courseNumber });
|
||||
return (
|
||||
<ModalDialog
|
||||
title={formatMessage(messages.header)}
|
||||
|
||||
49
src/containers/RelatedProgramsModal/index.test.jsx
Normal file
49
src/containers/RelatedProgramsModal/index.test.jsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { modalData } from './hooks';
|
||||
import RelatedProgramsModal from '.';
|
||||
|
||||
jest.mock('./components/ProgramCard', () => 'ProgramCard');
|
||||
jest.mock('./hooks', () => ({
|
||||
modalData: jest.fn(),
|
||||
}));
|
||||
|
||||
const courseNumber = 'test-course-number';
|
||||
const hookProps = {
|
||||
courseTitle: 'hookProps.courseTitle',
|
||||
relatedPrograms: [
|
||||
{
|
||||
programUrl: 'program-1-url',
|
||||
programData: { dataFor: 'program1' },
|
||||
},
|
||||
{
|
||||
programUrl: 'program-2-url',
|
||||
programData: { dataFor: 'program2' },
|
||||
},
|
||||
{
|
||||
programUrl: 'program-3-url',
|
||||
programData: { dataFor: 'program3' },
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const props = {
|
||||
isOpen: true,
|
||||
closeModal: jest.fn().mockName('props.closeModal'),
|
||||
courseNumber,
|
||||
};
|
||||
|
||||
describe('RelatedProgramsModal', () => {
|
||||
beforeEach(() => {
|
||||
modalData.mockReturnValueOnce(hookProps);
|
||||
});
|
||||
test('snapshot: open', () => {
|
||||
expect(shallow(<RelatedProgramsModal {...props} />)).toMatchSnapshot();
|
||||
});
|
||||
test('snapshot: closed', () => {
|
||||
expect(
|
||||
shallow(<RelatedProgramsModal {...props} isOpen={false} />),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -53,6 +53,7 @@ jest.mock('@edx/paragon', () => jest.requireActual('testUtils').mockNestedCompon
|
||||
ImageCap: 'Card.ImageCap',
|
||||
Section: 'Card.Section',
|
||||
},
|
||||
CardGrid: 'CardGrid',
|
||||
Col: 'Col',
|
||||
Collapsible: {
|
||||
Advanced: 'Collapsible.Advanced',
|
||||
@@ -88,7 +89,10 @@ jest.mock('@edx/paragon', () => jest.requireActual('testUtils').mockNestedCompon
|
||||
Hyperlink: 'Hyperlink',
|
||||
Icon: 'Icon',
|
||||
IconButton: 'IconButton',
|
||||
ModalDialog: 'ModalDialog',
|
||||
ModalDialog: {
|
||||
Header: 'ModalDialog.Header',
|
||||
Body: 'ModalDialog.Body',
|
||||
},
|
||||
MultiSelectDropdownFilter: 'MultiSelectDropdownFilter',
|
||||
OverlayTrigger: 'OverlayTrigger',
|
||||
Popover: {
|
||||
|
||||
Reference in New Issue
Block a user