fix: stop user from unenroll after earned the certificate (#162)
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`CourseCardMenu enrolled, share enabled, email setting enable snapshot 1`] = `
|
||||
exports[`CourseCardMenu default snapshot 1`] = `
|
||||
<Fragment>
|
||||
<Dropdown>
|
||||
<Dropdown
|
||||
onToggle={[MockFunction mockHandleToggleDropdown]}
|
||||
>
|
||||
<Dropdown.Toggle
|
||||
alt="Course actions dropdown"
|
||||
as="IconButton"
|
||||
@@ -28,7 +30,7 @@ exports[`CourseCardMenu enrolled, share enabled, email setting enable snapshot 1
|
||||
</Dropdown.Item>
|
||||
<FacebookShareButton
|
||||
className="pgn__dropdown-item dropdown-item"
|
||||
onClick={[MockFunction facebookShareClick]}
|
||||
onClick={[MockFunction handleFacebookShare]}
|
||||
resetButtonStyle={false}
|
||||
title="I'm taking test-course-name online with facebook-social-brand. Check it out!"
|
||||
url="facebook-share-url"
|
||||
@@ -37,7 +39,7 @@ exports[`CourseCardMenu enrolled, share enabled, email setting enable snapshot 1
|
||||
</FacebookShareButton>
|
||||
<TwitterShareButton
|
||||
className="pgn__dropdown-item dropdown-item"
|
||||
onClick={[MockFunction twitterShareClick]}
|
||||
onClick={[MockFunction handleTwitterShare]}
|
||||
resetButtonStyle={false}
|
||||
title="I'm taking test-course-name online with twitter-social-brand. Check it out!"
|
||||
url="twitter-share-url"
|
||||
@@ -61,7 +63,9 @@ exports[`CourseCardMenu enrolled, share enabled, email setting enable snapshot 1
|
||||
|
||||
exports[`CourseCardMenu masquerading snapshot 1`] = `
|
||||
<Fragment>
|
||||
<Dropdown>
|
||||
<Dropdown
|
||||
onToggle={[MockFunction mockHandleToggleDropdown]}
|
||||
>
|
||||
<Dropdown.Toggle
|
||||
alt="Course actions dropdown"
|
||||
as="IconButton"
|
||||
@@ -87,7 +91,7 @@ exports[`CourseCardMenu masquerading snapshot 1`] = `
|
||||
</Dropdown.Item>
|
||||
<FacebookShareButton
|
||||
className="pgn__dropdown-item dropdown-item"
|
||||
onClick={[MockFunction facebookShareClick]}
|
||||
onClick={[MockFunction handleFacebookShare]}
|
||||
resetButtonStyle={false}
|
||||
title="I'm taking test-course-name online with facebook-social-brand. Check it out!"
|
||||
url="facebook-share-url"
|
||||
@@ -96,7 +100,7 @@ exports[`CourseCardMenu masquerading snapshot 1`] = `
|
||||
</FacebookShareButton>
|
||||
<TwitterShareButton
|
||||
className="pgn__dropdown-item dropdown-item"
|
||||
onClick={[MockFunction twitterShareClick]}
|
||||
onClick={[MockFunction handleTwitterShare]}
|
||||
resetButtonStyle={false}
|
||||
title="I'm taking test-course-name online with twitter-social-brand. Check it out!"
|
||||
url="twitter-share-url"
|
||||
@@ -118,23 +122,4 @@ exports[`CourseCardMenu masquerading snapshot 1`] = `
|
||||
</Fragment>
|
||||
`;
|
||||
|
||||
exports[`CourseCardMenu not enrolled, share disabled, email setting disabled snapshot 1`] = `
|
||||
<Fragment>
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle
|
||||
alt="Course actions dropdown"
|
||||
as="IconButton"
|
||||
iconAs="Icon"
|
||||
id="course-actions-dropdown-test-card-id"
|
||||
src={[MockFunction icons.MoreVert]}
|
||||
variant="primary"
|
||||
/>
|
||||
<Dropdown.Menu />
|
||||
</Dropdown>
|
||||
<UnenrollConfirmModal
|
||||
cardId="test-card-id"
|
||||
closeModal={[MockFunction unenrollHide]}
|
||||
show={false}
|
||||
/>
|
||||
</Fragment>
|
||||
`;
|
||||
exports[`CourseCardMenu renders null if showDropdown is false 1`] = `""`;
|
||||
|
||||
@@ -36,3 +36,36 @@ export const useHandleToggleDropdown = (cardId) => {
|
||||
if (isOpen) { trackCourseEvent(); }
|
||||
};
|
||||
};
|
||||
|
||||
export const useCourseCardMenu = (cardId) => {
|
||||
const { courseName } = reduxHooks.useCardCourseData(cardId);
|
||||
const { isEnrolled, isEmailEnabled } = reduxHooks.useCardEnrollmentData(cardId);
|
||||
const { twitter, facebook } = reduxHooks.useCardSocialSettingsData(cardId);
|
||||
const { isMasquerading } = reduxHooks.useMasqueradeData();
|
||||
const { isEarned } = reduxHooks.useCardCertificateData(cardId);
|
||||
const handleTwitterShare = reduxHooks.useTrackCourseEvent(
|
||||
track.socialShare,
|
||||
cardId,
|
||||
'twitter',
|
||||
);
|
||||
const handleFacebookShare = reduxHooks.useTrackCourseEvent(
|
||||
track.socialShare,
|
||||
cardId,
|
||||
'facebook',
|
||||
);
|
||||
|
||||
const showUnenrollItem = isEnrolled && !isEarned;
|
||||
const showDropdown = showUnenrollItem || isEmailEnabled || facebook.isEnabled || twitter.isEnabled;
|
||||
|
||||
return {
|
||||
courseName,
|
||||
isMasquerading,
|
||||
isEmailEnabled,
|
||||
showUnenrollItem,
|
||||
showDropdown,
|
||||
facebook,
|
||||
twitter,
|
||||
handleTwitterShare,
|
||||
handleFacebookShare,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -7,6 +7,11 @@ import * as hooks from './hooks';
|
||||
jest.mock('hooks', () => ({
|
||||
reduxHooks: {
|
||||
useTrackCourseEvent: jest.fn(),
|
||||
useCardCourseData: jest.fn(),
|
||||
useCardEnrollmentData: jest.fn(),
|
||||
useCardSocialSettingsData: jest.fn(),
|
||||
useMasqueradeData: jest.fn(),
|
||||
useCardCertificateData: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -14,6 +19,18 @@ const trackCourseEvent = jest.fn();
|
||||
reduxHooks.useTrackCourseEvent.mockReturnValue(trackCourseEvent);
|
||||
const state = new MockUseState(hooks);
|
||||
|
||||
const defaultSocialShare = {
|
||||
facebook: {
|
||||
isEnabled: true,
|
||||
shareUrl: 'facebook-share-url',
|
||||
socialBrand: 'facebook-social-brand',
|
||||
},
|
||||
twitter: {
|
||||
isEnabled: true,
|
||||
shareUrl: 'twitter-share-url',
|
||||
socialBrand: 'twitter-social-brand',
|
||||
},
|
||||
};
|
||||
const cardId = 'test-card-id';
|
||||
let out;
|
||||
|
||||
@@ -88,4 +105,116 @@ describe('CourseCardMenu hooks', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('useCourseCardMenu', () => {
|
||||
const mockUseCourseCardMenu = ({
|
||||
courseName,
|
||||
isEnrolled,
|
||||
isEmailEnabled,
|
||||
isMasquerading,
|
||||
facebook,
|
||||
twitter,
|
||||
isEarned,
|
||||
} = {}) => {
|
||||
reduxHooks.useCardCourseData.mockReturnValueOnce({ courseName });
|
||||
reduxHooks.useCardSocialSettingsData.mockReturnValueOnce({
|
||||
facebook: {
|
||||
...defaultSocialShare.facebook,
|
||||
...facebook,
|
||||
},
|
||||
twitter: {
|
||||
...defaultSocialShare.twitter,
|
||||
...twitter,
|
||||
},
|
||||
});
|
||||
reduxHooks.useCardEnrollmentData.mockReturnValueOnce({
|
||||
isEnrolled,
|
||||
isEmailEnabled,
|
||||
});
|
||||
reduxHooks.useMasqueradeData.mockReturnValueOnce({ isMasquerading });
|
||||
reduxHooks.useCardCertificateData.mockReturnValueOnce({ isEarned });
|
||||
};
|
||||
afterEach(() => jest.resetAllMocks());
|
||||
describe('showUnenrollItem', () => {
|
||||
test('return true', () => {
|
||||
mockUseCourseCardMenu({ isEnrolled: true, isEarned: false });
|
||||
out = hooks.useCourseCardMenu(cardId);
|
||||
expect(out.showUnenrollItem).toBeTruthy();
|
||||
});
|
||||
|
||||
test('return false', () => {
|
||||
mockUseCourseCardMenu({ isEnrolled: true, isEarned: true });
|
||||
out = hooks.useCourseCardMenu(cardId);
|
||||
expect(out.showUnenrollItem).toBeFalsy();
|
||||
|
||||
mockUseCourseCardMenu({ isEnrolled: false, isEarned: false });
|
||||
out = hooks.useCourseCardMenu(cardId);
|
||||
expect(out.showUnenrollItem).toBeFalsy();
|
||||
|
||||
mockUseCourseCardMenu({ isEnrolled: false, isEarned: true });
|
||||
out = hooks.useCourseCardMenu(cardId);
|
||||
expect(out.showUnenrollItem).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('showDropdown', () => {
|
||||
test('return false iif everything is false', () => {
|
||||
mockUseCourseCardMenu({
|
||||
isEnrolled: false,
|
||||
isEarned: false,
|
||||
isEmailEnabled: false,
|
||||
facebook: { isEnabled: false },
|
||||
twitter: { isEnabled: false },
|
||||
});
|
||||
out = hooks.useCourseCardMenu(cardId);
|
||||
expect(out.showDropdown).toBeFalsy();
|
||||
});
|
||||
|
||||
test('return true iif at least one is true', () => {
|
||||
mockUseCourseCardMenu({
|
||||
isEnrolled: true,
|
||||
isEarned: false,
|
||||
isEmailEnabled: false,
|
||||
facebook: { isEnabled: false },
|
||||
twitter: { isEnabled: false },
|
||||
});
|
||||
out = hooks.useCourseCardMenu(cardId);
|
||||
expect(out.showDropdown).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
test('return correct values', () => {
|
||||
const expected = {
|
||||
courseName: 'abitrary-course-name',
|
||||
isMasquerading: 'abitrary-masquerading-value',
|
||||
isEmailEnabled: 'abitrary-email-enabled-value',
|
||||
facebook: { isEnabled: 'abitrary-facebook-value' },
|
||||
twitter: { isEnabled: 'abitrary-twitter-value' },
|
||||
};
|
||||
mockUseCourseCardMenu(expected);
|
||||
out = hooks.useCourseCardMenu(cardId);
|
||||
expect(out.courseName).toEqual(expected.courseName);
|
||||
expect(out.isMasquerading).toEqual(expected.isMasquerading);
|
||||
expect(out.isEmailEnabled).toEqual(expected.isEmailEnabled);
|
||||
expect(out.facebook.isEnabled).toEqual(expected.facebook.isEnabled);
|
||||
expect(out.twitter.isEnabled).toEqual(expected.twitter.isEnabled);
|
||||
});
|
||||
|
||||
test('handleSocialShareClick', () => {
|
||||
mockUseCourseCardMenu();
|
||||
|
||||
out = hooks.useCourseCardMenu(cardId);
|
||||
expect(reduxHooks.useTrackCourseEvent).toHaveBeenCalledTimes(2);
|
||||
expect(reduxHooks.useTrackCourseEvent).toHaveBeenCalledWith(
|
||||
track.socialShare,
|
||||
cardId,
|
||||
'facebook',
|
||||
);
|
||||
expect(reduxHooks.useTrackCourseEvent).toHaveBeenCalledWith(
|
||||
track.socialShare,
|
||||
cardId,
|
||||
'twitter',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,14 +6,13 @@ import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Dropdown, Icon, IconButton } from '@edx/paragon';
|
||||
import { MoreVert } from '@edx/paragon/icons';
|
||||
|
||||
import track from 'tracking';
|
||||
import { reduxHooks } from 'hooks';
|
||||
import EmailSettingsModal from 'containers/EmailSettingsModal';
|
||||
import UnenrollConfirmModal from 'containers/UnenrollConfirmModal';
|
||||
import {
|
||||
useEmailSettings,
|
||||
useUnenrollData,
|
||||
useHandleToggleDropdown,
|
||||
useCourseCardMenu,
|
||||
} from './hooks';
|
||||
|
||||
import messages from './messages';
|
||||
@@ -21,25 +20,26 @@ import messages from './messages';
|
||||
export const CourseCardMenu = ({ cardId }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const { courseName } = reduxHooks.useCardCourseData(cardId);
|
||||
const { isEnrolled, isEmailEnabled } = reduxHooks.useCardEnrollmentData(cardId);
|
||||
const { twitter, facebook } = reduxHooks.useCardSocialSettingsData(cardId);
|
||||
const { isMasquerading } = reduxHooks.useMasqueradeData();
|
||||
const handleTwitterShare = reduxHooks.useTrackCourseEvent(
|
||||
track.socialShare,
|
||||
cardId,
|
||||
'twitter',
|
||||
);
|
||||
const handleFacebookShare = reduxHooks.useTrackCourseEvent(
|
||||
track.socialShare,
|
||||
cardId,
|
||||
'facebook',
|
||||
);
|
||||
|
||||
const emailSettingsModal = useEmailSettings();
|
||||
const unenrollModal = useUnenrollData();
|
||||
const handleToggleDropdown = useHandleToggleDropdown(cardId);
|
||||
|
||||
const {
|
||||
courseName,
|
||||
isMasquerading,
|
||||
isEmailEnabled,
|
||||
showUnenrollItem,
|
||||
showDropdown,
|
||||
facebook,
|
||||
twitter,
|
||||
handleTwitterShare,
|
||||
handleFacebookShare,
|
||||
} = useCourseCardMenu(cardId);
|
||||
|
||||
if (!showDropdown) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Dropdown onToggle={handleToggleDropdown}>
|
||||
@@ -52,7 +52,7 @@ export const CourseCardMenu = ({ cardId }) => {
|
||||
alt={formatMessage(messages.dropdownAlt)}
|
||||
/>
|
||||
<Dropdown.Menu>
|
||||
{isEnrolled && (
|
||||
{showUnenrollItem && (
|
||||
<Dropdown.Item
|
||||
disabled={isMasquerading}
|
||||
onClick={unenrollModal.show}
|
||||
|
||||
@@ -1,26 +1,19 @@
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { reduxHooks } from 'hooks';
|
||||
import { useEmailSettings, useUnenrollData } from './hooks';
|
||||
import {
|
||||
useEmailSettings, useUnenrollData, useCourseCardMenu,
|
||||
} from './hooks';
|
||||
import CourseCardMenu from '.';
|
||||
|
||||
jest.mock('react-share', () => ({
|
||||
FacebookShareButton: () => 'FacebookShareButton',
|
||||
TwitterShareButton: () => 'TwitterShareButton',
|
||||
}));
|
||||
jest.mock('hooks', () => ({
|
||||
reduxHooks: {
|
||||
useCardCourseData: jest.fn(),
|
||||
useCardEnrollmentData: jest.fn(),
|
||||
useCardSocialSettingsData: jest.fn(),
|
||||
useMasqueradeData: jest.fn(),
|
||||
useTrackCourseEvent: (_, __, site) => jest.fn().mockName(`${site}ShareClick`),
|
||||
},
|
||||
}));
|
||||
jest.mock('./hooks', () => ({
|
||||
useEmailSettings: jest.fn(),
|
||||
useUnenrollData: jest.fn(),
|
||||
useHandleToggleDropdown: jest.fn(),
|
||||
useCourseCardMenu: jest.fn(),
|
||||
useHandleToggleDropdown: () => jest.fn().mockName('mockHandleToggleDropdown'),
|
||||
}));
|
||||
|
||||
const props = {
|
||||
@@ -48,77 +41,105 @@ const defaultSocialShare = {
|
||||
socialBrand: 'twitter-social-brand',
|
||||
},
|
||||
};
|
||||
const courseName = 'test-course-name';
|
||||
const defaultUseCourseCardMenu = {
|
||||
courseName: 'test-course-name',
|
||||
isMasquerading: false,
|
||||
isEmailEnabled: true,
|
||||
showUnenrollItem: true,
|
||||
showDropdown: true,
|
||||
handleTwitterShare: jest.fn().mockName('handleTwitterShare'),
|
||||
handleFacebookShare: jest.fn().mockName('handleFacebookShare'),
|
||||
};
|
||||
let wrapper;
|
||||
let el;
|
||||
|
||||
describe('CourseCardMenu', () => {
|
||||
beforeEach(() => {
|
||||
useEmailSettings.mockReturnValue(defaultEmailSettingsModal);
|
||||
useUnenrollData.mockReturnValue(defaultUnenrollModal);
|
||||
reduxHooks.useCardSocialSettingsData.mockReturnValue(defaultSocialShare);
|
||||
reduxHooks.useCardCourseData.mockReturnValue({ courseName });
|
||||
reduxHooks.useCardEnrollmentData.mockReturnValue({ isEnrolled: true, isEmailEnabled: true });
|
||||
reduxHooks.useMasqueradeData.mockReturnValue({ isMasquerading: false });
|
||||
useEmailSettings.mockReturnValue(defaultEmailSettingsModal);
|
||||
useUnenrollData.mockReturnValue(defaultUnenrollModal);
|
||||
|
||||
const mockUseCourseCardMenu = ({
|
||||
isMasquerading,
|
||||
isEmailEnabled,
|
||||
showUnenrollItem,
|
||||
showDropdown,
|
||||
facebook,
|
||||
twitter,
|
||||
}) => {
|
||||
useCourseCardMenu.mockReturnValueOnce({
|
||||
...defaultUseCourseCardMenu,
|
||||
isMasquerading,
|
||||
isEmailEnabled,
|
||||
showUnenrollItem,
|
||||
showDropdown,
|
||||
facebook,
|
||||
twitter,
|
||||
});
|
||||
return shallow(<CourseCardMenu {...props} />);
|
||||
};
|
||||
test('default snapshot', () => {
|
||||
wrapper = mockUseCourseCardMenu({
|
||||
isMasquerading: false,
|
||||
isEmailEnabled: true,
|
||||
showUnenrollItem: true,
|
||||
showDropdown: true,
|
||||
...defaultSocialShare,
|
||||
});
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
describe('enrolled, share enabled, email setting enable', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(<CourseCardMenu {...props} />);
|
||||
});
|
||||
test('snapshot', () => {
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
it('renders share buttons', () => {
|
||||
el = wrapper.find('FacebookShareButton');
|
||||
expect(el.length).toEqual(1);
|
||||
expect(el.prop('url')).toEqual('facebook-share-url');
|
||||
el = wrapper.find('TwitterShareButton');
|
||||
expect(el.length).toEqual(1);
|
||||
expect(el.prop('url')).toEqual('twitter-share-url');
|
||||
});
|
||||
it('renders enabled unenroll modal toggle', () => {
|
||||
el = wrapper.find({ 'data-testid': 'unenrollModalToggle' });
|
||||
expect(el.props().disabled).toEqual(false);
|
||||
});
|
||||
it('renders enabled email settings modal toggle', () => {
|
||||
el = wrapper.find({ 'data-testid': 'emailSettingsModalToggle' });
|
||||
expect(el.props().disabled).toEqual(false);
|
||||
});
|
||||
it('renders enabled email settings modal toggle', () => {
|
||||
el = wrapper.find({ 'data-testid': 'emailSettingsModalToggle' });
|
||||
expect(el.props().disabled).toEqual(false);
|
||||
test('renders null if showDropdown is false', () => {
|
||||
wrapper = mockUseCourseCardMenu({
|
||||
isMasquerading: true,
|
||||
isEmailEnabled: true,
|
||||
showUnenrollItem: true,
|
||||
showDropdown: false,
|
||||
...defaultSocialShare,
|
||||
});
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
expect(wrapper.isEmptyRender()).toEqual(true);
|
||||
});
|
||||
describe('not enrolled, share disabled, email setting disabled', () => {
|
||||
beforeEach(() => {
|
||||
reduxHooks.useCardSocialSettingsData.mockReturnValueOnce({
|
||||
...defaultSocialShare,
|
||||
twitter: { ...defaultSocialShare.twitter, isEnabled: false },
|
||||
facebook: { ...defaultSocialShare.facebook, isEnabled: false },
|
||||
|
||||
describe('disable state options', () => {
|
||||
beforeAll(() => {
|
||||
wrapper = mockUseCourseCardMenu({
|
||||
isMasquerading: false,
|
||||
isEmailEnabled: false,
|
||||
showUnenrollItem: false,
|
||||
showDropdown: true, // set to true for testing
|
||||
facebook: {
|
||||
isEnabled: false,
|
||||
},
|
||||
twitter: {
|
||||
isEnabled: false,
|
||||
},
|
||||
});
|
||||
reduxHooks.useCardEnrollmentData.mockReturnValueOnce({ isEnrolled: false, isEmailEnabled: false });
|
||||
wrapper = shallow(<CourseCardMenu {...props} />);
|
||||
});
|
||||
test('snapshot', () => {
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
// to make sure it try to render the dropdown
|
||||
it('render dropdown base on showDropdown', () => {
|
||||
expect(wrapper.isEmptyRender()).toEqual(false);
|
||||
expect(wrapper.find('Dropdown').length).toEqual(1);
|
||||
});
|
||||
it('does not renders share buttons', () => {
|
||||
it('not renders email settings modal toggle', () => {
|
||||
el = wrapper.find({ 'data-testid': 'emailSettingsModalToggle' });
|
||||
expect(el.length).toEqual(0);
|
||||
});
|
||||
it('not renders unenroll modal toggle', () => {
|
||||
el = wrapper.find({ 'data-testid': 'unenrollModalToggle' });
|
||||
expect(el.length).toEqual(0);
|
||||
});
|
||||
it('not renders share buttons', () => {
|
||||
expect(wrapper.find('FacebookShareButton').length).toEqual(0);
|
||||
expect(wrapper.find('TwitterShareButton').length).toEqual(0);
|
||||
});
|
||||
it('does not render unenroll modal toggle', () => {
|
||||
el = wrapper.find({ 'data-testid': 'unenrollModalToggle' });
|
||||
expect(el.length).toEqual(0);
|
||||
});
|
||||
it('does not render email settings modal toggle', () => {
|
||||
el = wrapper.find({ 'data-testid': 'emailSettingsModalToggle' });
|
||||
expect(el.length).toEqual(0);
|
||||
});
|
||||
});
|
||||
describe('masquerading', () => {
|
||||
beforeEach(() => {
|
||||
reduxHooks.useMasqueradeData.mockReturnValue({ isMasquerading: true });
|
||||
wrapper = shallow(<CourseCardMenu {...props} />);
|
||||
wrapper = mockUseCourseCardMenu({
|
||||
isMasquerading: true,
|
||||
isEmailEnabled: true,
|
||||
showUnenrollItem: true,
|
||||
showDropdown: true,
|
||||
...defaultSocialShare,
|
||||
});
|
||||
});
|
||||
test('snapshot', () => {
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
||||
@@ -15,17 +15,14 @@ export const loadDateVal = (date) => (date ? new Date(date) : null);
|
||||
export const courseCard = StrictDict({
|
||||
certificate: mkCardSelector(
|
||||
cardSimpleSelectors.certificate,
|
||||
(certificate) => {
|
||||
const availableDate = new Date(certificate.availableDate);
|
||||
const isAvailable = availableDate <= new Date();
|
||||
return {
|
||||
availableDate,
|
||||
certPreviewUrl: baseAppUrl(certificate.certPreviewUrl),
|
||||
isDownloadable: certificate.isDownloadable,
|
||||
isEarnedButUnavailable: certificate.isEarned && !isAvailable,
|
||||
isRestricted: certificate.isRestricted,
|
||||
};
|
||||
},
|
||||
(certificate) => (certificate === null ? {} : ({
|
||||
availableDate: new Date(certificate.availableDate),
|
||||
certPreviewUrl: baseAppUrl(certificate.certPreviewUrl),
|
||||
isDownloadable: certificate.isDownloadable,
|
||||
isEarnedButUnavailable: certificate.isEarned && new Date(certificate.availableDate) > new Date(),
|
||||
isRestricted: certificate.isRestricted,
|
||||
isEarned: certificate.isEarned,
|
||||
})),
|
||||
),
|
||||
course: mkCardSelector(
|
||||
cardSimpleSelectors.course,
|
||||
|
||||
@@ -79,6 +79,9 @@ describe('courseCard selectors module', () => {
|
||||
it('returns a card selector based on certificate cardSimpleSelector', () => {
|
||||
expect(simpleSelector).toEqual(cardSimpleSelectors.certificate);
|
||||
});
|
||||
it('returns {} object if null certificate received', () => {
|
||||
expect(selector(null)).toEqual({});
|
||||
});
|
||||
it('passes availableDate, converted to a date', () => {
|
||||
expect(selected.availableDate).toMatchObject(new Date(testData.availableDate));
|
||||
});
|
||||
@@ -162,6 +165,9 @@ describe('courseCard selectors module', () => {
|
||||
it('returns a card selector based on courseRun cardSimpleSelector', () => {
|
||||
expect(simpleSelector).toEqual(cardSimpleSelectors.courseRun);
|
||||
});
|
||||
it('returns {} object if null courseRun received', () => {
|
||||
expect(selector(null)).toEqual({});
|
||||
});
|
||||
it('passes [endDate, startDate], converted to dates', () => {
|
||||
expect(selected.endDate).toEqual(new Date(testData.endDate));
|
||||
expect(selected.startDate).toEqual(new Date(testData.startDate));
|
||||
|
||||
Reference in New Issue
Block a user