Skip to content

Commit

Permalink
Merge branch 'master' into ahtesham/VAN-1601/design
Browse files Browse the repository at this point in the history
  • Loading branch information
ahtesham-quraish committed Aug 16, 2023
2 parents 6cecc38 + ce269e8 commit 4ee6543
Show file tree
Hide file tree
Showing 44 changed files with 2,175 additions and 1,843 deletions.
1,754 changes: 827 additions & 927 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"@edx/frontend-enterprise-hotjar": "^1.2.0",
"@edx/frontend-platform": "^4.2.0",
"@edx/paragon": "^20.32.0",
"@edx/react-unit-test-utils": "^1.7.0",
"@fortawesome/fontawesome-svg-core": "^1.2.36",
"@fortawesome/free-brands-svg-icons": "^5.15.4",
"@fortawesome/free-solid-svg-icons": "^5.15.4",
Expand All @@ -53,6 +54,7 @@
"history": "5.0.1",
"html-react-parser": "^1.3.0",
"jest": "^26.6.3",
"jest-when": "^3.6.0",
"lodash": "^4.17.21",
"moment": "^2.29.4",
"prop-types": "15.7.2",
Expand Down
51 changes: 51 additions & 0 deletions src/components/ModalView/__snapshots__/index.test.jsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`ModalView snapshot renders default ModalView 1`] = `
<div
className="containers"
>
<ModalDialog
hasCloseButton={false}
isFullscreenScroll={true}
isOpen={true}
onClose={[MockFunction]}
title=""
>
<ModalDialog.Header>
<Component>
<h3
className="mt-2"
>
Thank you for your interest!
</h3>
</Component>
</ModalDialog.Header>
<ModalDialog.Body>
<div>
<p
className="mt-2"
>
Personalized recommendations feature is not yet available. We are working hard on bringing it to your learner home in the near future.
</p>
<p>
Would you like to be alerted when it becomes available?
</p>
</div>
</ModalDialog.Body>
<Component>
<ActionRow>
<Component
variant="tertiary"
>
Skip for now
</Component>
<Button
variant="primary"
>
Count me in!
</Button>
</ActionRow>
</Component>
</ModalDialog>
</div>
`;
18 changes: 18 additions & 0 deletions src/components/ModalView/hooks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react';
import { StrictDict } from 'utils';

import * as module from './hooks';

export const state = StrictDict({
isRecommendationsModalOpen: (val) => React.useState(val), // eslint-disable-line
});

export const useRecommendationsModal = () => {
const [isRecommendationsModalOpen, setIsRecommendationsModalOpen] = module.state.isRecommendationsModalOpen(false);
const toggleRecommendationsModal = () => setIsRecommendationsModalOpen(!isRecommendationsModalOpen);

return {
isRecommendationsModalOpen,
toggleRecommendationsModal,
};
};
21 changes: 21 additions & 0 deletions src/components/ModalView/hooks.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { MockUseState } from 'testUtils';

import * as hooks from './hooks';

const state = new MockUseState(hooks);

const {
useRecommendationsModal,
} = hooks;

describe('LearnerDashboardHeader hooks', () => {
describe('useRecommendationsModal', () => {
test('default state', () => {
state.mock();
const out = useRecommendationsModal();
state.expectInitializedWith(state.keys.isRecommendationsModalOpen, false);
out.toggleRecommendationsModal();
expect(state.values.isRecommendationsModalOpen).toEqual(true);
});
});
});
12 changes: 4 additions & 8 deletions src/components/ModalView/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,12 @@ export const ModalView = ({
}) => {
const { formatMessage } = useIntl();

const handleClose = () => {
onClose(false);
};
return (
<div className="containers">
<ModalDialog
title=""
isOpen={isOpen}
onClose={handleClose}
onClose={onClose}
hasCloseButton={false}
isFullscreenScroll
>
Expand All @@ -29,9 +26,9 @@ export const ModalView = ({
</ModalDialog.Title>
</ModalDialog.Header>
<ModalDialog.Body>
<div className="modal-continer">
<div>
<p className="mt-2">{formatMessage(messages.recommendationsFeatureText)}</p>
<p>{formatMessage(messages.recommendationsAlertedText)}</p>
<p>{formatMessage(messages.recommendationsAlertText)}</p>
</div>
</ModalDialog.Body>
<ModalDialog.Footer>
Expand All @@ -49,11 +46,10 @@ export const ModalView = ({

ModalView.defaultProps = {
isOpen: false,
onClose: () => {},
};

ModalView.propTypes = {
onClose: PropTypes.func,
onClose: PropTypes.func.isRequired,
isOpen: PropTypes.bool,
};

Expand Down
16 changes: 16 additions & 0 deletions src/components/ModalView/index.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { shallow } from 'enzyme';

import ModalView from '.';

describe('ModalView', () => {
const props = {
isOpen: true,
onClose: jest.fn(),
};
describe('snapshot', () => {
test('renders default ModalView', () => {
const wrapper = shallow(<ModalView {...props} />);
expect(wrapper).toMatchSnapshot();
});
});
});
4 changes: 2 additions & 2 deletions src/components/ModalView/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ const messages = defineMessages({
defaultMessage: 'Personalized recommendations feature is not yet available. We are working hard on bringing it to your learner home in the near future.',
description: 'recommendations feature text',
},
recommendationsAlertedText: {
id: 'RecommendationsPanel.recommendationsAlertedText',
recommendationsAlertText: {
id: 'RecommendationsPanel.recommendationsAlertText',
defaultMessage: 'Would you like to be alerted when it becomes available?',
description: 'recommendations alerted text',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,17 @@ import { reduxHooks } from 'hooks';
import useActionDisabledState from '../hooks';
import ActionButton from './ActionButton';
import messages from './messages';
import { useEnterpriseDashboardData } from '../../../../data/redux/hooks/app';

export const BeginCourseButton = ({ cardId }) => {
const { formatMessage } = useIntl();
const { homeUrl } = reduxHooks.useCardCourseRunData(cardId);
const execEdTrackingParam = reduxHooks.useCardExecEdTrackingParam(cardId);
const { disableBeginCourse } = useActionDisabledState(cardId);

const { authOrgId } = useEnterpriseDashboardData();
const { isExecutiveEd2uCourse } = useActionDisabledState(cardId);
const execEdURLParam = `?org_id=${authOrgId}`;
const handleClick = reduxHooks.useTrackCourseEvent(
track.course.enterCourseClicked,
cardId,
homeUrl + ((isExecutiveEd2uCourse && authOrgId) ? execEdURLParam : ''),
homeUrl + execEdTrackingParam,
);
return (
<ActionButton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,22 @@ jest.mock('tracking', () => ({

jest.mock('hooks', () => ({
reduxHooks: {
useCardCourseRunData: jest.fn(() => ({ homeUrl: 'home-url' })),
useTrackCourseEvent: jest.fn(
(eventName, cardId, upgradeUrl) => ({ trackCourseEvent: { eventName, cardId, upgradeUrl } }),
),
useCardCourseRunData: jest.fn(),
useCardExecEdTrackingParam: jest.fn(),
useTrackCourseEvent: jest.fn(),
},
}));
jest.mock('../hooks', () => jest.fn(() => ({ disableBeginCourse: false })));
jest.mock('./ActionButton', () => 'ActionButton');

let wrapper;
const { homeUrl } = reduxHooks.useCardCourseRunData();
const homeUrl = 'home-url';
reduxHooks.useCardCourseRunData.mockReturnValue({ homeUrl });
const execEdPath = (cardId) => `exec-ed-tracking-path=${cardId}`;
reduxHooks.useCardExecEdTrackingParam.mockImplementation(execEdPath);
reduxHooks.useTrackCourseEvent.mockImplementation(
(eventName, cardId, upgradeUrl) => ({ trackCourseEvent: { eventName, cardId, upgradeUrl } }),
);

describe('BeginCourseButton', () => {
const props = {
Expand All @@ -33,27 +38,50 @@ describe('BeginCourseButton', () => {
beforeEach(() => {
jest.clearAllMocks();
});
describe('snapshot', () => {
test('renders default button when learner has access to the course', () => {
wrapper = shallow(<BeginCourseButton {...props} />);
expect(wrapper).toMatchSnapshot();
expect(wrapper.prop(htmlProps.disabled)).toEqual(false);
expect(wrapper.prop(htmlProps.onClick)).toEqual(reduxHooks.useTrackCourseEvent(
track.course.enterCourseClicked,
props.cardId,
homeUrl,
));
});
});
describe('behavior', () => {
it('initializes course run data with cardId', () => {
wrapper = shallow(<BeginCourseButton {...props} />);
expect(reduxHooks.useCardCourseRunData).toHaveBeenCalledWith(props.cardId);
});
test('disabled states', () => {
useActionDisabledState.mockReturnValueOnce({ disableBeginCourse: true });
it('loads exec education path param', () => {
wrapper = shallow(<BeginCourseButton {...props} />);
expect(reduxHooks.useCardExecEdTrackingParam).toHaveBeenCalledWith(props.cardId);
});
it('loads disabled states for begin action from action hooks', () => {
wrapper = shallow(<BeginCourseButton {...props} />);
expect(wrapper.prop(htmlProps.disabled)).toEqual(true);
expect(useActionDisabledState).toHaveBeenCalledWith(props.cardId);
});
});
describe('snapshot', () => {
describe('disabled', () => {
beforeEach(() => {
useActionDisabledState.mockReturnValueOnce({ disableBeginCourse: true });
wrapper = shallow(<BeginCourseButton {...props} />);
});
test('snapshot', () => {
expect(wrapper).toMatchSnapshot();
});
it('should be disabled', () => {
expect(wrapper.prop(htmlProps.disabled)).toEqual(true);
});
});
describe('enabled', () => {
beforeEach(() => {
wrapper = shallow(<BeginCourseButton {...props} />);
});
test('snapshot', () => {
expect(wrapper).toMatchSnapshot();
});
it('should be enabled', () => {
expect(wrapper.prop(htmlProps.disabled)).toEqual(false);
});
it('should track enter course clicked event on click, with exec ed param', () => {
expect(wrapper.prop(htmlProps.onClick)).toEqual(reduxHooks.useTrackCourseEvent(
track.course.enterCourseClicked,
props.cardId,
homeUrl + execEdPath(props.cardId),
));
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,17 @@ import { reduxHooks } from 'hooks';
import useActionDisabledState from '../hooks';
import ActionButton from './ActionButton';
import messages from './messages';
import { useEnterpriseDashboardData } from '../../../../data/redux/hooks/app';

export const ResumeButton = ({ cardId }) => {
const { formatMessage } = useIntl();
const { resumeUrl } = reduxHooks.useCardCourseRunData(cardId);
const execEdTrackingParam = reduxHooks.useCardExecEdTrackingParam(cardId);
const { disableResumeCourse } = useActionDisabledState(cardId);

const { authOrgId } = useEnterpriseDashboardData();
const { isExecutiveEd2uCourse } = useActionDisabledState(cardId);
const execEdURLParam = `?org_id=${authOrgId}`;
const handleClick = reduxHooks.useTrackCourseEvent(
track.course.enterCourseClicked,
cardId,
resumeUrl + ((isExecutiveEd2uCourse && authOrgId) ? execEdURLParam : ''),
resumeUrl + execEdTrackingParam,
);
return (
<ActionButton
Expand Down
Loading

0 comments on commit 4ee6543

Please sign in to comment.