feat: program card tests

This commit is contained in:
Ben Warzeski
2022-06-13 22:17:06 -04:00
parent 61cff124a8
commit fac5d6aba7
12 changed files with 425 additions and 27 deletions

View File

@@ -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>

View File

@@ -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', () => {

View File

@@ -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>
`;

View File

@@ -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)}

View File

@@ -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();
});
});

View File

@@ -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>
`;

View 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;

View File

@@ -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;

View 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);
});
});

View File

@@ -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)}

View 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();
});
});

View File

@@ -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: {