feat: add social actions + descriptive names to mock data (#41)
This commit is contained in:
70
package-lock.json
generated
70
package-lock.json
generated
@@ -47,6 +47,7 @@
|
||||
"react-router": "5.2.0",
|
||||
"react-router-dom": "5.2.0",
|
||||
"react-router-redux": "^5.0.0-alpha.9",
|
||||
"react-share": "^4.4.0",
|
||||
"redux": "4.1.1",
|
||||
"redux-beacon": "^2.1.0",
|
||||
"redux-devtools-extension": "2.13.9",
|
||||
@@ -17637,6 +17638,27 @@
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonp": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonp/-/jsonp-0.2.1.tgz",
|
||||
"integrity": "sha512-pfog5gdDxPdV4eP7Kg87M8/bHgshlZ5pybl+yKxAnCZ5O7lCIn7Ixydj03wOlnDQesky2BPyA91SQ+5Y/mNwzw==",
|
||||
"dependencies": {
|
||||
"debug": "^2.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonp/node_modules/debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"dependencies": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonp/node_modules/ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
},
|
||||
"node_modules/jsonparse": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
|
||||
@@ -24885,6 +24907,22 @@
|
||||
"isarray": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/react-share": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/react-share/-/react-share-4.4.0.tgz",
|
||||
"integrity": "sha512-POe8Ge/JT9Ew9iyW7CiYsCCWCb8uMJWqFl9S7W0fJ/oH5gBJNzukH0bL5vSr17KKG5h15d3GfKaoviI22BKeYA==",
|
||||
"dependencies": {
|
||||
"classnames": "^2.2.5",
|
||||
"jsonp": "^0.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0",
|
||||
"npm": ">=5.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.3.0 || ^17"
|
||||
}
|
||||
},
|
||||
"node_modules/react-side-effect": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.2.tgz",
|
||||
@@ -43636,6 +43674,29 @@
|
||||
"universalify": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"jsonp": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonp/-/jsonp-0.2.1.tgz",
|
||||
"integrity": "sha512-pfog5gdDxPdV4eP7Kg87M8/bHgshlZ5pybl+yKxAnCZ5O7lCIn7Ixydj03wOlnDQesky2BPyA91SQ+5Y/mNwzw==",
|
||||
"requires": {
|
||||
"debug": "^2.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"jsonparse": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
|
||||
@@ -48922,6 +48983,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-share": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/react-share/-/react-share-4.4.0.tgz",
|
||||
"integrity": "sha512-POe8Ge/JT9Ew9iyW7CiYsCCWCb8uMJWqFl9S7W0fJ/oH5gBJNzukH0bL5vSr17KKG5h15d3GfKaoviI22BKeYA==",
|
||||
"requires": {
|
||||
"classnames": "^2.2.5",
|
||||
"jsonp": "^0.2.1"
|
||||
}
|
||||
},
|
||||
"react-side-effect": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.2.tgz",
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
"react-router": "5.2.0",
|
||||
"react-router-dom": "5.2.0",
|
||||
"react-router-redux": "^5.0.0-alpha.9",
|
||||
"react-share": "^4.4.0",
|
||||
"redux": "4.1.1",
|
||||
"redux-beacon": "^2.1.0",
|
||||
"redux-devtools-extension": "2.13.9",
|
||||
|
||||
@@ -7,7 +7,8 @@ import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { AppContext } from '@edx/frontend-platform/react';
|
||||
import Footer from '@edx/frontend-component-footer';
|
||||
|
||||
import { thunkActions } from 'data/redux';
|
||||
import store from 'data/store';
|
||||
import { selectors, actions, thunkActions } from 'data/redux';
|
||||
import fakeData from 'data/services/lms/fakeData/courses';
|
||||
import LearnerDashboardHeader from 'containers/LearnerDashboardHeader';
|
||||
import Dashboard from 'containers/Dashboard';
|
||||
@@ -34,6 +35,10 @@ export const App = () => {
|
||||
],
|
||||
}));
|
||||
};
|
||||
window.store = store;
|
||||
window.selectors = selectors;
|
||||
window.actions = actions;
|
||||
window.thunkActions = thunkActions;
|
||||
}
|
||||
});
|
||||
return (
|
||||
|
||||
@@ -16,9 +16,9 @@ export const CertificateBanner = ({ cardId }) => {
|
||||
const {
|
||||
isAudit,
|
||||
isVerified,
|
||||
hasFinished,
|
||||
} = appHooks.useCardEnrollmentData(cardId);
|
||||
const { isPassing } = appHooks.useCardGradeData(cardId);
|
||||
const { isArchived } = appHooks.useCardCourseRunData(cardId);
|
||||
const { minPassingGrade, progressUrl } = appHooks.useCardCourseRunData(cardId);
|
||||
const { supportEmail, billingEmail } = appHooks.usePlatformSettingsData();
|
||||
const { formatMessage, formatDate } = useIntl();
|
||||
@@ -45,7 +45,7 @@ export const CertificateBanner = ({ cardId }) => {
|
||||
</Banner>
|
||||
);
|
||||
}
|
||||
if (hasFinished) {
|
||||
if (isArchived) {
|
||||
return (
|
||||
<Banner variant="warning">
|
||||
{formatMessage(messages.notEligibleForCert)}.
|
||||
|
||||
@@ -7,9 +7,9 @@ import messages from './messages';
|
||||
jest.mock('data/redux', () => ({
|
||||
hooks: {
|
||||
useCardCertificateData: jest.fn(),
|
||||
useCardCourseRunData: jest.fn(),
|
||||
useCardEnrollmentData: jest.fn(),
|
||||
useCardGradeData: jest.fn(),
|
||||
useCardCourseRunData: jest.fn(),
|
||||
usePlatformSettingsData: jest.fn(),
|
||||
},
|
||||
}));
|
||||
@@ -17,9 +17,7 @@ jest.mock('data/redux', () => ({
|
||||
jest.mock('Components/Banner', () => 'Banner');
|
||||
|
||||
describe('CertificateBanner', () => {
|
||||
const props = {
|
||||
cardId: 'cardId',
|
||||
};
|
||||
const props = { cardId: 'cardId' };
|
||||
hooks.usePlatformSettingsData.mockReturnValue({
|
||||
supportEmail: 'suport@email',
|
||||
billingEmail: 'billing@email',
|
||||
@@ -37,19 +35,19 @@ describe('CertificateBanner', () => {
|
||||
const defaultEnrollment = {
|
||||
isAudit: false,
|
||||
isVerified: false,
|
||||
hasFinished: false,
|
||||
};
|
||||
const defaultGrade = {
|
||||
isPassing: false,
|
||||
};
|
||||
const defaultCourseRun = { isArchived: false };
|
||||
const defaultGrade = { isPassing: false };
|
||||
const createWrapper = ({
|
||||
certificate = {},
|
||||
enrollment = {},
|
||||
grade = {},
|
||||
courseRun = {},
|
||||
}) => {
|
||||
hooks.useCardGradeData.mockReturnValueOnce({ ...defaultGrade, ...grade });
|
||||
hooks.useCardCertificateData.mockReturnValueOnce({ ...defaultCertificate, ...certificate });
|
||||
hooks.useCardEnrollmentData.mockReturnValueOnce({ ...defaultEnrollment, ...enrollment });
|
||||
hooks.useCardCourseRunData.mockReturnValueOnce({ ...defaultCourseRun, ...courseRun });
|
||||
return shallow(<CertificateBanner {...props} />);
|
||||
};
|
||||
describe('snapshot', () => {
|
||||
@@ -82,9 +80,7 @@ describe('CertificateBanner', () => {
|
||||
});
|
||||
test('not passing and has finished', () => {
|
||||
const wrapper = createWrapper({
|
||||
enrollment: {
|
||||
hasFinished: true,
|
||||
},
|
||||
courseRun: { isArchived: true },
|
||||
});
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@@ -81,7 +81,7 @@ describe('CourseCardDetails hooks', () => {
|
||||
};
|
||||
const courseRunData = {
|
||||
isStarted: true,
|
||||
isFinished: false,
|
||||
isArchived: false,
|
||||
startDate: '10/10/1000',
|
||||
endDate: '10/20/2000',
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@ exports[`CourseCardMenu snapshot 1`] = `
|
||||
<Fragment>
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle
|
||||
alt="Actions dropdown"
|
||||
alt="Course actions dropdown"
|
||||
as="IconButton"
|
||||
iconAs="Icon"
|
||||
id="course-actions-dropdown-test-card-id"
|
||||
@@ -13,24 +13,116 @@ exports[`CourseCardMenu snapshot 1`] = `
|
||||
/>
|
||||
<Dropdown.Menu>
|
||||
<Dropdown.Item
|
||||
data-testid="unenrollModalToggle"
|
||||
disabled={false}
|
||||
onClick={[MockFunction unenrollShow]}
|
||||
>
|
||||
Unenroll
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
data-testid="emailSettingsModalToggle"
|
||||
disabled={false}
|
||||
onClick={[MockFunction emailSettingShow]}
|
||||
>
|
||||
Email Settings
|
||||
Email settings
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
href="#/action-3"
|
||||
>
|
||||
Share to Facebook
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
href="#/action-3"
|
||||
>
|
||||
Share to Twitter
|
||||
<Dropdown.Item>
|
||||
<TwitterShareButton
|
||||
title="I'm taking test-course-name online with facebook-social-brand. Check it out!"
|
||||
url="facebook-share-url"
|
||||
>
|
||||
Share to Twitter
|
||||
</TwitterShareButton>
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
<UnenrollConfirmModal
|
||||
cardId="test-card-id"
|
||||
closeModal={[MockFunction unenrollHide]}
|
||||
show={false}
|
||||
/>
|
||||
<EmailSettingsModal
|
||||
cardId="test-card-id"
|
||||
closeModal={[MockFunction emailSettingHide]}
|
||||
show={false}
|
||||
/>
|
||||
</Fragment>
|
||||
`;
|
||||
|
||||
exports[`CourseCardMenu snapshot: masquerading 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.Item
|
||||
data-testid="unenrollModalToggle"
|
||||
disabled={true}
|
||||
onClick={[MockFunction unenrollShow]}
|
||||
>
|
||||
Unenroll
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
data-testid="emailSettingsModalToggle"
|
||||
disabled={true}
|
||||
onClick={[MockFunction emailSettingShow]}
|
||||
>
|
||||
Email settings
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item>
|
||||
<TwitterShareButton
|
||||
title="I'm taking test-course-name online with facebook-social-brand. Check it out!"
|
||||
url="facebook-share-url"
|
||||
>
|
||||
Share to Twitter
|
||||
</TwitterShareButton>
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
<UnenrollConfirmModal
|
||||
cardId="test-card-id"
|
||||
closeModal={[MockFunction unenrollHide]}
|
||||
show={false}
|
||||
/>
|
||||
<EmailSettingsModal
|
||||
cardId="test-card-id"
|
||||
closeModal={[MockFunction emailSettingHide]}
|
||||
show={false}
|
||||
/>
|
||||
</Fragment>
|
||||
`;
|
||||
|
||||
exports[`CourseCardMenu twitter share disabled 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.Item
|
||||
data-testid="unenrollModalToggle"
|
||||
disabled={false}
|
||||
onClick={[MockFunction unenrollShow]}
|
||||
>
|
||||
Unenroll
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
data-testid="emailSettingsModalToggle"
|
||||
disabled={false}
|
||||
onClick={[MockFunction emailSettingShow]}
|
||||
>
|
||||
Email settings
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
|
||||
@@ -24,14 +24,3 @@ export const useEmailSettings = () => {
|
||||
isVisible,
|
||||
};
|
||||
};
|
||||
|
||||
export const useCardMenuData = () => {
|
||||
const unenrollModal = module.useUnenrollData();
|
||||
const emailSettingsModal = module.useEmailSettings();
|
||||
return {
|
||||
emailSettingsModal,
|
||||
unenrollModal,
|
||||
};
|
||||
};
|
||||
|
||||
export default useCardMenuData;
|
||||
|
||||
@@ -1,20 +1,29 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import * as ReactShare from 'react-share';
|
||||
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Dropdown, Icon, IconButton } from '@edx/paragon';
|
||||
import { MoreVert } from '@edx/paragon/icons';
|
||||
|
||||
import { hooks as appHooks } from 'data/redux';
|
||||
import EmailSettingsModal from 'containers/EmailSettingsModal';
|
||||
import UnenrollConfirmModal from 'containers/UnenrollConfirmModal';
|
||||
import useCourseCardMenuData from './hooks';
|
||||
import { useEmailSettings, useUnenrollData } from './hooks';
|
||||
|
||||
import messages from './messages';
|
||||
|
||||
export const CourseCardMenu = ({ cardId }) => {
|
||||
const emailSettingsModal = useEmailSettings();
|
||||
const unenrollModal = useUnenrollData();
|
||||
const { courseName } = appHooks.useCardCourseData(cardId);
|
||||
const {
|
||||
emailSettingsModal,
|
||||
unenrollModal,
|
||||
} = useCourseCardMenuData();
|
||||
// facebook,
|
||||
twitter,
|
||||
} = appHooks.useCardSocialSettingsData(cardId);
|
||||
const { isMasquerading } = appHooks.useMasqueradeData();
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Dropdown>
|
||||
@@ -24,17 +33,51 @@ export const CourseCardMenu = ({ cardId }) => {
|
||||
src={MoreVert}
|
||||
iconAs={Icon}
|
||||
variant="primary"
|
||||
alt="Actions dropdown"
|
||||
alt={formatMessage(messages.dropdownAlt)}
|
||||
/>
|
||||
<Dropdown.Menu>
|
||||
<Dropdown.Item disabled={isMasquerading} onClick={unenrollModal.show}>
|
||||
Unenroll
|
||||
<Dropdown.Item
|
||||
disabled={isMasquerading}
|
||||
onClick={unenrollModal.show}
|
||||
data-testid="unenrollModalToggle"
|
||||
>
|
||||
{formatMessage(messages.unenroll)}
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item disabled={isMasquerading} onClick={emailSettingsModal.show}>
|
||||
Email Settings
|
||||
<Dropdown.Item
|
||||
disabled={isMasquerading}
|
||||
onClick={emailSettingsModal.show}
|
||||
data-testid="emailSettingsModalToggle"
|
||||
>
|
||||
{formatMessage(messages.emailSettings)}
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item href="#/action-3">Share to Facebook</Dropdown.Item>
|
||||
<Dropdown.Item href="#/action-3">Share to Twitter</Dropdown.Item>
|
||||
{/* Disabled pending PM decision on missing quote param in updated FB api.
|
||||
{facebook.isEnabled && (
|
||||
<Dropdown.Item>
|
||||
<ReactShare.FacebookShareButton
|
||||
url={facebook.shareUrl}
|
||||
quote={formatMessage(messages.shareQuote, {
|
||||
courseName,
|
||||
socialBrand: facebook.socialBrand,
|
||||
})}
|
||||
>
|
||||
{formatMessage(messages.shareToFacebook)}
|
||||
</ReactShare.FacebookShareButton>
|
||||
</Dropdown.Item>
|
||||
)}
|
||||
*/}
|
||||
{twitter.isEnabled && (
|
||||
<Dropdown.Item>
|
||||
<ReactShare.TwitterShareButton
|
||||
url={twitter.shareUrl}
|
||||
title={formatMessage(messages.shareQuote, {
|
||||
courseName,
|
||||
socialBrand: twitter.socialBrand,
|
||||
})}
|
||||
>
|
||||
{formatMessage(messages.shareToTwitter)}
|
||||
</ReactShare.TwitterShareButton>
|
||||
</Dropdown.Item>
|
||||
)}
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
<UnenrollConfirmModal
|
||||
|
||||
@@ -1,31 +1,102 @@
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { hooks as appHooks } from 'data/redux';
|
||||
import { useEmailSettings, useUnenrollData } from './hooks';
|
||||
import CourseCardMenu from '.';
|
||||
import useCourseCardMenuData from './hooks';
|
||||
|
||||
jest.mock('./hooks', () => jest.fn());
|
||||
jest.mock('react-share', () => ({
|
||||
FacebookShareButton: () => 'FacebookShareButton',
|
||||
TwitterShareButton: () => 'TwitterShareButton',
|
||||
}));
|
||||
jest.mock('data/redux', () => ({
|
||||
hooks: {
|
||||
useCardCourseData: jest.fn(),
|
||||
useCardSocialSettingsData: jest.fn(),
|
||||
useMasqueradeData: jest.fn(),
|
||||
},
|
||||
}));
|
||||
jest.mock('./hooks', () => ({
|
||||
useEmailSettings: jest.fn(),
|
||||
useUnenrollData: jest.fn(),
|
||||
}));
|
||||
|
||||
const props = {
|
||||
cardId: 'test-card-id',
|
||||
};
|
||||
const defaultEmailSettingsModal = {
|
||||
isVisible: false,
|
||||
show: jest.fn().mockName('emailSettingShow'),
|
||||
hide: jest.fn().mockName('emailSettingHide'),
|
||||
};
|
||||
const defaultUnenrollModal = {
|
||||
isVisible: false,
|
||||
show: jest.fn().mockName('unenrollShow'),
|
||||
hide: jest.fn().mockName('unenrollHide'),
|
||||
};
|
||||
const defaultSocialShare = {
|
||||
facebook: {
|
||||
isEnabled: true,
|
||||
shareUrl: 'facebook-share-url',
|
||||
socialBrand: 'facebook-social-brand',
|
||||
},
|
||||
twitter: {
|
||||
isEnabled: true,
|
||||
shareUrl: 'facebook-share-url',
|
||||
socialBrand: 'facebook-social-brand',
|
||||
},
|
||||
};
|
||||
const courseName = 'test-course-name';
|
||||
let wrapper;
|
||||
|
||||
describe('CourseCardMenu', () => {
|
||||
const props = {
|
||||
cardId: 'test-card-id',
|
||||
};
|
||||
const defaultEmailSettingsModal = {
|
||||
isVisible: false,
|
||||
show: jest.fn().mockName('emailSettingShow'),
|
||||
hide: jest.fn().mockName('emailSettingHide'),
|
||||
};
|
||||
const defaultUnenrollModal = {
|
||||
isVisible: false,
|
||||
show: jest.fn().mockName('unenrollShow'),
|
||||
hide: jest.fn().mockName('unenrollHide'),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
useEmailSettings.mockReturnValue(defaultEmailSettingsModal);
|
||||
useUnenrollData.mockReturnValue(defaultUnenrollModal);
|
||||
appHooks.useCardSocialSettingsData.mockReturnValue(defaultSocialShare);
|
||||
appHooks.useCardCourseData.mockReturnValue({ courseName });
|
||||
appHooks.useMasqueradeData.mockReturnValue({ isMasquerading: false });
|
||||
});
|
||||
test('snapshot', () => {
|
||||
useCourseCardMenuData.mockReturnValue({
|
||||
emailSettingsModal: defaultEmailSettingsModal,
|
||||
unenrollModal: defaultUnenrollModal,
|
||||
});
|
||||
const wrapper = shallow(<CourseCardMenu {...props} />);
|
||||
wrapper = shallow(<CourseCardMenu {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
// expect(wrapper.find('FacebookShareButton').length).toEqual(1);
|
||||
expect(wrapper.find('TwitterShareButton').length).toEqual(1);
|
||||
expect(wrapper.find({
|
||||
'data-testid': 'unenrollModalToggle',
|
||||
}).props().disabled).toEqual(false);
|
||||
expect(wrapper.find({
|
||||
'data-testid': 'emailSettingsModalToggle',
|
||||
}).props().disabled).toEqual(false);
|
||||
});
|
||||
test('snapshot: masquerading', () => {
|
||||
appHooks.useMasqueradeData.mockReturnValue({ isMasquerading: true });
|
||||
wrapper = shallow(<CourseCardMenu {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
expect(wrapper.find({
|
||||
'data-testid': 'unenrollModalToggle',
|
||||
}).props().disabled).toEqual(true);
|
||||
expect(wrapper.find({
|
||||
'data-testid': 'emailSettingsModalToggle',
|
||||
}).props().disabled).toEqual(true);
|
||||
});
|
||||
/*
|
||||
test('facebook share disabled', () => {
|
||||
appHooks.useCardSocialSettingsData.mockReturnValueOnce({
|
||||
...defaultSocialShare,
|
||||
facebook: { ...defaultSocialShare.facebook, isEnabled: false },
|
||||
});
|
||||
wrapper = shallow(<CourseCardMenu {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
expect(wrapper.find('FacebookShareButton').length).toEqual(0);
|
||||
});
|
||||
*/
|
||||
test('twitter share disabled', () => {
|
||||
appHooks.useCardSocialSettingsData.mockReturnValueOnce({
|
||||
...defaultSocialShare,
|
||||
twitter: { ...defaultSocialShare.twitter, isEnabled: false },
|
||||
});
|
||||
wrapper = shallow(<CourseCardMenu {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
expect(wrapper.find('TwitterShareButton').length).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { StrictDict } from 'utils';
|
||||
|
||||
export const messages = StrictDict({
|
||||
unenroll: {
|
||||
id: 'learner-dash.courseCardMenu.unenroll',
|
||||
description: 'Course unenroll menu button',
|
||||
defaultMessage: 'Unenroll',
|
||||
},
|
||||
dropdownAlt: {
|
||||
id: 'learner-dash.courseCardMenu.dropdownAlt',
|
||||
description: 'Course action menu alt-text',
|
||||
defaultMessage: 'Course actions dropdown',
|
||||
},
|
||||
emailSettings: {
|
||||
id: 'learner-dash.courseCardMenu.emailSettings',
|
||||
description: 'Course email settings menu button',
|
||||
defaultMessage: 'Email settings',
|
||||
},
|
||||
shareToFacebook: {
|
||||
id: 'learner-dash.courseCardMenu.shareToFacebook',
|
||||
description: 'Course Facebook Sharing button',
|
||||
defaultMessage: 'Share to Facebook',
|
||||
},
|
||||
shareToTwitter: {
|
||||
id: 'learner-dash.courseCardMenu.shareToTwitter',
|
||||
description: 'Course Twitter Sharing button',
|
||||
defaultMessage: 'Share to Twitter',
|
||||
},
|
||||
shareQuote: {
|
||||
id: 'learner-dash.courseCardMenu.shareQuote',
|
||||
description: 'Social sharing quote',
|
||||
defaultMessage: 'I\'m taking {courseName} online with {socialBrand}. Check it out!',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
@@ -18,7 +18,7 @@ exports[`EnterpriseDashboard snapshot 1`] = `
|
||||
You have access to the edX, Inc. dashboard
|
||||
</h4>
|
||||
<p>
|
||||
To access the coureses available to you through edX, Inc., visit the edX, Inc. dashboard now.
|
||||
To access the courses available to you through edX, Inc., visit the edX, Inc. dashboard now.
|
||||
</p>
|
||||
<ActionRow>
|
||||
<Button
|
||||
|
||||
@@ -8,7 +8,7 @@ const messages = defineMessages({
|
||||
},
|
||||
enterpriseDialogBody: {
|
||||
id: 'leanerDashboard.enterpriseDialogBody',
|
||||
defaultMessage: 'To access the coureses available to you through {label}, visit the {label} dashboard now.',
|
||||
defaultMessage: 'To access the courses available to you through {label}, visit the {label} dashboard now.',
|
||||
description: 'Body text for enterpise dashboard dialog',
|
||||
},
|
||||
enterpriseDialogDismissButton: {
|
||||
|
||||
@@ -42,6 +42,7 @@ const app = createSlice({
|
||||
enterpriseDashboard: payload.enterpriseDashboard,
|
||||
platformSettings: payload.platformSettings,
|
||||
suggestedCourses: payload.suggestedCourses,
|
||||
socialShareSettings: payload.socialShareSettings,
|
||||
}),
|
||||
updateSelectSessionModal: (state, { payload }) => ({
|
||||
...state,
|
||||
|
||||
@@ -35,6 +35,7 @@ export const courseCard = StrictDict({
|
||||
courseNumber: course.courseNumber,
|
||||
courseName: course.courseName,
|
||||
website: course.website,
|
||||
socialShareUrl: course.socialShareUrl,
|
||||
}),
|
||||
),
|
||||
courseProvider: mkCardSelector(
|
||||
|
||||
@@ -108,6 +108,7 @@ describe('courseCard selectors module', () => {
|
||||
courseNumber: 'test-course-number',
|
||||
courseName: 'test-course-name',
|
||||
website: 'test-website',
|
||||
socialShareUrl: 'test-social-share-url',
|
||||
});
|
||||
});
|
||||
it('returns a card selector based on course cardSimpleSelector', () => {
|
||||
@@ -116,8 +117,11 @@ describe('courseCard selectors module', () => {
|
||||
it('passes bannerImgSrc, converted to a baseAppUrl', () => {
|
||||
expect(selected.bannerImgSrc).toEqual(baseAppUrl(testData.bannerImgSrc));
|
||||
});
|
||||
it('passes [courseNumber, courseName, website]', () => {
|
||||
it('passes [courseNumber, courseName, website, socialShareUrl]', () => {
|
||||
expect(selected.courseNumber).toEqual(testData.courseNumber);
|
||||
expect(selected.courseName).toEqual(testData.courseName);
|
||||
expect(selected.website).toEqual(testData.website);
|
||||
expect(selected.socialShareUrl).toEqual(testData.socialShareUrl);
|
||||
});
|
||||
});
|
||||
describe('courseProvider selector', () => {
|
||||
|
||||
@@ -15,6 +15,7 @@ export const simpleSelectors = StrictDict({
|
||||
enterpriseDashboard: mkSimpleSelector(app => app.enterpriseDashboard),
|
||||
selectSessionModal: mkSimpleSelector(app => app.selectSessionModal),
|
||||
pageNumber: mkSimpleSelector(app => app.pageNumber),
|
||||
socialShareSettings: mkSimpleSelector(app => app.socialShareSettings),
|
||||
});
|
||||
|
||||
export const cardSimpleSelectors = StrictDict({
|
||||
|
||||
@@ -28,6 +28,7 @@ describe('app simple selectors', () => {
|
||||
keys.enterpriseDashboard,
|
||||
keys.selectSessionModal,
|
||||
keys.pageNumber,
|
||||
keys.socialShareSettings,
|
||||
])('%s app simple selector forwards corresponding data from app store', (key) => {
|
||||
testState = { app: { [key]: testString, otherField: 'fake string' } };
|
||||
const { preSelectors, cb } = simpleSelectors[key];
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useSelector } from 'react-redux';
|
||||
import { actions as appActions } from './app/reducer';
|
||||
import appSelectors from './app/selectors';
|
||||
import requestSelectors from './requests/selectors';
|
||||
import * as module from './hooks';
|
||||
|
||||
const { courseCard } = appSelectors;
|
||||
|
||||
@@ -13,6 +14,7 @@ export const usePlatformSettingsData = () => useSelector(appSelectors.platformSe
|
||||
// suggested courses is max at 3 at the moment.
|
||||
export const useSuggestedCoursesData = () => useSelector(appSelectors.suggestedCourses).slice(0, 3);
|
||||
export const useSelectSessionModalData = () => useSelector(appSelectors.selectSessionModal);
|
||||
export const useSocialSettingsData = () => useSelector(appSelectors.socialSettingsData);
|
||||
|
||||
export const useHasCourses = () => useSelector(appSelectors.hasCourses);
|
||||
export const useHasAvailableDashboards = () => useSelector(appSelectors.hasAvailableDashboards);
|
||||
@@ -35,6 +37,27 @@ export const useCardGradeData = useCourseCardData(courseCard.gradeData);
|
||||
export const useCardProviderData = useCourseCardData(courseCard.courseProvider);
|
||||
export const useCardRelatedProgramsData = useCourseCardData(courseCard.relatedPrograms);
|
||||
|
||||
export const useCardSocialSettingsData = (cardId) => {
|
||||
const { socialShareUrl } = module.useCardCourseData(cardId);
|
||||
const socialShareSettings = useSelector(appSelectors.socialShareSettings);
|
||||
if (!socialShareSettings) {
|
||||
return {
|
||||
facebook: { isEnabled: false, shareUrl: '' },
|
||||
twitter: { isEnabled: false, shareUrl: '' },
|
||||
};
|
||||
}
|
||||
return {
|
||||
facebook: {
|
||||
isEnabled: socialShareSettings.facebook.isEnabled,
|
||||
shareUrl: `${socialShareUrl}?${socialShareSettings.facebook.utmParams}`,
|
||||
},
|
||||
twitter: {
|
||||
isEnabled: socialShareSettings.twitter.isEnabled,
|
||||
shareUrl: `${socialShareUrl}?${socialShareSettings.twitter.utmParams}`,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const useUpdateSelectSessionModalCallback = (dispatch, cardId) => () => dispatch(
|
||||
appActions.updateSelectSessionModal(cardId),
|
||||
);
|
||||
|
||||
@@ -49,7 +49,7 @@ export const relatedPrograms = [
|
||||
export const genCardId = (index) => `card-id${index}`;
|
||||
export const genCourseId = (index) => `course-number${index}-course-id${index}`;
|
||||
export const genCourseNumber = (index) => `course-number${index}`;
|
||||
export const genCourseTitle = (index) => `Course Name ${index}`;
|
||||
export const genCourseShareUrl = (index) => `home.edx.org?social-share-url/${index}`;
|
||||
export const genEntitlementUUID = (index) => `entitlement-course-uuid-${index}`;
|
||||
|
||||
const bannerImgSrc = '/asset-v1:edX+DemoX+Demo_Course+type@asset+block@images_course_image.jpg';
|
||||
@@ -95,6 +95,18 @@ export const globalData = {
|
||||
courseUrl: 'www.edx/suggested-course',
|
||||
},
|
||||
],
|
||||
socialShareSettings: {
|
||||
facebook: {
|
||||
isEnabled: true,
|
||||
socialBrand: 'edx.org',
|
||||
utmParams: 'utm_campaign=social-sharing-db&utm_medium=social&utm_source=facebook',
|
||||
},
|
||||
twitter: {
|
||||
isEnabled: true,
|
||||
socialBrand: 'edx.org',
|
||||
utmParams: 'utm_campaign=social-sharing-db&utm_medium=social&utm_source=twitter',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const genCourseRunData = (data = {}) => ({
|
||||
@@ -169,9 +181,12 @@ export const availableSessions = [
|
||||
|
||||
export const courseRuns = [
|
||||
// audit, course run not started
|
||||
{},
|
||||
{
|
||||
courseName: 'Audit Course, Course run not started',
|
||||
},
|
||||
// audit, course run not started, too early to view
|
||||
{
|
||||
courseName: 'Audit Course, Course run not started, Too early to view',
|
||||
enrollment: {
|
||||
coursewareAccess: {
|
||||
isTooEarly: true,
|
||||
@@ -182,6 +197,7 @@ export const courseRuns = [
|
||||
},
|
||||
// audit, course run not started, too early to view and unmet prereqs
|
||||
{
|
||||
courseName: 'Audit Course, Course run not started, Too early to view, Has unmet prereqs.',
|
||||
enrollment: {
|
||||
coursewareAccess: {
|
||||
isTooEarly: true,
|
||||
@@ -192,10 +208,12 @@ export const courseRuns = [
|
||||
},
|
||||
// audit, course run started
|
||||
{
|
||||
courseName: 'Audit Course, Course run not started',
|
||||
courseRun: { isStarted: true },
|
||||
},
|
||||
// audit, course run started, unmet prereqs
|
||||
{
|
||||
courseName: 'Audit Course, Course run not started, Has unmet prereqs',
|
||||
enrollment: {
|
||||
coursewareAccess: {
|
||||
isTooEarly: true,
|
||||
@@ -207,6 +225,7 @@ export const courseRuns = [
|
||||
},
|
||||
// audit, course run started, access expired, learner not started
|
||||
{
|
||||
courseName: 'Audit Course, Course run started, Audit ccess expired, Learner not started',
|
||||
courseRun: { isStarted: true },
|
||||
enrollment: {
|
||||
accessExpirationDate: pastDate,
|
||||
@@ -215,6 +234,7 @@ export const courseRuns = [
|
||||
},
|
||||
// audit, course run started, access expired, cannot upgrade, learner not started
|
||||
{
|
||||
courseName: 'Audit course, Course run not started, Audit access expired, Cannot upgrade, Learner not started',
|
||||
courseRun: { isStarted: true },
|
||||
enrollment: {
|
||||
accessExpirationDate: pastDate,
|
||||
@@ -224,6 +244,7 @@ export const courseRuns = [
|
||||
},
|
||||
// audit, course run ended, access expired, cannot upgrade, learner not started
|
||||
{
|
||||
courseName: 'Audit Course, Course run ended, Audit access expired, Cannot upgrade, Learner not started',
|
||||
courseRun: {
|
||||
endDate: pastDate,
|
||||
isStarted: true,
|
||||
@@ -235,6 +256,7 @@ export const courseRuns = [
|
||||
},
|
||||
// audit, course run archived, access expired, cannot upgrade, learner not started
|
||||
{
|
||||
courseName: 'Audit Course, Course run archived, Audit access expired, Cannot upgrade, Learner not started',
|
||||
courseRun: {
|
||||
endDate: pastDate,
|
||||
isArchived: true,
|
||||
@@ -247,11 +269,13 @@ export const courseRuns = [
|
||||
},
|
||||
// audit, course run and learner started, passing
|
||||
{
|
||||
courseName: 'Audit Course, Course run and learner started, Passing',
|
||||
courseRun: { isStarted: true },
|
||||
enrollment: { hasStarted: true },
|
||||
},
|
||||
// audit, course run and learner started, access expired
|
||||
{
|
||||
courseName: 'Audit Course, Course run and learner started, Audit access expired',
|
||||
courseRun: { isStarted: true },
|
||||
enrollment: {
|
||||
accessExpirationDate: pastDate,
|
||||
@@ -261,6 +285,7 @@ export const courseRuns = [
|
||||
},
|
||||
// audit, course run and learner started, access expired, cannot upgrade
|
||||
{
|
||||
courseName: 'Audit Course, Course run and learner started, Audit access expired, Cannot upgrade',
|
||||
courseRun: { isStarted: true },
|
||||
enrollment: {
|
||||
accessExpirationDate: pastDate,
|
||||
@@ -271,6 +296,7 @@ export const courseRuns = [
|
||||
},
|
||||
// audit, course run ended, learner started, expired, cannot upgraded, not passing
|
||||
{
|
||||
courseName: 'Audit Course, Course run ended, Learner started, Access expired, Cannot upgrade, Not passing',
|
||||
courseRun: {
|
||||
isStarted: true,
|
||||
endDate: pastDate,
|
||||
@@ -285,6 +311,7 @@ export const courseRuns = [
|
||||
},
|
||||
// audit, course run archived, learner started, expired, cannot upgrade, not passing
|
||||
{
|
||||
courseName: 'Audit Course, Course run archived, Learner started, Access expired, Cannot upgrade, Not passing',
|
||||
courseRun: {
|
||||
isStarted: true,
|
||||
isArchived: true,
|
||||
@@ -299,25 +326,32 @@ export const courseRuns = [
|
||||
grade: { isPassing: false },
|
||||
},
|
||||
// verified, course not started, learner not started
|
||||
{ enrollment: { isVerified: true } },
|
||||
{
|
||||
courseName: 'Verified Course, Course and learner not started',
|
||||
enrollment: { isVerified: true },
|
||||
},
|
||||
// verified, course started, learner not started
|
||||
{
|
||||
courseName: 'Verified Course, Course started, Learner not started',
|
||||
courseRun: { isStarted: true },
|
||||
enrollment: { isVerified: true },
|
||||
},
|
||||
// verified, course started, learner started, passing
|
||||
{
|
||||
courseName: 'Verified Course, Course and learner started, Passing',
|
||||
courseRun: { isStarted: true },
|
||||
enrollment: { hasStarted: true, isVerified: true },
|
||||
},
|
||||
// verified, course started, learner started, not passing
|
||||
{
|
||||
courseName: 'Verified Course, Course and learner started, not passing',
|
||||
courseRun: { isStarted: true },
|
||||
gradeData: { isPassing: false },
|
||||
enrollment: { hasStarted: true, isVerified: true },
|
||||
},
|
||||
// verified, learner finished, not passing, cert not earned
|
||||
{
|
||||
courseName: 'Verified Course, Learner finished, cert not earned',
|
||||
enrollment: {
|
||||
hasFinished: true,
|
||||
hasStarted: true,
|
||||
@@ -331,6 +365,7 @@ export const courseRuns = [
|
||||
},
|
||||
// verified, learner finished, passing, cert earned but not available
|
||||
{
|
||||
courseName: 'Verified Course, Learner finished, Cert earned but not available',
|
||||
enrollment: {
|
||||
hasFinished: true,
|
||||
hasStarted: true,
|
||||
@@ -344,6 +379,7 @@ export const courseRuns = [
|
||||
},
|
||||
// verified, learner finished, passing, restricted
|
||||
{
|
||||
courseName: 'Verified Course, Learner finished, Passing, Certificate restricted',
|
||||
enrollment: {
|
||||
hasFinished: true,
|
||||
hasStarted: true,
|
||||
@@ -354,6 +390,7 @@ export const courseRuns = [
|
||||
},
|
||||
// verified, learner finished, cert earned, downloadable (web + link)
|
||||
{
|
||||
courseName: 'Verified Course, Learner finished, Passing, Certificate downloadable and viewable',
|
||||
enrollment: {
|
||||
hasFinished: true,
|
||||
hasStarted: true,
|
||||
@@ -369,6 +406,7 @@ export const courseRuns = [
|
||||
},
|
||||
// verified, course ended, learner finished, cert earned, downloadable (link only),
|
||||
{
|
||||
courseName: 'Verified Course, Course ended, Learner finished, Passing, Certificate downloadable',
|
||||
enrollment: {
|
||||
hasFinished: true,
|
||||
hasStarted: true,
|
||||
@@ -386,6 +424,7 @@ export const courseRuns = [
|
||||
},
|
||||
// verified, course archived, learner finished, cert earned, downloadable (web + link)
|
||||
{
|
||||
courseName: 'Verified Course, Course archived, Learner finished, Passing, Certificate downloadable and viewable',
|
||||
enrollment: {
|
||||
hasFinished: true,
|
||||
hasStarted: true,
|
||||
@@ -405,6 +444,7 @@ export const courseRuns = [
|
||||
},
|
||||
// Entitlement - not started
|
||||
{
|
||||
courseName: 'Entitlement Course, not started',
|
||||
enrollment: {
|
||||
isVerified: true,
|
||||
coursewareAccess: {
|
||||
@@ -426,6 +466,7 @@ export const courseRuns = [
|
||||
},
|
||||
// Entitlement - Course run started, learner not started, unmet prereqs
|
||||
{
|
||||
courseName: 'Entitlement Course, Course run started, Learner not started, Has unmet prereqs',
|
||||
enrollment: {
|
||||
isVerified: true,
|
||||
coursewareAccess: {
|
||||
@@ -444,6 +485,7 @@ export const courseRuns = [
|
||||
},
|
||||
// Entitlement - Course run started, learner started, not passing
|
||||
{
|
||||
courseName: 'Entitlement Course, Course run started, Learner started, Not passing',
|
||||
enrollment: {
|
||||
isVerified: true,
|
||||
hasStarted: true,
|
||||
@@ -462,6 +504,7 @@ export const courseRuns = [
|
||||
},
|
||||
// Entitlement - Course run started, learner started, passing, cannot change
|
||||
{
|
||||
courseName: 'Entitlement Course, Course run and learner started, Passing, Cannot change sessions',
|
||||
enrollment: {
|
||||
isVerified: true,
|
||||
hasStarted: true,
|
||||
@@ -479,6 +522,7 @@ export const courseRuns = [
|
||||
},
|
||||
// Entitlement - Learner finished, but did not pass
|
||||
{
|
||||
courseName: 'Entitlement Course, Learner finished but did not pass',
|
||||
enrollment: {
|
||||
isVerified: true,
|
||||
hasFinished: false,
|
||||
@@ -497,6 +541,7 @@ export const courseRuns = [
|
||||
},
|
||||
// Entitlement - Learner finished, and passed. cannot refund. previewable cert.
|
||||
{
|
||||
courseName: 'Entitlement course, Learner finished and passed, Cannot refund, Previewable Cert',
|
||||
enrollment: {
|
||||
isVerified: true,
|
||||
hasFinished: false,
|
||||
@@ -520,6 +565,7 @@ export const courseRuns = [
|
||||
},
|
||||
// Entitlement - Learner finished and failed. cannot refund. course ended.
|
||||
{
|
||||
courseName: 'Entitlement Course, Learner finished and failed, Cannot refund, Course ended',
|
||||
enrollment: {
|
||||
isVerified: true,
|
||||
hasFinished: false,
|
||||
@@ -541,6 +587,7 @@ export const courseRuns = [
|
||||
},
|
||||
// Entitlement - Learner finished and passed. cannot refund. course archived. cert downloadable
|
||||
{
|
||||
courseName: 'Entitlement Course, Learner finished and passed, Cannot refund, Course archived, Cert downloadable',
|
||||
enrollment: {
|
||||
isVerified: true,
|
||||
hasFinished: false,
|
||||
@@ -574,6 +621,7 @@ export const courseRuns = [
|
||||
// unfulfilled entitlement select session pass deadline without available session
|
||||
export const entitlementCourses = [
|
||||
{
|
||||
courseName: 'Unfulfilled Entitlement select session',
|
||||
entitlement: {
|
||||
uuid: genEntitlementUUID(10),
|
||||
availableSessions,
|
||||
@@ -584,6 +632,7 @@ export const entitlementCourses = [
|
||||
isRefundable: true,
|
||||
},
|
||||
}, {
|
||||
courseName: 'Unfulfilled Entitlement select session with upcoming deadline',
|
||||
entitlement: {
|
||||
uuid: genEntitlementUUID(11),
|
||||
availableSessions,
|
||||
@@ -594,6 +643,7 @@ export const entitlementCourses = [
|
||||
isRefundable: true,
|
||||
},
|
||||
}, {
|
||||
courseName: 'Unfulfilled Entitlement select session past deadline, With available session',
|
||||
entitlement: {
|
||||
uuid: genEntitlementUUID(12),
|
||||
availableSessions,
|
||||
@@ -604,6 +654,7 @@ export const entitlementCourses = [
|
||||
isRefundable: true,
|
||||
},
|
||||
}, {
|
||||
courseName: 'Unfulfilled Entitlement select session past deadline, With available no session',
|
||||
entitlement: {
|
||||
uuid: genEntitlementUUID(13),
|
||||
availableSessions: [],
|
||||
@@ -616,34 +667,33 @@ export const entitlementCourses = [
|
||||
},
|
||||
];
|
||||
|
||||
export const compileCourseRunData = (data, index) => {
|
||||
const courseName = genCourseTitle(index);
|
||||
const providerOptions = [
|
||||
providers.edx,
|
||||
providers.mit,
|
||||
null,
|
||||
];
|
||||
|
||||
const emailOptions = [
|
||||
{ isEmailEnabled: false, hasOptedOutOfEmail: false },
|
||||
{ isEmailEnabled: true, hasOptedOutOfEmail: false },
|
||||
{ isEmailEnabled: true, hasOptedOutOfEmail: true },
|
||||
];
|
||||
|
||||
const programsOptions = [
|
||||
{ relatedPrograms },
|
||||
{ relatedPrograms: [relatedPrograms[0]] },
|
||||
{ relatedPrograms: [] },
|
||||
];
|
||||
|
||||
const getOption = (options, index) => options[index % options.length];
|
||||
|
||||
export const compileCourseRunData = ({ courseName, ...data }, index) => {
|
||||
const courseId = genCourseId(index);
|
||||
const courseNumber = genCourseNumber(index);
|
||||
const providerIndex = index % 3;
|
||||
const socialShareUrl = genCourseShareUrl(index);
|
||||
const lastEnrolledDate = new Date();
|
||||
lastEnrolledDate.setDate(lastEnrolledDate.getDate() - index);
|
||||
lastEnrolledDate.setDate(lastEnrolledDate.getDate() - index - 1);
|
||||
const lastEnrolled = lastEnrolledDate.toISOString();
|
||||
const iteratedData = [
|
||||
{
|
||||
course: { courseName, bannerImgSrc, courseNumber },
|
||||
emailSettings: { isEmailEnabled: false, hasOptedOutOfEmail: false },
|
||||
programs: { relatedPrograms },
|
||||
courseProvider: providers.edx,
|
||||
},
|
||||
{
|
||||
course: { courseName, bannerImgSrc, courseNumber },
|
||||
emailSettings: { isEmailEnabled: true, hasOptedOutOfEmail: false },
|
||||
courseProvider: providers.mit,
|
||||
programs: { relatedPrograms: [relatedPrograms[0]] },
|
||||
},
|
||||
{
|
||||
course: { courseName, bannerImgSrc, courseNumber },
|
||||
emailSettings: { isEmailEnabled: true, hasOptedOutOfEmail: true },
|
||||
courseProvider: null,
|
||||
programs: { relatedPrograms: [] },
|
||||
},
|
||||
];
|
||||
const out = {
|
||||
gradeData: { isPassing: true },
|
||||
entitlement: null,
|
||||
@@ -652,12 +702,17 @@ export const compileCourseRunData = (data, index) => {
|
||||
enrollment: genEnrollmentData({ lastEnrolled, ...data.enrollment }),
|
||||
courseRun: genCourseRunData({
|
||||
...data.courseRun,
|
||||
...iteratedData.emailSettings,
|
||||
...getOption(emailOptions, index),
|
||||
courseId,
|
||||
}),
|
||||
courseProvider: iteratedData[providerIndex].courseProvider,
|
||||
course: iteratedData[providerIndex].course,
|
||||
programs: iteratedData[providerIndex].programs,
|
||||
course: {
|
||||
courseName,
|
||||
bannerImgSrc,
|
||||
courseNumber,
|
||||
socialShareUrl,
|
||||
},
|
||||
courseProvider: getOption(providerOptions, index),
|
||||
programs: getOption(programsOptions, index),
|
||||
};
|
||||
if (out.enrollment.canUpgrade) {
|
||||
out.courseRun.upgradeUrl = 'test-upgrade-url';
|
||||
@@ -665,27 +720,9 @@ export const compileCourseRunData = (data, index) => {
|
||||
return out;
|
||||
};
|
||||
|
||||
export const compileEntitlementData = (data, index) => {
|
||||
const courseName = genCourseTitle(100 + index);
|
||||
export const compileEntitlementData = ({ courseName, ...data }, index) => {
|
||||
const courseNumber = genCourseNumber(100 + index);
|
||||
const providerIndex = index % 3;
|
||||
const iteratedData = [
|
||||
{
|
||||
courseProvider: providers.edx,
|
||||
course: { courseNumber, courseName, bannerImgSrc },
|
||||
programs: { relatedPrograms },
|
||||
},
|
||||
{
|
||||
courseProvider: providers.mit,
|
||||
course: { courseNumber, courseName, bannerImgSrc },
|
||||
programs: { relatedPrograms: [relatedPrograms[0]] },
|
||||
},
|
||||
{
|
||||
courseProvider: null,
|
||||
course: { courseNumber, courseName, bannerImgSrc },
|
||||
programs: { relatedPrograms: [] },
|
||||
},
|
||||
];
|
||||
const socialShareUrl = genCourseShareUrl(100 + index);
|
||||
return {
|
||||
enrollment: genEnrollmentData({
|
||||
isEnrolled: false,
|
||||
@@ -703,7 +740,14 @@ export const compileEntitlementData = (data, index) => {
|
||||
certificate: null,
|
||||
courseRun: null,
|
||||
...data,
|
||||
...iteratedData[providerIndex],
|
||||
course: {
|
||||
courseName,
|
||||
courseNumber,
|
||||
bannerImgSrc,
|
||||
socialShareUrl,
|
||||
},
|
||||
courseProvider: getOption(providerOptions, index),
|
||||
programs: getOption(programsOptions, index),
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import * as fakeData from 'data/services/lms/fakeData/courses';
|
||||
import { RequestKeys, RequestStates } from 'data/constants/requests';
|
||||
import reducers from 'data/redux';
|
||||
import messages from 'i18n';
|
||||
import { selectors } from 'data/redux';
|
||||
import { selectors, thunkActions } from 'data/redux';
|
||||
import { cardId as genCardId } from 'data/redux/app/reducer';
|
||||
|
||||
import App from 'App';
|
||||
@@ -134,46 +134,63 @@ const waitForRequestStatus = (key, status) => waitForEqual(
|
||||
);
|
||||
|
||||
const loadApp = async (courses) => {
|
||||
initCourses.mockReturnValue(courses);
|
||||
initCourses.mockReturnValue(courses.map(compileCourseRunData));
|
||||
await renderEl();
|
||||
inspector = new Inspector(el);
|
||||
await waitForRequestStatus(RequestKeys.initialize, RequestStates.pending);
|
||||
resolveFns.init.success();
|
||||
await waitForRequestStatus(RequestKeys.initialize, RequestStates.completed);
|
||||
}
|
||||
|
||||
const courseNames = [
|
||||
'course-name-1',
|
||||
'course-name-2',
|
||||
'course-name-3',
|
||||
];
|
||||
|
||||
describe('ESG app integration tests', () => {
|
||||
beforeEach(() => {
|
||||
mockApi();
|
||||
});
|
||||
|
||||
test('initialization', async () => {
|
||||
await loadApp([compileCourseRunData({}, 0)]);
|
||||
await waitForRequestStatus(RequestKeys.initialize, RequestStates.pending);
|
||||
resolveFns.init.success();
|
||||
await waitForRequestStatus(RequestKeys.initialize, RequestStates.completed);
|
||||
await loadApp([{ courseName: courseNames[0] }]);
|
||||
});
|
||||
|
||||
describe('course cards', () => {
|
||||
const loadCourses = async (courses, tests) => {
|
||||
await loadApp(courses);
|
||||
resolveFns.init.success();
|
||||
await waitForRequestStatus(RequestKeys.initialize, RequestStates.completed);
|
||||
const courseNames = [
|
||||
'course-name-0',
|
||||
'course-name-1',
|
||||
'course-name-2',
|
||||
];
|
||||
const testCourse = async (tests) => {
|
||||
await getState();
|
||||
const cards = inspector.get.courseCards;
|
||||
courses.forEach((course, index) => {
|
||||
const card = cards.at(index);
|
||||
const cardId = genCardId(index);
|
||||
const cardDetails = inspector.get.card.details(card);
|
||||
const { courseName } = selectors.app.courseCard.course(state, cardId);
|
||||
inspector.verifyText(inspector.get.card.header(card), courseName);
|
||||
if (tests.length > index) {
|
||||
tests[index]({ cardId, cardDetails });
|
||||
}
|
||||
});
|
||||
const index = 0;
|
||||
const card = cards.at(index);
|
||||
const cardId = genCardId(index);
|
||||
const cardDetails = inspector.get.card.details(card);
|
||||
const courseData = selectors.app.courseCard.course(state, cardId);
|
||||
const { courseName } = selectors.app.courseCard.course(state, cardId);
|
||||
inspector.verifyText(inspector.get.card.header(card), courseName);
|
||||
if (tests.length > index) {
|
||||
tests[index]({ cardId, cardDetails });
|
||||
}
|
||||
}
|
||||
|
||||
const loadCourse = async (course) => {
|
||||
initCourses.mockReturnValue([course].map(compileCourseRunData));
|
||||
store.dispatch(thunkActions.app.initialize());
|
||||
await waitForRequestStatus(RequestKeys.initialize, RequestStates.pending);
|
||||
resolveFns.init.success();
|
||||
await waitForRequestStatus(RequestKeys.initialize, RequestStates.completed);
|
||||
};
|
||||
|
||||
test('audit', async () => {
|
||||
const courses = [
|
||||
{}, // audit, course run not started
|
||||
{ courseName: courseNames[0] }, // audit, course run not started
|
||||
{
|
||||
courseName: courseNames[1],
|
||||
enrollment: {
|
||||
coursewareAccess: {
|
||||
isTooEarly: true,
|
||||
@@ -183,6 +200,7 @@ describe('ESG app integration tests', () => {
|
||||
},
|
||||
}, // audit, course run not started, is too early
|
||||
{
|
||||
courseName: courseNames[2],
|
||||
courseRun: {
|
||||
courseRun: { isStarted: true },
|
||||
},
|
||||
@@ -195,7 +213,8 @@ describe('ESG app integration tests', () => {
|
||||
}, // audit, course run and learner started, access expired, cannot upgrade
|
||||
];
|
||||
const { formatDate } = useIntl();
|
||||
await loadCourses(courses.map(compileCourseRunData), [
|
||||
await loadApp([courses[0]]);
|
||||
await testCourse([
|
||||
({ cardId, cardDetails }) => {
|
||||
const enrollment = selectors.app.courseCard.enrollment(state, cardId);
|
||||
const courseRun = selectors.app.courseCard.courseRun(state, cardId);
|
||||
@@ -212,6 +231,9 @@ describe('ESG app integration tests', () => {
|
||||
}),
|
||||
].forEach(value => inspector.verifyTextIncludes(cardDetails, value));
|
||||
},
|
||||
]);
|
||||
await loadCourse(courses[1]);
|
||||
await testCourse([
|
||||
({ cardId, cardDetails }) => {
|
||||
const enrollment = selectors.app.courseCard.enrollment(state, cardId);
|
||||
const courseRun = selectors.app.courseCard.courseRun(state, cardId);
|
||||
|
||||
Reference in New Issue
Block a user