feat: tracking upgrade and discovery (#66)
This commit is contained in:
@@ -5,6 +5,7 @@ import { Locked } from '@edx/paragon/icons';
|
|||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
|
|
||||||
import { hooks } from 'data/redux';
|
import { hooks } from 'data/redux';
|
||||||
|
import useTrackUpgradeData from './hooks';
|
||||||
import ActionButton from './ActionButton';
|
import ActionButton from './ActionButton';
|
||||||
import messages from './messages';
|
import messages from './messages';
|
||||||
|
|
||||||
@@ -14,11 +15,14 @@ export const UpgradeButton = ({ cardId }) => {
|
|||||||
const { isMasquerading } = hooks.useMasqueradeData();
|
const { isMasquerading } = hooks.useMasqueradeData();
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const isEnabled = (!isMasquerading && canUpgrade);
|
const isEnabled = (!isMasquerading && canUpgrade);
|
||||||
|
const { trackUpgradeClick } = useTrackUpgradeData();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ActionButton
|
<ActionButton
|
||||||
iconBefore={Locked}
|
iconBefore={Locked}
|
||||||
variant="outline-primary"
|
variant="outline-primary"
|
||||||
disabled={!isEnabled}
|
disabled={!isEnabled}
|
||||||
|
onClick={trackUpgradeClick}
|
||||||
{...isEnabled && { as: 'a', href: upgradeUrl }}
|
{...isEnabled && { as: 'a', href: upgradeUrl }}
|
||||||
>
|
>
|
||||||
{formatMessage(messages.upgrade)}
|
{formatMessage(messages.upgrade)}
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ jest.mock('data/redux', () => ({
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
jest.mock('./ActionButton', () => 'ActionButton');
|
jest.mock('./ActionButton', () => 'ActionButton');
|
||||||
|
jest.mock('./hooks', () => () => ({
|
||||||
|
trackUpgradeClick: jest.fn().mockName('trackUpgradeClick'),
|
||||||
|
}));
|
||||||
|
|
||||||
describe('UpgradeButton', () => {
|
describe('UpgradeButton', () => {
|
||||||
const props = {
|
const props = {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ exports[`UpgradeButton snapshot can upgrade 1`] = `
|
|||||||
disabled={false}
|
disabled={false}
|
||||||
href="upgradeUrl"
|
href="upgradeUrl"
|
||||||
iconBefore={[MockFunction icons.Locked]}
|
iconBefore={[MockFunction icons.Locked]}
|
||||||
|
onClick={[MockFunction trackUpgradeClick]}
|
||||||
variant="outline-primary"
|
variant="outline-primary"
|
||||||
>
|
>
|
||||||
Upgrade
|
Upgrade
|
||||||
@@ -16,6 +17,7 @@ exports[`UpgradeButton snapshot cannot upgrade 1`] = `
|
|||||||
<ActionButton
|
<ActionButton
|
||||||
disabled={true}
|
disabled={true}
|
||||||
iconBefore={[MockFunction icons.Locked]}
|
iconBefore={[MockFunction icons.Locked]}
|
||||||
|
onClick={[MockFunction trackUpgradeClick]}
|
||||||
variant="outline-primary"
|
variant="outline-primary"
|
||||||
>
|
>
|
||||||
Upgrade
|
Upgrade
|
||||||
@@ -26,6 +28,7 @@ exports[`UpgradeButton snapshot masquerading 1`] = `
|
|||||||
<ActionButton
|
<ActionButton
|
||||||
disabled={true}
|
disabled={true}
|
||||||
iconBefore={[MockFunction icons.Locked]}
|
iconBefore={[MockFunction icons.Locked]}
|
||||||
|
onClick={[MockFunction trackUpgradeClick]}
|
||||||
variant="outline-primary"
|
variant="outline-primary"
|
||||||
>
|
>
|
||||||
Upgrade
|
Upgrade
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { handleEvent } from 'data/services/segment/utils';
|
||||||
|
import { eventNames } from 'data/services/segment/constants';
|
||||||
|
|
||||||
|
export const useTrackUpgradeData = () => {
|
||||||
|
const trackUpgradeClick = () => {
|
||||||
|
handleEvent(eventNames.upgradeCourse, {
|
||||||
|
pageName: 'learner_home',
|
||||||
|
linkType: 'button',
|
||||||
|
linkCategory: 'green_upgrade',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
trackUpgradeClick,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useTrackUpgradeData;
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { handleEvent } from 'data/services/segment/utils';
|
||||||
|
import { eventNames } from 'data/services/segment/constants';
|
||||||
|
import * as hooks from './hooks';
|
||||||
|
|
||||||
|
jest.mock('data/services/segment/utils', () => ({
|
||||||
|
handleEvent: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('CourseCardActions hooks', () => {
|
||||||
|
describe('useTrackUpgradeData', () => {
|
||||||
|
it('calls handleEvent with correct params', () => {
|
||||||
|
const out = hooks.useTrackUpgradeData();
|
||||||
|
out.trackUpgradeClick();
|
||||||
|
expect(handleEvent).toHaveBeenCalledWith(eventNames.upgradeCourse, {
|
||||||
|
pageName: 'learner_home',
|
||||||
|
linkType: 'button',
|
||||||
|
linkCategory: 'green_upgrade',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -5,10 +5,12 @@ export const events = StrictDict({
|
|||||||
entitlementUnenroll: 'entitlementUnenroll',
|
entitlementUnenroll: 'entitlementUnenroll',
|
||||||
sessionChange: 'sessionChange',
|
sessionChange: 'sessionChange',
|
||||||
unenrollReason: 'unenrollReason',
|
unenrollReason: 'unenrollReason',
|
||||||
|
upgradeCourse: 'upgradeCourse',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const eventNames = StrictDict({
|
export const eventNames = StrictDict({
|
||||||
[events.courseEnroll]: 'edx.bi.user.program-details.enrollment',
|
[events.courseEnroll]: 'edx.bi.user.program-details.enrollment',
|
||||||
|
[events.upgradeCourse]: 'learner_home.course_card.upgrade',
|
||||||
[events.entitlementUnenroll]: 'entitlement_unenrollment_reason.selected',
|
[events.entitlementUnenroll]: 'entitlement_unenrollment_reason.selected',
|
||||||
[events.sessionChange]: ({ action }) => `course-dashboard.${action}-session`, // 'switch', 'new', 'leave'
|
[events.sessionChange]: ({ action }) => `course-dashboard.${action}-session`, // 'switch', 'new', 'leave'
|
||||||
[events.unenrollReason]: 'unenrollment_reason.selected',
|
[events.unenrollReason]: 'unenrollment_reason.selected',
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ exports[`LookingForChallengeWidget snapshots default 1`] = `
|
|||||||
<Hyperlink
|
<Hyperlink
|
||||||
className="d-flex align-items-center"
|
className="d-flex align-items-center"
|
||||||
destination="course-search-url"
|
destination="course-search-url"
|
||||||
|
onClick={[MockFunction courseSearchClickTracker]}
|
||||||
variant="brand"
|
variant="brand"
|
||||||
>
|
>
|
||||||
<format-message-function
|
<format-message-function
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
import { Card, Hyperlink, Icon } from '@edx/paragon';
|
import { Card, Hyperlink, Icon } from '@edx/paragon';
|
||||||
import { ArrowForward } from '@edx/paragon/icons';
|
import { ArrowForward } from '@edx/paragon/icons';
|
||||||
@@ -11,9 +13,11 @@ import './index.scss';
|
|||||||
|
|
||||||
export const arrowIcon = (<Icon className="mx-1" src={ArrowForward} />);
|
export const arrowIcon = (<Icon className="mx-1" src={ArrowForward} />);
|
||||||
|
|
||||||
export const LookingForChallengeWidget = () => {
|
export const LookingForChallengeWidget = ({
|
||||||
const { formatMessage } = useIntl();
|
courseSearchClickTracker,
|
||||||
|
}) => {
|
||||||
const { courseSearchUrl } = hooks.usePlatformSettingsData();
|
const { courseSearchUrl } = hooks.usePlatformSettingsData();
|
||||||
|
const { formatMessage } = useIntl();
|
||||||
return (
|
return (
|
||||||
<Card orientation="horizontal" id="looking-for-challenge-widget">
|
<Card orientation="horizontal" id="looking-for-challenge-widget">
|
||||||
<Card.ImageCap
|
<Card.ImageCap
|
||||||
@@ -25,7 +29,12 @@ export const LookingForChallengeWidget = () => {
|
|||||||
{formatMessage(messages.lookingForChallengePrompt)}
|
{formatMessage(messages.lookingForChallengePrompt)}
|
||||||
</h4>
|
</h4>
|
||||||
<h5>
|
<h5>
|
||||||
<Hyperlink variant="brand" destination={courseSearchUrl} className="d-flex align-items-center">
|
<Hyperlink
|
||||||
|
variant="brand"
|
||||||
|
destination={courseSearchUrl}
|
||||||
|
onClick={courseSearchClickTracker}
|
||||||
|
className="d-flex align-items-center"
|
||||||
|
>
|
||||||
{formatMessage(messages.findCoursesButton, { arrow: arrowIcon })}
|
{formatMessage(messages.findCoursesButton, { arrow: arrowIcon })}
|
||||||
</Hyperlink>
|
</Hyperlink>
|
||||||
</h5>
|
</h5>
|
||||||
@@ -34,4 +43,8 @@ export const LookingForChallengeWidget = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
LookingForChallengeWidget.propTypes = {
|
||||||
|
courseSearchClickTracker: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
export default LookingForChallengeWidget;
|
export default LookingForChallengeWidget;
|
||||||
|
|||||||
@@ -11,9 +11,12 @@ jest.mock('data/redux', () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
describe('LookingForChallengeWidget', () => {
|
describe('LookingForChallengeWidget', () => {
|
||||||
|
const props = {
|
||||||
|
courseSearchClickTracker: jest.fn().mockName('courseSearchClickTracker'),
|
||||||
|
};
|
||||||
describe('snapshots', () => {
|
describe('snapshots', () => {
|
||||||
test('default', () => {
|
test('default', () => {
|
||||||
const wrapper = shallow(<LookingForChallengeWidget />);
|
const wrapper = shallow(<LookingForChallengeWidget {...props} />);
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import './index.scss';
|
|||||||
|
|
||||||
export const LoadedView = ({
|
export const LoadedView = ({
|
||||||
courses,
|
courses,
|
||||||
|
courseSearchClickTracker,
|
||||||
}) => {
|
}) => {
|
||||||
const { courseSearchUrl } = hooks.usePlatformSettingsData();
|
const { courseSearchUrl } = hooks.usePlatformSettingsData();
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
@@ -31,6 +32,7 @@ export const LoadedView = ({
|
|||||||
iconBefore={Search}
|
iconBefore={Search}
|
||||||
as="a"
|
as="a"
|
||||||
href={courseSearchUrl}
|
href={courseSearchUrl}
|
||||||
|
onClick={courseSearchClickTracker}
|
||||||
>
|
>
|
||||||
{formatMessage(messages.exploreCoursesButton)}
|
{formatMessage(messages.exploreCoursesButton)}
|
||||||
</Button>
|
</Button>
|
||||||
@@ -46,6 +48,7 @@ LoadedView.propTypes = {
|
|||||||
logoImageUrl: PropTypes.string,
|
logoImageUrl: PropTypes.string,
|
||||||
marketingUrl: PropTypes.string,
|
marketingUrl: PropTypes.string,
|
||||||
})).isRequired,
|
})).isRequired,
|
||||||
|
courseSearchClickTracker: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LoadedView;
|
export default LoadedView;
|
||||||
|
|||||||
@@ -1,22 +1,24 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import { hooks } from 'data/redux';
|
|
||||||
import LoadedView from './LoadedView';
|
import LoadedView from './LoadedView';
|
||||||
import mockData from './mockData';
|
import mockData from './mockData';
|
||||||
|
|
||||||
jest.mock('./components/CourseCard', () => 'CourseCard');
|
jest.mock('./components/CourseCard', () => 'CourseCard');
|
||||||
jest.mock('data/redux', () => ({
|
jest.mock('data/redux', () => ({
|
||||||
hooks: {
|
hooks: {
|
||||||
usePlatformSettingsData: jest.fn(),
|
usePlatformSettingsData: () => ({
|
||||||
|
courseSearchUrl: 'course-search-url',
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const courseSearchUrl = 'test-course-search-url';
|
|
||||||
hooks.usePlatformSettingsData.mockReturnValue(courseSearchUrl);
|
|
||||||
|
|
||||||
describe('RecommendationsPanel LoadedView', () => {
|
describe('RecommendationsPanel LoadedView', () => {
|
||||||
|
const props = {
|
||||||
|
courses: mockData.courses,
|
||||||
|
courseSearchClickTracker: jest.fn().mockName('courseSearchClickTracker'),
|
||||||
|
};
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(shallow(<LoadedView courses={mockData.courses} />)).toMatchSnapshot();
|
expect(shallow(<LoadedView {...props} />)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ exports[`RecommendationsPanel LoadedView snapshot 1`] = `
|
|||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
as="a"
|
as="a"
|
||||||
|
href="course-search-url"
|
||||||
|
onClick={[MockFunction courseSearchClickTracker]}
|
||||||
variant="tertiary"
|
variant="tertiary"
|
||||||
>
|
>
|
||||||
Explore courses
|
Explore courses
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ import React from 'react';
|
|||||||
|
|
||||||
import { StrictDict } from 'utils';
|
import { StrictDict } from 'utils';
|
||||||
import { RequestStates } from 'data/constants/requests';
|
import { RequestStates } from 'data/constants/requests';
|
||||||
|
import { handleEvent } from 'data/services/segment/utils';
|
||||||
|
|
||||||
import * as module from './hooks';
|
import * as module from './hooks';
|
||||||
import api from './api';
|
import api from './api';
|
||||||
|
|
||||||
|
export const searchCourseEventName = 'learner_home.widget.search_course';
|
||||||
|
|
||||||
export const state = StrictDict({
|
export const state = StrictDict({
|
||||||
requestState: (val) => React.useState(val), // eslint-disable-line
|
requestState: (val) => React.useState(val), // eslint-disable-line
|
||||||
data: (val) => React.useState(val), // eslint-disable-line
|
data: (val) => React.useState(val), // eslint-disable-line
|
||||||
@@ -34,12 +37,18 @@ export const useRecommendationPanelData = () => {
|
|||||||
const [data, setData] = module.state.data({});
|
const [data, setData] = module.state.data({});
|
||||||
module.useFetchCourses(setRequestState, setData);
|
module.useFetchCourses(setRequestState, setData);
|
||||||
const courses = data.data?.courses || [];
|
const courses = data.data?.courses || [];
|
||||||
|
const courseSearchClickTracker = () => handleEvent(searchCourseEventName, {
|
||||||
|
pageName: 'learner_home',
|
||||||
|
linkType: 'button',
|
||||||
|
linkCategory: 'search_button',
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
courses,
|
courses,
|
||||||
isLoaded: requestState === RequestStates.completed && courses.length > 0,
|
isLoaded: requestState === RequestStates.completed && courses.length > 0,
|
||||||
isFailed: requestState === RequestStates.failed
|
isFailed: requestState === RequestStates.failed
|
||||||
|| (requestState === RequestStates.completed && courses.length === 0),
|
|| (requestState === RequestStates.completed && courses.length === 0),
|
||||||
isLoading: requestState === RequestStates.pending,
|
isLoading: requestState === RequestStates.pending,
|
||||||
|
courseSearchClickTracker,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import React from 'react';
|
|||||||
|
|
||||||
import { MockUseState } from 'testUtils';
|
import { MockUseState } from 'testUtils';
|
||||||
import { RequestStates } from 'data/constants/requests';
|
import { RequestStates } from 'data/constants/requests';
|
||||||
|
import { handleEvent } from 'data/services/segment/utils';
|
||||||
|
|
||||||
import api from './api';
|
import api from './api';
|
||||||
import * as hooks from './hooks';
|
import * as hooks from './hooks';
|
||||||
@@ -9,6 +10,9 @@ import * as hooks from './hooks';
|
|||||||
jest.mock('./api', () => ({
|
jest.mock('./api', () => ({
|
||||||
fetchRecommendedCourses: jest.fn(),
|
fetchRecommendedCourses: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
jest.mock('data/services/segment/utils', () => ({
|
||||||
|
handleEvent: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
const state = new MockUseState(hooks);
|
const state = new MockUseState(hooks);
|
||||||
|
|
||||||
@@ -96,6 +100,16 @@ describe('RecommendationsPanel hooks', () => {
|
|||||||
it('initializes requestState as RequestStates.pending', () => {
|
it('initializes requestState as RequestStates.pending', () => {
|
||||||
state.expectInitializedWith(state.keys.requestState, RequestStates.pending);
|
state.expectInitializedWith(state.keys.requestState, RequestStates.pending);
|
||||||
});
|
});
|
||||||
|
describe('courseSearchClickTracker behavior', () => {
|
||||||
|
it('calls handleEvent with correct args', () => {
|
||||||
|
out.courseSearchClickTracker();
|
||||||
|
expect(handleEvent).toHaveBeenCalledWith(hooks.searchCourseEventName, {
|
||||||
|
pageName: 'learner_home',
|
||||||
|
linkType: 'button',
|
||||||
|
linkCategory: 'search_button',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
describe('output', () => {
|
describe('output', () => {
|
||||||
describe('request is completed, with returned courses', () => {
|
describe('request is completed, with returned courses', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|||||||
@@ -11,19 +11,20 @@ export const RecommendationsPanel = () => {
|
|||||||
isFailed,
|
isFailed,
|
||||||
isLoaded,
|
isLoaded,
|
||||||
isLoading,
|
isLoading,
|
||||||
|
courseSearchClickTracker,
|
||||||
} = hooks.useRecommendationPanelData();
|
} = hooks.useRecommendationPanelData();
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (<LoadingView />);
|
return (<LoadingView />);
|
||||||
}
|
}
|
||||||
if (isLoaded) {
|
if (isLoaded) {
|
||||||
return (<LoadedView courses={courses} />);
|
return (<LoadedView courses={courses} courseSearchClickTracker={courseSearchClickTracker} />);
|
||||||
}
|
}
|
||||||
if (isFailed) {
|
if (isFailed) {
|
||||||
return (<LookingForChallengeWidget />);
|
return (<LookingForChallengeWidget courseSearchClickTracker={courseSearchClickTracker} />);
|
||||||
}
|
}
|
||||||
// default fallback
|
// default fallback
|
||||||
return (<LookingForChallengeWidget />);
|
return (<LookingForChallengeWidget courseSearchClickTracker={courseSearchClickTracker} />);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default RecommendationsPanel;
|
export default RecommendationsPanel;
|
||||||
|
|||||||
@@ -18,46 +18,48 @@ jest.mock('./LoadedView', () => 'LoadedView');
|
|||||||
const { courses } = mockData;
|
const { courses } = mockData;
|
||||||
|
|
||||||
describe('RecommendationsPanel snapshot', () => {
|
describe('RecommendationsPanel snapshot', () => {
|
||||||
|
const defaultProps = {
|
||||||
|
courseSearchClickTracker: jest.fn().mockName('courseSearchClickTracker'),
|
||||||
|
};
|
||||||
|
const defaultValues = {
|
||||||
|
isFailed: false,
|
||||||
|
isLoaded: false,
|
||||||
|
isLoading: false,
|
||||||
|
courses: [],
|
||||||
|
...defaultProps,
|
||||||
|
};
|
||||||
it('displays LoadingView if request is loading', () => {
|
it('displays LoadingView if request is loading', () => {
|
||||||
hooks.useRecommendationPanelData.mockReturnValueOnce({
|
hooks.useRecommendationPanelData.mockReturnValueOnce({
|
||||||
courses: [],
|
...defaultValues,
|
||||||
isFailed: false,
|
|
||||||
isLoaded: false,
|
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
});
|
});
|
||||||
expect(shallow(<RecommendationsPanel />)).toMatchObject(shallow(<LoadingView />));
|
expect(shallow(<RecommendationsPanel />)).toMatchObject(shallow(<LoadingView />));
|
||||||
});
|
});
|
||||||
it('displays LoadedView with courses if request is loaded', () => {
|
it('displays LoadedView with courses if request is loaded', () => {
|
||||||
hooks.useRecommendationPanelData.mockReturnValueOnce({
|
hooks.useRecommendationPanelData.mockReturnValueOnce({
|
||||||
|
...defaultValues,
|
||||||
courses,
|
courses,
|
||||||
isFailed: false,
|
|
||||||
isLoaded: true,
|
isLoaded: true,
|
||||||
isLoading: false,
|
|
||||||
});
|
});
|
||||||
expect(shallow(<RecommendationsPanel />)).toMatchObject(
|
expect(shallow(<RecommendationsPanel />)).toMatchObject(
|
||||||
shallow(<LoadedView courses={courses} />),
|
shallow(<LoadedView courses={courses} {...defaultProps} />),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('displays LookingForChallengeWidget if request is failed', () => {
|
it('displays LookingForChallengeWidget if request is failed', () => {
|
||||||
hooks.useRecommendationPanelData.mockReturnValueOnce({
|
hooks.useRecommendationPanelData.mockReturnValueOnce({
|
||||||
courses: [],
|
...defaultValues,
|
||||||
isFailed: true,
|
isFailed: true,
|
||||||
isLoaded: false,
|
|
||||||
isLoading: false,
|
|
||||||
});
|
});
|
||||||
expect(shallow(<RecommendationsPanel />)).toMatchObject(
|
expect(shallow(<RecommendationsPanel />)).toMatchObject(
|
||||||
shallow(<LookingForChallengeWidget />),
|
shallow(<LookingForChallengeWidget {...defaultProps} />),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('defaults to LookingForChallengeWidget if no flags are true', () => {
|
it('defaults to LookingForChallengeWidget if no flags are true', () => {
|
||||||
hooks.useRecommendationPanelData.mockReturnValueOnce({
|
hooks.useRecommendationPanelData.mockReturnValueOnce({
|
||||||
courses: [],
|
...defaultValues,
|
||||||
isFailed: false,
|
|
||||||
isLoaded: false,
|
|
||||||
isLoading: false,
|
|
||||||
});
|
});
|
||||||
expect(shallow(<RecommendationsPanel />)).toMatchObject(
|
expect(shallow(<RecommendationsPanel />)).toMatchObject(
|
||||||
shallow(<LookingForChallengeWidget />),
|
shallow(<LookingForChallengeWidget {...defaultProps} />),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user