Merge branch 'master' of https://github.com/openedx/frontend-app-learner-dashboard into mashal-m/replace-edx/paragon-frontend-build
This commit is contained in:
@@ -1,129 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { StrictDict } from 'utils';
|
||||
import * as module from './PaintedDoorExperimentContext';
|
||||
import {
|
||||
useEmailConfirmationData,
|
||||
useHasAvailableDashboards,
|
||||
useRequestIsPending,
|
||||
} from '../../data/redux/hooks';
|
||||
import { RequestKeys } from '../../data/constants/requests';
|
||||
import { trackPaintedDoorVariationGroup } from './track';
|
||||
|
||||
export const state = StrictDict({
|
||||
enterpriseUser: (val) => React.useState(val), // eslint-disable-line
|
||||
experimentData: (val) => React.useState(val), // eslint-disable-line
|
||||
});
|
||||
|
||||
const PAINTED_DOOR_RECOMMENDATIONS_EXP_ID = 25116810832;
|
||||
const PAINTED_DOOR_RECOMMENDATIONS_PAGE = 'url_targeting_for_van1604_recommendations_painted_door_exp';
|
||||
const PAINTED_DOOR_RECS_EXP_NAVBAR_BTN_VARIATION = 'btn_navbar';
|
||||
const PAINTED_DOOR_RECS_EXP_WIDGET_BTN_VARIATION = 'btn_widget';
|
||||
const PAINTED_DOOR_RECS_EXP_CONTROL_VARIATION = 'control';
|
||||
|
||||
export function getPaintedDoorRecommendationsExperimentVariation() {
|
||||
try {
|
||||
if (window.optimizely && window.optimizely.get('data').experiments[PAINTED_DOOR_RECOMMENDATIONS_EXP_ID]) {
|
||||
const selectedVariant = window.optimizely.get('state').getVariationMap()[PAINTED_DOOR_RECOMMENDATIONS_EXP_ID];
|
||||
return selectedVariant?.name;
|
||||
}
|
||||
} catch (e) { /* empty */ }
|
||||
return '';
|
||||
}
|
||||
|
||||
export function activatePaintedDoorRecommendationsExperiment() {
|
||||
window.optimizely = window.optimizely || [];
|
||||
window.optimizely.push({
|
||||
type: 'page',
|
||||
pageName: PAINTED_DOOR_RECOMMENDATIONS_PAGE,
|
||||
});
|
||||
}
|
||||
|
||||
export const useIsEnterpriseUser = () => {
|
||||
const [enterpriseUser, setEnterpriseUser] = module.state.enterpriseUser({
|
||||
isEnterpriseUser: false,
|
||||
isLoading: true,
|
||||
});
|
||||
|
||||
const initIsPending = useRequestIsPending(RequestKeys.initialize);
|
||||
const hasAvailableDashboards = useHasAvailableDashboards();
|
||||
const confirmationData = useEmailConfirmationData();
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!initIsPending && Object.keys(confirmationData).length && hasAvailableDashboards) {
|
||||
setEnterpriseUser(prev => ({
|
||||
...prev,
|
||||
isEnterpriseUser: true,
|
||||
isLoading: false,
|
||||
}));
|
||||
} else if (!initIsPending && Object.keys(confirmationData).length && !hasAvailableDashboards) {
|
||||
setEnterpriseUser(prev => ({
|
||||
...prev,
|
||||
isEnterpriseUser: false,
|
||||
isLoading: false,
|
||||
}));
|
||||
}
|
||||
}, [initIsPending]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
return enterpriseUser;
|
||||
};
|
||||
|
||||
export const PaintedDoorExperimentContext = React.createContext({
|
||||
experimentVariation: null,
|
||||
isPaintedDoorNavbarBtnVariation: null,
|
||||
isPaintedDoorWidgetBtnVariation: null,
|
||||
isPaintedDoorControlVariation: null,
|
||||
experimentLoading: null,
|
||||
});
|
||||
|
||||
export const PaintedDoorExperimentProvider = ({ children }) => {
|
||||
const [experimentData, setExperimentData] = module.state.experimentData({
|
||||
experimentVariation: '',
|
||||
isPaintedDoorNavbarBtnVariation: false,
|
||||
isPaintedDoorWidgetBtnVariation: false,
|
||||
isPaintedDoorControlVariation: false,
|
||||
experimentLoading: true,
|
||||
});
|
||||
const enterpriseUser = useIsEnterpriseUser();
|
||||
|
||||
const contextValue = React.useMemo(
|
||||
() => ({
|
||||
...experimentData,
|
||||
}),
|
||||
[experimentData],
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
let timer = null;
|
||||
if (!enterpriseUser.isLoading && !enterpriseUser.isEnterpriseUser) {
|
||||
activatePaintedDoorRecommendationsExperiment();
|
||||
timer = setTimeout(() => {
|
||||
const variation = getPaintedDoorRecommendationsExperimentVariation();
|
||||
setExperimentData(prev => ({
|
||||
...prev,
|
||||
experimentVariation: variation,
|
||||
isPaintedDoorNavbarBtnVariation: variation === PAINTED_DOOR_RECS_EXP_NAVBAR_BTN_VARIATION,
|
||||
isPaintedDoorWidgetBtnVariation: variation === PAINTED_DOOR_RECS_EXP_WIDGET_BTN_VARIATION,
|
||||
isPaintedDoorControlVariation: variation === PAINTED_DOOR_RECS_EXP_CONTROL_VARIATION,
|
||||
experimentLoading: false,
|
||||
}));
|
||||
trackPaintedDoorVariationGroup(variation);
|
||||
}, 500);
|
||||
}
|
||||
return () => clearTimeout(timer);
|
||||
}, [enterpriseUser]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
return (
|
||||
<PaintedDoorExperimentContext.Provider value={contextValue}>
|
||||
{children}
|
||||
</PaintedDoorExperimentContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const usePaintedDoorExperimentContext = () => React.useContext(PaintedDoorExperimentContext);
|
||||
|
||||
PaintedDoorExperimentProvider.propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
};
|
||||
|
||||
export default PaintedDoorExperimentProvider;
|
||||
@@ -1,151 +0,0 @@
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
|
||||
import { MockUseState } from 'testUtils';
|
||||
|
||||
import * as experiment from './PaintedDoorExperimentContext';
|
||||
import { useEmailConfirmationData, useHasAvailableDashboards, useRequestIsPending } from '../../data/redux/hooks';
|
||||
import { trackPaintedDoorVariationGroup } from './track';
|
||||
import { useIsEnterpriseUser } from './PaintedDoorExperimentContext';
|
||||
|
||||
const state = new MockUseState(experiment);
|
||||
trackPaintedDoorVariationGroup();
|
||||
jest.unmock('react');
|
||||
jest.spyOn(React, 'useEffect').mockImplementation((cb, prereqs) => ({ useEffect: { cb, prereqs } }));
|
||||
|
||||
jest.mock('../../data/redux/hooks', () => ({
|
||||
useRequestIsPending: jest.fn(),
|
||||
useHasAvailableDashboards: jest.fn(),
|
||||
useEmailConfirmationData: jest.fn(),
|
||||
}));
|
||||
jest.mock('./track', () => ({
|
||||
trackPaintedDoorVariationGroup: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('useIsEnterpriseUser hook', () => {
|
||||
describe('state fields', () => {
|
||||
state.testGetter(state.keys.enterpriseUser);
|
||||
});
|
||||
describe('useIsEnterpriseUser', () => {
|
||||
beforeEach(() => {
|
||||
state.mock();
|
||||
useRequestIsPending.mockReturnValueOnce(false);
|
||||
useEmailConfirmationData.mockReturnValueOnce({ confirmed: true });
|
||||
});
|
||||
it('initializes enterpriseUser', () => {
|
||||
useIsEnterpriseUser();
|
||||
state.expectInitializedWith(state.keys.enterpriseUser, {
|
||||
isEnterpriseUser: false,
|
||||
isLoading: true,
|
||||
});
|
||||
});
|
||||
it('get isEnterpriseUser false if useHasAvailableDashboards return false', () => {
|
||||
useHasAvailableDashboards.mockReturnValueOnce(false);
|
||||
|
||||
state.mockVal(state.keys.enterpriseUser, {
|
||||
isEnterpriseUser: false,
|
||||
isLoading: false,
|
||||
});
|
||||
|
||||
const enterpriseUser = useIsEnterpriseUser();
|
||||
const [cb] = React.useEffect.mock.calls[0];
|
||||
cb();
|
||||
|
||||
expect(enterpriseUser.isEnterpriseUser).toEqual(false);
|
||||
expect(enterpriseUser.isLoading).toEqual(false);
|
||||
});
|
||||
it('get isEnterpriseUser true if useHasAvailableDashboards return true', () => {
|
||||
useHasAvailableDashboards.mockReturnValueOnce(true);
|
||||
|
||||
state.mockVal(state.keys.enterpriseUser, {
|
||||
isEnterpriseUser: true,
|
||||
isLoading: false,
|
||||
});
|
||||
|
||||
const enterpriseUser = useIsEnterpriseUser();
|
||||
const [cb] = React.useEffect.mock.calls[0];
|
||||
cb();
|
||||
|
||||
expect(enterpriseUser.isEnterpriseUser).toEqual(true);
|
||||
expect(enterpriseUser.isLoading).toEqual(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Painted door experiments context', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
describe('PaintedDoorExperimentProvider', () => {
|
||||
const { PaintedDoorExperimentProvider } = experiment;
|
||||
|
||||
const TestComponent = () => {
|
||||
const {
|
||||
experimentVariation,
|
||||
isPaintedDoorNavbarBtnVariation,
|
||||
isPaintedDoorWidgetBtnVariation,
|
||||
isPaintedDoorControlVariation,
|
||||
experimentLoading,
|
||||
} = experiment.usePaintedDoorExperimentContext();
|
||||
|
||||
expect(experimentVariation).toEqual('');
|
||||
expect(isPaintedDoorNavbarBtnVariation).toBe(false);
|
||||
expect(isPaintedDoorWidgetBtnVariation).toBe(false);
|
||||
expect(isPaintedDoorControlVariation).toBe(false);
|
||||
expect(experimentLoading).toBe(true);
|
||||
|
||||
return (
|
||||
<div />
|
||||
);
|
||||
};
|
||||
|
||||
it('test experiment gets activated for non enterprise users', () => {
|
||||
state.mock();
|
||||
jest.useFakeTimers();
|
||||
useRequestIsPending.mockReturnValueOnce(false);
|
||||
useHasAvailableDashboards.mockReturnValueOnce(false);
|
||||
useEmailConfirmationData.mockReturnValueOnce({ confirmed: true });
|
||||
|
||||
state.mockVal(state.keys.enterpriseUser, {
|
||||
isEnterpriseUser: false,
|
||||
isLoading: false,
|
||||
});
|
||||
|
||||
shallow(
|
||||
<PaintedDoorExperimentProvider>
|
||||
<TestComponent />
|
||||
</PaintedDoorExperimentProvider>,
|
||||
);
|
||||
const [cb] = React.useEffect.mock.calls[1];
|
||||
cb();
|
||||
jest.advanceTimersByTime(500);
|
||||
|
||||
expect(trackPaintedDoorVariationGroup).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('test experiment does not get activated for enterprise users', () => {
|
||||
state.mock();
|
||||
jest.useFakeTimers();
|
||||
useRequestIsPending.mockReturnValueOnce(false);
|
||||
useHasAvailableDashboards.mockReturnValueOnce(true);
|
||||
useEmailConfirmationData.mockReturnValueOnce({ confirmed: true });
|
||||
|
||||
state.mockVal(state.keys.enterpriseUser, {
|
||||
isEnterpriseUser: true,
|
||||
isLoading: false,
|
||||
});
|
||||
|
||||
shallow(
|
||||
<PaintedDoorExperimentProvider>
|
||||
<TestComponent />
|
||||
</PaintedDoorExperimentProvider>,
|
||||
);
|
||||
const [cb] = React.useEffect.mock.calls[1];
|
||||
cb();
|
||||
jest.advanceTimersByTime(500);
|
||||
|
||||
expect(trackPaintedDoorVariationGroup).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,14 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`RecommendationsPaintedDoorBtn matches snapshot 1`] = `
|
||||
<Fragment>
|
||||
<RecommendationsPanelButton
|
||||
handleClick={[Function]}
|
||||
/>
|
||||
<ModalView
|
||||
isOpen={false}
|
||||
onClose={[MockFunction]}
|
||||
variation=""
|
||||
/>
|
||||
</Fragment>
|
||||
`;
|
||||
@@ -1,31 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Button } from '@openedx/paragon';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import messages from '../messages';
|
||||
import { COLLAPSED_NAVBAR, EXPANDED_NAVBAR } from '../constants';
|
||||
|
||||
export const NavbarButton = ({ placement, handleClick }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
return (
|
||||
<Button
|
||||
as="a"
|
||||
className={classNames({
|
||||
'p-4': placement === EXPANDED_NAVBAR,
|
||||
})}
|
||||
variant="inverse-primary"
|
||||
onClick={handleClick}
|
||||
>
|
||||
{formatMessage(messages.recommendedForYou)}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
NavbarButton.propTypes = {
|
||||
placement: PropTypes.oneOf([COLLAPSED_NAVBAR, EXPANDED_NAVBAR]).isRequired,
|
||||
handleClick: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default NavbarButton;
|
||||
@@ -1,52 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ModalView snapshot should renders default ModalView 1`] = `
|
||||
<div
|
||||
className="containers modal-container"
|
||||
>
|
||||
<[object Object]
|
||||
hasCloseButton={false}
|
||||
isBlocking={true}
|
||||
isFullscreenScroll={true}
|
||||
isOpen={true}
|
||||
onClose={[MockFunction]}
|
||||
title=""
|
||||
>
|
||||
<ModalDialog.Header>
|
||||
<ModalDialog.Title
|
||||
className="mt-2"
|
||||
>
|
||||
Thank you for your interest!
|
||||
</ModalDialog.Title>
|
||||
</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>
|
||||
<ModalDialog.Footer>
|
||||
<ActionRow>
|
||||
<ModalDialog.CloseButton
|
||||
onClick={[Function]}
|
||||
variant="tertiary"
|
||||
>
|
||||
Skip for now
|
||||
</ModalDialog.CloseButton>
|
||||
<ModalDialog.CloseButton
|
||||
onClick={[Function]}
|
||||
variant="primary"
|
||||
>
|
||||
Count me in!
|
||||
</ModalDialog.CloseButton>
|
||||
</ActionRow>
|
||||
</ModalDialog.Footer>
|
||||
</[object Object]>
|
||||
</div>
|
||||
`;
|
||||
@@ -1,18 +0,0 @@
|
||||
import React from 'react';
|
||||
import { StrictDict } from 'utils';
|
||||
|
||||
import * as module from './hooks';
|
||||
|
||||
export const state = StrictDict({
|
||||
isModalOpen: (val) => React.useState(val), // eslint-disable-line
|
||||
});
|
||||
|
||||
export const usePaintedDoorModal = () => {
|
||||
const [isModalOpen, setIsModalOpen] = module.state.isModalOpen(false);
|
||||
const toggleModal = () => setIsModalOpen(!isModalOpen);
|
||||
|
||||
return {
|
||||
isModalOpen,
|
||||
toggleModal,
|
||||
};
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
import { MockUseState } from 'testUtils';
|
||||
|
||||
import * as hooks from './hooks';
|
||||
|
||||
const state = new MockUseState(hooks);
|
||||
|
||||
const {
|
||||
usePaintedDoorModal,
|
||||
} = hooks;
|
||||
|
||||
describe('LearnerDashboardHeader hooks', () => {
|
||||
describe('state fields', () => {
|
||||
state.testGetter(state.keys.isModalOpen);
|
||||
});
|
||||
describe('useRecommendationsModal', () => {
|
||||
beforeEach(() => {
|
||||
state.mock();
|
||||
});
|
||||
it('initializes isModalOpen with false', () => {
|
||||
usePaintedDoorModal();
|
||||
state.expectInitializedWith(state.keys.isModalOpen, false);
|
||||
});
|
||||
test('change isModalOpen value on toggle', () => {
|
||||
const out = usePaintedDoorModal();
|
||||
state.expectInitializedWith(state.keys.isModalOpen, false);
|
||||
out.toggleModal();
|
||||
expect(state.values.isModalOpen).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,70 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { ModalDialog, ActionRow } from '@openedx/paragon';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import messages from '../../messages';
|
||||
|
||||
import './index.scss';
|
||||
import {
|
||||
trackPaintedDoorRecommendationHomeInterestBtnClicked,
|
||||
trackPaintedDoorRecommendationHomeSkipBtnClicked,
|
||||
} from '../../track';
|
||||
|
||||
export const ModalView = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
variation,
|
||||
}) => {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const handleSkipBtnClick = () => trackPaintedDoorRecommendationHomeSkipBtnClicked(variation);
|
||||
const handleInterestBtnClick = () => trackPaintedDoorRecommendationHomeInterestBtnClicked(variation);
|
||||
|
||||
return (
|
||||
<div className="containers modal-container">
|
||||
<ModalDialog
|
||||
title=""
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
hasCloseButton={false}
|
||||
isFullscreenScroll
|
||||
isBlocking
|
||||
>
|
||||
<ModalDialog.Header>
|
||||
<ModalDialog.Title className="mt-2">
|
||||
{formatMessage(messages.recommendationsModalHeading)}
|
||||
</ModalDialog.Title>
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Body>
|
||||
<div>
|
||||
<p className="mt-2">{formatMessage(messages.recommendationsFeatureText)}</p>
|
||||
<p>{formatMessage(messages.recommendationsAlertText)}</p>
|
||||
</div>
|
||||
</ModalDialog.Body>
|
||||
<ModalDialog.Footer>
|
||||
<ActionRow>
|
||||
<ModalDialog.CloseButton variant="tertiary" onClick={handleSkipBtnClick}>
|
||||
{formatMessage(messages.modalSkipButton)}
|
||||
</ModalDialog.CloseButton>
|
||||
<ModalDialog.CloseButton variant="primary" onClick={handleInterestBtnClick}>
|
||||
{formatMessage(messages.modalCountMeButton)}
|
||||
</ModalDialog.CloseButton>
|
||||
</ActionRow>
|
||||
</ModalDialog.Footer>
|
||||
</ModalDialog>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ModalView.defaultProps = {
|
||||
isOpen: false,
|
||||
};
|
||||
|
||||
ModalView.propTypes = {
|
||||
onClose: PropTypes.func.isRequired,
|
||||
isOpen: PropTypes.bool,
|
||||
variation: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default ModalView;
|
||||
@@ -1,15 +0,0 @@
|
||||
@import "@openedx/paragon/scss/core/core";
|
||||
|
||||
.modal-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (max-width: 464px) {
|
||||
.pgn__action-row{
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
|
||||
import ModalView from '.';
|
||||
|
||||
jest.mock('../../track', () => ({
|
||||
trackPaintedDoorRecommendationHomeSkipBtnClicked: jest.fn(),
|
||||
trackPaintedDoorRecommendationHomeInterestBtnClicked: jest.fn(),
|
||||
}));
|
||||
jest.mock('@openedx/paragon', () => ({
|
||||
...jest.requireActual('@openedx/paragon'),
|
||||
ModalDialog: {
|
||||
Body: 'ModalDialog.Body',
|
||||
Header: 'ModalDialog.Header',
|
||||
Title: 'ModalDialog.Title',
|
||||
Footer: 'ModalDialog.Footer',
|
||||
CloseButton: 'ModalDialog.CloseButton',
|
||||
},
|
||||
ActionRow: 'ActionRow',
|
||||
}));
|
||||
|
||||
describe('ModalView', () => {
|
||||
const props = {
|
||||
isOpen: true,
|
||||
onClose: jest.fn(),
|
||||
variation: '',
|
||||
};
|
||||
describe('snapshot', () => {
|
||||
test('should renders default ModalView', () => {
|
||||
const wrapper = shallow(<ModalView {...props} />);
|
||||
expect(wrapper.snapshot).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,25 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Button } from '@openedx/paragon';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import PropTypes from 'prop-types';
|
||||
import messages from '../messages';
|
||||
|
||||
export const RecommendationsPanelButton = ({ handleClick }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
return (
|
||||
<Button
|
||||
as="a"
|
||||
variant="brand"
|
||||
onClick={handleClick}
|
||||
>
|
||||
{formatMessage(messages.seeAllRecommendationsButton)}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
RecommendationsPanelButton.propTypes = {
|
||||
handleClick: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default RecommendationsPanelButton;
|
||||
@@ -1,3 +0,0 @@
|
||||
export const COLLAPSED_NAVBAR = 'collapsedNavbar';
|
||||
export const EXPANDED_NAVBAR = 'expendedNavbar';
|
||||
export const RECOMMENDATIONS_PANEL = 'recommendationsPanel';
|
||||
@@ -1,44 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import NavbarButton from './components/NavbarButton';
|
||||
import PaintedDoorModal from './components/PaintedDoorModal';
|
||||
import { usePaintedDoorModal } from './components/PaintedDoorModal/hooks';
|
||||
import { COLLAPSED_NAVBAR, EXPANDED_NAVBAR, RECOMMENDATIONS_PANEL } from './constants';
|
||||
import RecommendationsPanelButton from './components/RecommendationsPanelButton';
|
||||
import { trackPaintedDoorRecommendationHomeBtnClicked } from './track';
|
||||
|
||||
export const RecommendationsPaintedDoorBtn = ({ placement, experimentVariation }) => {
|
||||
const { isModalOpen, toggleModal } = usePaintedDoorModal();
|
||||
|
||||
const handleClick = () => {
|
||||
toggleModal();
|
||||
trackPaintedDoorRecommendationHomeBtnClicked(experimentVariation);
|
||||
};
|
||||
|
||||
const getPaintedDoorButton = () => {
|
||||
if ([COLLAPSED_NAVBAR, EXPANDED_NAVBAR].includes(placement)) {
|
||||
return (
|
||||
<NavbarButton handleClick={handleClick} placement={placement} />
|
||||
);
|
||||
} if (placement === RECOMMENDATIONS_PANEL) {
|
||||
return (
|
||||
<RecommendationsPanelButton handleClick={handleClick} />
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{getPaintedDoorButton()}
|
||||
<PaintedDoorModal isOpen={isModalOpen} onClose={toggleModal} variation={experimentVariation} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
RecommendationsPaintedDoorBtn.propTypes = {
|
||||
placement: PropTypes.oneOf([COLLAPSED_NAVBAR, EXPANDED_NAVBAR, RECOMMENDATIONS_PANEL]).isRequired,
|
||||
experimentVariation: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default RecommendationsPaintedDoorBtn;
|
||||
@@ -1,95 +0,0 @@
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
import { ModalDialog } from '@openedx/paragon';
|
||||
import RecommendationsPaintedDoorBtn from './index';
|
||||
import { EXPANDED_NAVBAR, RECOMMENDATIONS_PANEL } from './constants';
|
||||
import NavbarButton from './components/NavbarButton';
|
||||
import RecommendationsPanelButton from './components/RecommendationsPanelButton';
|
||||
import { trackPaintedDoorRecommendationHomeBtnClicked } from './track';
|
||||
|
||||
jest.mock('./components/PaintedDoorModal/hooks', () => ({
|
||||
usePaintedDoorModal: jest.fn(() => ({
|
||||
isModalOpen: false,
|
||||
toggleModal: jest.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
jest.mock('./track', () => ({
|
||||
trackPaintedDoorRecommendationHomeBtnClicked: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('RecommendationsPaintedDoorBtn', () => {
|
||||
let props = {
|
||||
placement: RECOMMENDATIONS_PANEL,
|
||||
experimentVariation: '',
|
||||
};
|
||||
|
||||
it('matches snapshot', () => {
|
||||
expect(shallow(<RecommendationsPaintedDoorBtn {...props} />).snapshot).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders painted door modal', () => {
|
||||
const wrapper = shallow(<RecommendationsPaintedDoorBtn {...props} />);
|
||||
|
||||
expect(wrapper.instance.findByType(ModalDialog)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('renders painted door navbar button', () => {
|
||||
props = {
|
||||
...props,
|
||||
placement: EXPANDED_NAVBAR,
|
||||
};
|
||||
const wrapper = shallow(<RecommendationsPaintedDoorBtn {...props} />);
|
||||
|
||||
expect(wrapper.instance.findByType(NavbarButton)).not.toHaveLength(0);
|
||||
expect(wrapper.instance.findByType(RecommendationsPanelButton)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('renders painted door recommendations panel button', () => {
|
||||
props = {
|
||||
...props,
|
||||
placement: RECOMMENDATIONS_PANEL,
|
||||
};
|
||||
const wrapper = shallow(<RecommendationsPaintedDoorBtn {...props} />);
|
||||
|
||||
expect(wrapper.instance.findByType(NavbarButton)).toHaveLength(0);
|
||||
expect(wrapper.instance.findByType(RecommendationsPanelButton)).not.toHaveLength(0);
|
||||
});
|
||||
|
||||
it('test no button (null) rendered for invalid placement', () => {
|
||||
props = {
|
||||
...props,
|
||||
placement: '',
|
||||
};
|
||||
const wrapper = shallow(<RecommendationsPaintedDoorBtn {...props} />);
|
||||
|
||||
expect(wrapper.instance.findByType(NavbarButton)).toHaveLength(0);
|
||||
expect(wrapper.instance.findByType(RecommendationsPanelButton)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('test track event is fired on navbar button click', () => {
|
||||
props = {
|
||||
...props,
|
||||
placement: EXPANDED_NAVBAR,
|
||||
};
|
||||
const wrapper = shallow(<RecommendationsPaintedDoorBtn {...props} />);
|
||||
const navbarButton = wrapper.instance.findByType(NavbarButton)[0];
|
||||
|
||||
navbarButton.props.handleClick();
|
||||
|
||||
expect(trackPaintedDoorRecommendationHomeBtnClicked).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('test track event is fired on recommendations panel button click', () => {
|
||||
props = {
|
||||
...props,
|
||||
placement: RECOMMENDATIONS_PANEL,
|
||||
};
|
||||
const wrapper = shallow(<RecommendationsPaintedDoorBtn {...props} />);
|
||||
const recommendationsPanelButton = wrapper.instance.findByType(RecommendationsPanelButton)[0];
|
||||
|
||||
recommendationsPanelButton.props.handleClick();
|
||||
|
||||
expect(trackPaintedDoorRecommendationHomeBtnClicked).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -1,41 +0,0 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
recommendationsFeatureText: {
|
||||
id: 'RecommendationsPanel.recommendationsFeatureText',
|
||||
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',
|
||||
},
|
||||
recommendationsAlertText: {
|
||||
id: 'RecommendationsPanel.recommendationsAlertText',
|
||||
defaultMessage: 'Would you like to be alerted when it becomes available?',
|
||||
description: 'recommendations alerted text',
|
||||
},
|
||||
recommendationsModalHeading: {
|
||||
id: 'RecommendationsPanel.recommendationsModalHeading',
|
||||
defaultMessage: 'Thank you for your interest!',
|
||||
description: 'Heading of modal',
|
||||
},
|
||||
modalSkipButton: {
|
||||
id: 'RecommendationsPanel.modalSkipButton',
|
||||
defaultMessage: 'Skip for now',
|
||||
description: 'button for Skip for now',
|
||||
},
|
||||
modalCountMeButton: {
|
||||
id: 'RecommendationsPanel.modalCountMeButton',
|
||||
defaultMessage: 'Count me in!',
|
||||
description: 'button for Count me in!',
|
||||
},
|
||||
recommendedForYou: {
|
||||
id: 'learnerVariantDashboard.recommendedForYou',
|
||||
defaultMessage: 'Recommended For You',
|
||||
description: 'Header link for recommended page.',
|
||||
},
|
||||
seeAllRecommendationsButton: {
|
||||
id: 'RecommendationsPanel.seeAllRecommendationsButton',
|
||||
defaultMessage: 'See All Recommendations',
|
||||
description: 'Button to see all recommendations',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
@@ -1,35 +0,0 @@
|
||||
import { StrictDict } from 'utils';
|
||||
import { createEventTracker } from 'data/services/segment/utils';
|
||||
|
||||
export const eventNames = StrictDict({
|
||||
variationGroup: 'edx.bi.user.recommendation_home.variation.group',
|
||||
recommendationHomeBtnClicked: 'edx.bi.user.recommendation_home.btn.clicked',
|
||||
recommendationHomeModalInterestBtnClicked: 'edx.bi.user.recommendation_home.modal.interest_btn.clicked',
|
||||
recommendationHomeModalSkipBtnClicked: 'edx.bi.user.recommendation_home.modal.skip_btn.clicked',
|
||||
});
|
||||
|
||||
export const trackPaintedDoorVariationGroup = (variation) => {
|
||||
createEventTracker(eventNames.variationGroup, {
|
||||
variation,
|
||||
page: 'dashboard',
|
||||
})();
|
||||
};
|
||||
|
||||
export const trackPaintedDoorRecommendationHomeBtnClicked = (variation) => {
|
||||
createEventTracker(eventNames.recommendationHomeBtnClicked, {
|
||||
variation,
|
||||
page: 'dashboard',
|
||||
})();
|
||||
};
|
||||
|
||||
export const trackPaintedDoorRecommendationHomeInterestBtnClicked = (variation) => {
|
||||
createEventTracker(eventNames.recommendationHomeModalInterestBtnClicked, {
|
||||
variation,
|
||||
})();
|
||||
};
|
||||
|
||||
export const trackPaintedDoorRecommendationHomeSkipBtnClicked = (variation) => {
|
||||
createEventTracker(eventNames.recommendationHomeModalSkipBtnClicked, {
|
||||
variation,
|
||||
})();
|
||||
};
|
||||
@@ -1,58 +0,0 @@
|
||||
import { createEventTracker } from 'data/services/segment/utils';
|
||||
import {
|
||||
eventNames,
|
||||
trackPaintedDoorRecommendationHomeBtnClicked,
|
||||
trackPaintedDoorVariationGroup,
|
||||
trackPaintedDoorRecommendationHomeSkipBtnClicked,
|
||||
trackPaintedDoorRecommendationHomeInterestBtnClicked,
|
||||
} from './track';
|
||||
|
||||
jest.mock('data/services/segment/utils', () => ({
|
||||
createEventTracker: jest.fn(() => () => {}),
|
||||
}));
|
||||
|
||||
const TEST_VARIATION = 'testVariation';
|
||||
|
||||
describe('Recommendations Painted Door experiment trackers', () => {
|
||||
it('test creates an event tracker for painted door variation group', () => {
|
||||
trackPaintedDoorVariationGroup(TEST_VARIATION);
|
||||
expect(createEventTracker).toHaveBeenCalledWith(
|
||||
eventNames.variationGroup,
|
||||
{
|
||||
variation: TEST_VARIATION,
|
||||
page: 'dashboard',
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('test creates an event tracker for painted door button click', () => {
|
||||
trackPaintedDoorRecommendationHomeBtnClicked(TEST_VARIATION);
|
||||
expect(createEventTracker).toHaveBeenCalledWith(
|
||||
eventNames.recommendationHomeBtnClicked,
|
||||
{
|
||||
variation: TEST_VARIATION,
|
||||
page: 'dashboard',
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('test creates an event tracker for painted door skip button click', () => {
|
||||
trackPaintedDoorRecommendationHomeSkipBtnClicked(TEST_VARIATION);
|
||||
expect(createEventTracker).toHaveBeenCalledWith(
|
||||
eventNames.recommendationHomeModalSkipBtnClicked,
|
||||
{
|
||||
variation: TEST_VARIATION,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('test creates an event tracker for painted door interest button click', () => {
|
||||
trackPaintedDoorRecommendationHomeInterestBtnClicked(TEST_VARIATION);
|
||||
expect(createEventTracker).toHaveBeenCalledWith(
|
||||
eventNames.recommendationHomeModalInterestBtnClicked,
|
||||
{
|
||||
variation: TEST_VARIATION,
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -12,9 +12,6 @@ import CourseCard from './components/CourseCard';
|
||||
import messages from './messages';
|
||||
|
||||
import './index.scss';
|
||||
import { usePaintedDoorExperimentContext } from '../RecommendationsPaintedDoorBtn/PaintedDoorExperimentContext';
|
||||
import { RECOMMENDATIONS_PANEL } from '../RecommendationsPaintedDoorBtn/constants';
|
||||
import RecommendationsPaintedDoorBtn from '../RecommendationsPaintedDoorBtn';
|
||||
|
||||
export const LoadedView = ({
|
||||
courses,
|
||||
@@ -22,11 +19,6 @@ export const LoadedView = ({
|
||||
}) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const { courseSearchUrl } = reduxHooks.usePlatformSettingsData();
|
||||
const {
|
||||
experimentVariation,
|
||||
isPaintedDoorWidgetBtnVariation,
|
||||
experimentLoading,
|
||||
} = usePaintedDoorExperimentContext();
|
||||
|
||||
return (
|
||||
<div className="p-4 w-100 panel-background">
|
||||
@@ -43,19 +35,15 @@ export const LoadedView = ({
|
||||
))}
|
||||
</div>
|
||||
<div className="text-center explore-courses-btn">
|
||||
{!experimentLoading && isPaintedDoorWidgetBtnVariation ? (
|
||||
<RecommendationsPaintedDoorBtn placement={RECOMMENDATIONS_PANEL} experimentVariation={experimentVariation} />
|
||||
) : (
|
||||
<Button
|
||||
variant="tertiary"
|
||||
iconBefore={Search}
|
||||
as="a"
|
||||
href={baseAppUrl(courseSearchUrl)}
|
||||
onClick={track.findCoursesWidgetClicked(baseAppUrl(courseSearchUrl))}
|
||||
>
|
||||
{formatMessage(messages.exploreCoursesButton)}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
variant="tertiary"
|
||||
iconBefore={Search}
|
||||
as="a"
|
||||
href={baseAppUrl(courseSearchUrl)}
|
||||
onClick={track.findCoursesWidgetClicked(baseAppUrl(courseSearchUrl))}
|
||||
>
|
||||
{formatMessage(messages.exploreCoursesButton)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import React from 'react';
|
||||
import { shallow } from '@edx/react-unit-test-utils';
|
||||
|
||||
import { Button } from '@openedx/paragon';
|
||||
import LoadedView from './LoadedView';
|
||||
import mockData from './mockData';
|
||||
import messages from './messages';
|
||||
import { usePaintedDoorExperimentContext } from '../RecommendationsPaintedDoorBtn/PaintedDoorExperimentContext';
|
||||
import RecommendationsPaintedDoorBtn from '../RecommendationsPaintedDoorBtn';
|
||||
|
||||
jest.mock('hooks', () => ({
|
||||
reduxHooks: {
|
||||
@@ -22,64 +19,24 @@ jest.mock('./track', () => ({
|
||||
findCoursesWidgetClicked: (href) => jest.fn().mockName(`track.findCoursesWidgetClicked('${href}')`),
|
||||
}));
|
||||
jest.mock('./components/CourseCard', () => 'CourseCard');
|
||||
jest.mock('widgets/RecommendationsPaintedDoorBtn/PaintedDoorExperimentContext', () => ({
|
||||
usePaintedDoorExperimentContext: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('RecommendationsPanel LoadedView', () => {
|
||||
const props = {
|
||||
courses: mockData.courses,
|
||||
isControl: null,
|
||||
};
|
||||
let mockExperimentContext = {
|
||||
experimentVariation: '',
|
||||
isPaintedDoorWidgetBtnVariation: true,
|
||||
experimentLoading: false,
|
||||
};
|
||||
|
||||
describe('RecommendationPanelLoadedView', () => {
|
||||
test('without personalize recommendation', () => {
|
||||
usePaintedDoorExperimentContext.mockReturnValueOnce(mockExperimentContext);
|
||||
const el = shallow(<LoadedView {...props} />);
|
||||
expect(el.snapshot).toMatchSnapshot();
|
||||
expect(el.instance.findByType('h3')[0].children[0].el).toEqual(messages.popularCoursesHeading.defaultMessage);
|
||||
});
|
||||
|
||||
test('with personalize recommendation', () => {
|
||||
usePaintedDoorExperimentContext.mockReturnValueOnce(mockExperimentContext);
|
||||
const el = shallow(<LoadedView {...props} isControl={false} />);
|
||||
expect(el.snapshot).toMatchSnapshot();
|
||||
expect(el.instance.findByType('h3')[0].children[0].el).toEqual(messages.recommendationsHeading.defaultMessage);
|
||||
});
|
||||
|
||||
test('test painted door button is rendered if user is in variation', () => {
|
||||
usePaintedDoorExperimentContext.mockReturnValueOnce(mockExperimentContext);
|
||||
const wrapper = shallow(<LoadedView {...props} />);
|
||||
expect(wrapper.instance.findByType(RecommendationsPaintedDoorBtn)).not.toHaveLength(0);
|
||||
});
|
||||
|
||||
test('test explore courses button is returned if user is not in variation', () => {
|
||||
mockExperimentContext = {
|
||||
...mockExperimentContext,
|
||||
isPaintedDoorWidgetBtnVariation: false,
|
||||
};
|
||||
usePaintedDoorExperimentContext.mockReturnValueOnce(mockExperimentContext);
|
||||
const wrapper = shallow(<LoadedView {...props} />);
|
||||
expect(wrapper.instance.findByType(RecommendationsPaintedDoorBtn)).toHaveLength(0);
|
||||
expect(wrapper.instance.findByType(Button)[0].children[0].el)
|
||||
.toEqual(messages.exploreCoursesButton.defaultMessage);
|
||||
});
|
||||
|
||||
test('test explore courses button is returned if experiment is loading', () => {
|
||||
mockExperimentContext = {
|
||||
...mockExperimentContext,
|
||||
isPaintedDoorWidgetBtnVariation: false,
|
||||
experimentLoading: true,
|
||||
};
|
||||
usePaintedDoorExperimentContext.mockReturnValueOnce(mockExperimentContext);
|
||||
const wrapper = shallow(<LoadedView {...props} />);
|
||||
expect(wrapper.instance.findByType(RecommendationsPaintedDoorBtn)).toHaveLength(0);
|
||||
expect(wrapper.instance.findByType(Button)[0].children[0].el)
|
||||
.toEqual(messages.exploreCoursesButton.defaultMessage);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -62,10 +62,15 @@ exports[`RecommendationsPanel LoadedView RecommendationPanelLoadedView with pers
|
||||
<div
|
||||
className="text-center explore-courses-btn"
|
||||
>
|
||||
<RecommendationsPaintedDoorBtn
|
||||
experimentVariation=""
|
||||
placement="recommendationsPanel"
|
||||
/>
|
||||
<Button
|
||||
as="a"
|
||||
href="http://localhost:18000/course-search-url"
|
||||
iconBefore={[MockFunction icons.Search]}
|
||||
onClick={[MockFunction track.findCoursesWidgetClicked('http://localhost:18000/course-search-url')]}
|
||||
variant="tertiary"
|
||||
>
|
||||
Explore courses
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -132,10 +137,15 @@ exports[`RecommendationsPanel LoadedView RecommendationPanelLoadedView without p
|
||||
<div
|
||||
className="text-center explore-courses-btn"
|
||||
>
|
||||
<RecommendationsPaintedDoorBtn
|
||||
experimentVariation=""
|
||||
placement="recommendationsPanel"
|
||||
/>
|
||||
<Button
|
||||
as="a"
|
||||
href="http://localhost:18000/course-search-url"
|
||||
iconBefore={[MockFunction icons.Search]}
|
||||
onClick={[MockFunction track.findCoursesWidgetClicked('http://localhost:18000/course-search-url')]}
|
||||
variant="tertiary"
|
||||
>
|
||||
Explore courses
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -4,9 +4,6 @@ import LookingForChallengeWidget from 'widgets/LookingForChallengeWidget';
|
||||
import LoadingView from './LoadingView';
|
||||
import LoadedView from './LoadedView';
|
||||
import hooks from './hooks';
|
||||
import RecommendationsPaintedDoorBtn from '../RecommendationsPaintedDoorBtn';
|
||||
import { RECOMMENDATIONS_PANEL } from '../RecommendationsPaintedDoorBtn/constants';
|
||||
import { usePaintedDoorExperimentContext } from '../RecommendationsPaintedDoorBtn/PaintedDoorExperimentContext';
|
||||
|
||||
export const RecommendationsPanel = () => {
|
||||
const {
|
||||
@@ -16,29 +13,6 @@ export const RecommendationsPanel = () => {
|
||||
isLoaded,
|
||||
isLoading,
|
||||
} = hooks.useRecommendationPanelData();
|
||||
const {
|
||||
experimentVariation,
|
||||
isPaintedDoorWidgetBtnVariation,
|
||||
experimentLoading,
|
||||
} = usePaintedDoorExperimentContext();
|
||||
|
||||
const getDefaultOrFailedStateWidget = () => {
|
||||
if (!experimentLoading && isPaintedDoorWidgetBtnVariation) {
|
||||
return (
|
||||
<>
|
||||
<LookingForChallengeWidget />
|
||||
<div className="pt-3" />
|
||||
<RecommendationsPaintedDoorBtn
|
||||
experimentVariation={experimentVariation}
|
||||
placement={RECOMMENDATIONS_PANEL}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<LookingForChallengeWidget />
|
||||
);
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return (<LoadingView />);
|
||||
@@ -49,10 +23,10 @@ export const RecommendationsPanel = () => {
|
||||
);
|
||||
}
|
||||
if (isFailed) {
|
||||
return getDefaultOrFailedStateWidget();
|
||||
return (<LookingForChallengeWidget />);
|
||||
}
|
||||
// default fallback
|
||||
return getDefaultOrFailedStateWidget();
|
||||
return (<LookingForChallengeWidget />);
|
||||
};
|
||||
|
||||
export default RecommendationsPanel;
|
||||
|
||||
@@ -7,8 +7,6 @@ import mockData from './mockData';
|
||||
import LoadedView from './LoadedView';
|
||||
import LoadingView from './LoadingView';
|
||||
import RecommendationsPanel from '.';
|
||||
import { usePaintedDoorExperimentContext } from '../RecommendationsPaintedDoorBtn/PaintedDoorExperimentContext';
|
||||
import RecommendationsPaintedDoorBtn from '../RecommendationsPaintedDoorBtn';
|
||||
|
||||
jest.mock('./hooks', () => ({
|
||||
useRecommendationPanelData: jest.fn(),
|
||||
@@ -16,9 +14,6 @@ jest.mock('./hooks', () => ({
|
||||
jest.mock('widgets/LookingForChallengeWidget', () => 'LookingForChallengeWidget');
|
||||
jest.mock('./LoadingView', () => 'LoadingView');
|
||||
jest.mock('./LoadedView', () => 'LoadedView');
|
||||
jest.mock('widgets/RecommendationsPaintedDoorBtn/PaintedDoorExperimentContext', () => ({
|
||||
usePaintedDoorExperimentContext: jest.fn(),
|
||||
}));
|
||||
|
||||
const { courses } = mockData;
|
||||
|
||||
@@ -34,13 +29,6 @@ describe('RecommendationsPanel snapshot', () => {
|
||||
...defaultLoadedViewProps,
|
||||
};
|
||||
describe('RecommendationsPanel recommendations tests', () => {
|
||||
beforeEach(() => {
|
||||
usePaintedDoorExperimentContext.mockReturnValueOnce({
|
||||
experimentVariation: '',
|
||||
isPaintedDoorWidgetBtnVariation: false,
|
||||
experimentLoading: false,
|
||||
});
|
||||
});
|
||||
it('displays LoadingView if request is loading', () => {
|
||||
hooks.useRecommendationPanelData.mockReturnValueOnce({
|
||||
...defaultValues,
|
||||
@@ -77,65 +65,4 @@ describe('RecommendationsPanel snapshot', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('RecommendationsPanel painted door exp tests', () => {
|
||||
it('displays painted door btn if user is in variation and request is failed', () => {
|
||||
hooks.useRecommendationPanelData.mockReturnValueOnce({
|
||||
...defaultValues,
|
||||
isFailed: true,
|
||||
});
|
||||
usePaintedDoorExperimentContext.mockReturnValueOnce({
|
||||
experimentVariation: '',
|
||||
isPaintedDoorWidgetBtnVariation: true,
|
||||
experimentLoading: false,
|
||||
});
|
||||
|
||||
const wrapper = shallow(<RecommendationsPanel />);
|
||||
expect(wrapper.instance.findByType(RecommendationsPaintedDoorBtn)).not.toHaveLength(0);
|
||||
});
|
||||
it('displays painted door btn if user is in variation and no flags are set (defaults)', () => {
|
||||
hooks.useRecommendationPanelData.mockReturnValueOnce({
|
||||
...defaultValues,
|
||||
isFailed: true,
|
||||
});
|
||||
usePaintedDoorExperimentContext.mockReturnValueOnce({
|
||||
experimentVariation: '',
|
||||
isPaintedDoorWidgetBtnVariation: true,
|
||||
experimentLoading: false,
|
||||
});
|
||||
|
||||
const wrapper = shallow(<RecommendationsPanel />);
|
||||
expect(wrapper.instance.findByType(RecommendationsPaintedDoorBtn)).not.toHaveLength(0);
|
||||
});
|
||||
it('renders only LookingForChallengeWidget if user is not in variation', () => {
|
||||
hooks.useRecommendationPanelData.mockReturnValueOnce({
|
||||
...defaultValues,
|
||||
isFailed: true,
|
||||
});
|
||||
usePaintedDoorExperimentContext.mockReturnValueOnce({
|
||||
experimentVariation: '',
|
||||
isPaintedDoorWidgetBtnVariation: false,
|
||||
experimentLoading: false,
|
||||
});
|
||||
|
||||
expect({ ...shallow(<RecommendationsPanel />).shallowWrapper, children: expect.any(Array) }).toMatchObject(
|
||||
shallow(<LookingForChallengeWidget />),
|
||||
);
|
||||
});
|
||||
it('renders only LookingForChallengeWidget if experiment is loading', () => {
|
||||
hooks.useRecommendationPanelData.mockReturnValueOnce({
|
||||
...defaultValues,
|
||||
isFailed: true,
|
||||
});
|
||||
usePaintedDoorExperimentContext.mockReturnValueOnce({
|
||||
experimentVariation: '',
|
||||
isPaintedDoorWidgetBtnVariation: false,
|
||||
experimentLoading: true,
|
||||
});
|
||||
|
||||
expect({ ...shallow(<RecommendationsPanel />).shallowWrapper, children: expect.any(Array) }).toMatchObject(
|
||||
shallow(<LookingForChallengeWidget />),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user