@@ -40,12 +42,14 @@ exports[`App router component component no network failure snapshot 1`] = `
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -65,16 +69,18 @@ exports[`App router component component refresh failure snapshot 1`] = `
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/src/containers/LearnerDashboardHeader/CollapsedHeader/CollapseMenuBody.jsx b/src/containers/LearnerDashboardHeader/CollapsedHeader/CollapseMenuBody.jsx
index 3736c26..58facf5 100644
--- a/src/containers/LearnerDashboardHeader/CollapsedHeader/CollapseMenuBody.jsx
+++ b/src/containers/LearnerDashboardHeader/CollapsedHeader/CollapseMenuBody.jsx
@@ -4,14 +4,14 @@ import PropTypes from 'prop-types';
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { AppContext } from '@edx/frontend-platform/react';
-
import { Button, Badge } from '@edx/paragon';
+import WidgetNavbar from 'containers/WidgetContainers/WidgetNavbar';
import urls from 'data/services/lms/urls';
import { reduxHooks } from 'hooks';
+import { COLLAPSED_NAVBAR } from 'widgets/RecommendationsPaintedDoorBtn/constants';
import { findCoursesNavDropdownClicked } from '../hooks';
-
import messages from '../messages';
export const CollapseMenuBody = ({ isOpen }) => {
@@ -40,6 +40,7 @@ export const CollapseMenuBody = ({ isOpen }) => {
>
{formatMessage(messages.discoverNew)}
+
diff --git a/src/containers/LearnerDashboardHeader/CollapsedHeader/__snapshots__/CollapseMenuBody.test.jsx.snap b/src/containers/LearnerDashboardHeader/CollapsedHeader/__snapshots__/CollapseMenuBody.test.jsx.snap
index c7694e8..7be3396 100644
--- a/src/containers/LearnerDashboardHeader/CollapsedHeader/__snapshots__/CollapseMenuBody.test.jsx.snap
+++ b/src/containers/LearnerDashboardHeader/CollapsedHeader/__snapshots__/CollapseMenuBody.test.jsx.snap
@@ -26,6 +26,9 @@ exports[`CollapseMenuBody render 1`] = `
>
Discover New
+
+
+
diff --git a/src/containers/LearnerDashboardHeader/ExpandedHeader/index.jsx b/src/containers/LearnerDashboardHeader/ExpandedHeader/index.jsx
index dccb045..250a775 100644
--- a/src/containers/LearnerDashboardHeader/ExpandedHeader/index.jsx
+++ b/src/containers/LearnerDashboardHeader/ExpandedHeader/index.jsx
@@ -4,11 +4,12 @@ import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Button } from '@edx/paragon';
+import WidgetNavbar from 'containers/WidgetContainers/WidgetNavbar';
import urls from 'data/services/lms/urls';
import { reduxHooks } from 'hooks';
+import { EXPANDED_NAVBAR } from 'widgets/RecommendationsPaintedDoorBtn/constants';
import AuthenticatedUserDropdown from './AuthenticatedUserDropdown';
-
import { useIsCollapsed, findCoursesNavClicked } from '../hooks';
import messages from '../messages';
import BrandLogo from '../BrandLogo';
@@ -51,6 +52,7 @@ export const ExpandedHeader = () => {
>
{formatMessage(messages.discoverNew)}
+
+`;
+
+exports[`AppWrapper WidgetContainer component output painted door experiment is active (08/23) snapshot 1`] = `
+
+
+ This is some
+
+ test
+
+
+
+ content
+
+
+
+`;
diff --git a/src/containers/WidgetContainers/AppWrapper/index.jsx b/src/containers/WidgetContainers/AppWrapper/index.jsx
new file mode 100644
index 0000000..d1e999e
--- /dev/null
+++ b/src/containers/WidgetContainers/AppWrapper/index.jsx
@@ -0,0 +1,25 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import PaintedDoorExperimentProvider from 'widgets/RecommendationsPaintedDoorBtn/PaintedDoorExperimentContext';
+
+export const AppWrapper = ({
+ children,
+}) => {
+ if (process.env.EXPERIMENT_08_23_VAN_PAINTED_DOOR) {
+ return (
+
+ {children}
+
+ );
+ }
+ return children;
+};
+AppWrapper.propTypes = {
+ children: PropTypes.oneOfType([
+ PropTypes.node,
+ PropTypes.arrayOf(PropTypes.node),
+ ]).isRequired,
+};
+
+export default AppWrapper;
diff --git a/src/containers/WidgetContainers/AppWrapper/index.test.jsx b/src/containers/WidgetContainers/AppWrapper/index.test.jsx
new file mode 100644
index 0000000..24d4617
--- /dev/null
+++ b/src/containers/WidgetContainers/AppWrapper/index.test.jsx
@@ -0,0 +1,56 @@
+import React from 'react';
+
+import { shallow } from '@edx/react-unit-test-utils';
+
+import PaintedDoorExperimentProvider from 'widgets/RecommendationsPaintedDoorBtn/PaintedDoorExperimentContext';
+
+import AppWrapper from '.';
+
+jest.mock(
+ 'widgets/RecommendationsPaintedDoorBtn/PaintedDoorExperimentContext',
+ () => 'PaintedDoorExperimentProvider',
+);
+
+let el;
+
+const children = (
This is some test content
);
+
+const render = () => {
+ el = shallow(
{children});
+};
+
+const mockAndRenderForBlock = (newVal) => {
+ const oldVal = process.env;
+ beforeEach(() => {
+ process.env = { ...oldVal, ...newVal };
+ render();
+ });
+ afterEach(() => {
+ process.env = oldVal;
+ render();
+ });
+};
+
+describe('AppWrapper WidgetContainer component', () => {
+ describe('output', () => {
+ describe('painted door experiment is active (08/23)', () => {
+ mockAndRenderForBlock({ EXPERIMENT_08_23_VAN_PAINTED_DOOR: true });
+ test('snapshot', () => {
+ expect(el.snapshot).toMatchSnapshot();
+ });
+ it('renders children wrapped in PaintedDoorExperimentProvider', () => {
+ const control = el.instance.findByType(PaintedDoorExperimentProvider)[0];
+ expect(el.instance).toEqual(control);
+ });
+ });
+ describe('no experiments are active', () => {
+ mockAndRenderForBlock({ EXPERIMENT_08_23_VAN_PAINTED_DOOR: false });
+ test('snapshot', () => {
+ expect(el.snapshot).toMatchSnapshot();
+ });
+ it('renders children wrapped in PaintedDoorExperimentProvider', () => {
+ expect(el.instance.matches(shallow(children))).toEqual(true);
+ });
+ });
+ });
+});
diff --git a/src/containers/WidgetContainers/WidgetNavbar/__snapshots__/index.test.jsx.snap b/src/containers/WidgetContainers/WidgetNavbar/__snapshots__/index.test.jsx.snap
new file mode 100644
index 0000000..04ccb59
--- /dev/null
+++ b/src/containers/WidgetContainers/WidgetNavbar/__snapshots__/index.test.jsx.snap
@@ -0,0 +1,8 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`WidgetNavbar snapshots default 1`] = `
+
+`;
diff --git a/src/containers/WidgetContainers/WidgetNavbar/index.jsx b/src/containers/WidgetContainers/WidgetNavbar/index.jsx
new file mode 100644
index 0000000..fbf7660
--- /dev/null
+++ b/src/containers/WidgetContainers/WidgetNavbar/index.jsx
@@ -0,0 +1,29 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import RecommendationsPaintedDoorBtn from 'widgets/RecommendationsPaintedDoorBtn';
+import { COLLAPSED_NAVBAR, EXPANDED_NAVBAR } from 'widgets/RecommendationsPaintedDoorBtn/constants';
+import {
+ usePaintedDoorExperimentContext,
+} from 'widgets/RecommendationsPaintedDoorBtn/PaintedDoorExperimentContext';
+
+export const WidgetNavbar = ({ placement }) => {
+ const {
+ experimentVariation,
+ isPaintedDoorNavbarBtnVariation,
+ experimentLoading,
+ } = usePaintedDoorExperimentContext();
+
+ if (!experimentLoading && isPaintedDoorNavbarBtnVariation) {
+ return (
+
+ );
+ }
+
+ return null;
+};
+
+WidgetNavbar.propTypes = {
+ placement: PropTypes.oneOf([COLLAPSED_NAVBAR, EXPANDED_NAVBAR]).isRequired,
+};
+
+export default WidgetNavbar;
diff --git a/src/containers/WidgetContainers/WidgetNavbar/index.test.jsx b/src/containers/WidgetContainers/WidgetNavbar/index.test.jsx
new file mode 100644
index 0000000..e2606a8
--- /dev/null
+++ b/src/containers/WidgetContainers/WidgetNavbar/index.test.jsx
@@ -0,0 +1,65 @@
+import { shallow } from 'enzyme';
+import {
+ usePaintedDoorExperimentContext,
+} from '../../../widgets/RecommendationsPaintedDoorBtn/PaintedDoorExperimentContext';
+import WidgetNavbar from './index';
+import { EXPANDED_NAVBAR } from '../../../widgets/RecommendationsPaintedDoorBtn/constants';
+import RecommendationsPaintedDoorBtn from '../../../widgets/RecommendationsPaintedDoorBtn';
+
+jest.mock('widgets/RecommendationsPaintedDoorBtn/PaintedDoorExperimentContext', () => ({
+ usePaintedDoorExperimentContext: jest.fn(),
+}));
+
+describe('WidgetNavbar', () => {
+ let mockExperimentContext = {
+ experimentVariation: '',
+ isPaintedDoorNavbarBtnVariation: true,
+ experimentLoading: false,
+ };
+ const props = {
+ placement: EXPANDED_NAVBAR,
+ };
+
+ describe('snapshots', () => {
+ test('default', () => {
+ usePaintedDoorExperimentContext.mockReturnValueOnce(mockExperimentContext);
+ const wrapper = shallow(
);
+
+ expect(usePaintedDoorExperimentContext).toHaveBeenCalled();
+ expect(wrapper).toMatchSnapshot();
+ });
+ });
+
+ test('renders button if user in navbar variation', () => {
+ usePaintedDoorExperimentContext.mockReturnValueOnce(mockExperimentContext);
+ const wrapper = shallow(
);
+
+ expect(usePaintedDoorExperimentContext).toHaveBeenCalled();
+ expect(wrapper.type()).toBe(RecommendationsPaintedDoorBtn);
+ });
+
+ test('renders nothing if user in not in navbar variation', () => {
+ mockExperimentContext = {
+ ...mockExperimentContext,
+ isPaintedDoorNavbarBtnVariation: false,
+ };
+ usePaintedDoorExperimentContext.mockReturnValueOnce(mockExperimentContext);
+ const wrapper = shallow(
);
+
+ expect(usePaintedDoorExperimentContext).toHaveBeenCalled();
+ expect(wrapper.type()).toBeNull();
+ });
+
+ test('renders nothing if experiment is loading', () => {
+ mockExperimentContext = {
+ ...mockExperimentContext,
+ isPaintedDoorNavbarBtnVariation: false,
+ experimentLoading: true,
+ };
+ usePaintedDoorExperimentContext.mockReturnValueOnce(mockExperimentContext);
+ const wrapper = shallow(
);
+
+ expect(usePaintedDoorExperimentContext).toHaveBeenCalled();
+ expect(wrapper.type()).toBeNull();
+ });
+});
diff --git a/src/widgets/RecommendationsPaintedDoorBtn/PaintedDoorExperimentContext.jsx b/src/widgets/RecommendationsPaintedDoorBtn/PaintedDoorExperimentContext.jsx
new file mode 100644
index 0000000..51e2c06
--- /dev/null
+++ b/src/widgets/RecommendationsPaintedDoorBtn/PaintedDoorExperimentContext.jsx
@@ -0,0 +1,123 @@
+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();
+
+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 (
+
+ {children}
+
+ );
+};
+
+export const usePaintedDoorExperimentContext = () => React.useContext(PaintedDoorExperimentContext);
+
+PaintedDoorExperimentProvider.propTypes = {
+ children: PropTypes.node.isRequired,
+};
+
+export default PaintedDoorExperimentProvider;
diff --git a/src/widgets/RecommendationsPaintedDoorBtn/PaintedDoorExperimentContext.test.jsx b/src/widgets/RecommendationsPaintedDoorBtn/PaintedDoorExperimentContext.test.jsx
new file mode 100644
index 0000000..db5d312
--- /dev/null
+++ b/src/widgets/RecommendationsPaintedDoorBtn/PaintedDoorExperimentContext.test.jsx
@@ -0,0 +1,151 @@
+import React from 'react';
+import { mount } from 'enzyme';
+
+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 (
+
+ );
+ };
+
+ 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,
+ });
+
+ mount(
+
+
+ ,
+ );
+ 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,
+ });
+
+ mount(
+
+
+ ,
+ );
+ const [cb] = React.useEffect.mock.calls[1];
+ cb();
+ jest.advanceTimersByTime(500);
+
+ expect(trackPaintedDoorVariationGroup).toHaveBeenCalledTimes(0);
+ });
+ });
+});
diff --git a/src/widgets/RecommendationsPaintedDoorBtn/__snapshots__/index.test.jsx.snap b/src/widgets/RecommendationsPaintedDoorBtn/__snapshots__/index.test.jsx.snap
new file mode 100644
index 0000000..384c9fb
--- /dev/null
+++ b/src/widgets/RecommendationsPaintedDoorBtn/__snapshots__/index.test.jsx.snap
@@ -0,0 +1,14 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`RecommendationsPaintedDoorBtn matches snapshot 1`] = `
+
+
+
+
+`;
diff --git a/src/widgets/RecommendationsPaintedDoorBtn/components/NavbarButton.jsx b/src/widgets/RecommendationsPaintedDoorBtn/components/NavbarButton.jsx
new file mode 100644
index 0000000..3394cef
--- /dev/null
+++ b/src/widgets/RecommendationsPaintedDoorBtn/components/NavbarButton.jsx
@@ -0,0 +1,31 @@
+import React from 'react';
+import { Button } from '@edx/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 (
+
+ );
+};
+
+NavbarButton.propTypes = {
+ placement: PropTypes.oneOf([COLLAPSED_NAVBAR, EXPANDED_NAVBAR]).isRequired,
+ handleClick: PropTypes.func.isRequired,
+};
+
+export default NavbarButton;
diff --git a/src/widgets/RecommendationsPaintedDoorBtn/components/PaintedDoorModal/__snapshots__/index.test.jsx.snap b/src/widgets/RecommendationsPaintedDoorBtn/components/PaintedDoorModal/__snapshots__/index.test.jsx.snap
new file mode 100644
index 0000000..c3a4c83
--- /dev/null
+++ b/src/widgets/RecommendationsPaintedDoorBtn/components/PaintedDoorModal/__snapshots__/index.test.jsx.snap
@@ -0,0 +1,52 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ModalView snapshot should renders default ModalView 1`] = `
+
+
+
+
+ Thank you for your interest!
+
+
+
+
+
+ Personalized recommendations feature is not yet available. We are working hard on bringing it to your learner home in the near future.
+
+
+ Would you like to be alerted when it becomes available?
+
+
+
+
+
+
+ Skip for now
+
+
+ Count me in!
+
+
+
+
+
+`;
diff --git a/src/widgets/RecommendationsPaintedDoorBtn/components/PaintedDoorModal/hooks.js b/src/widgets/RecommendationsPaintedDoorBtn/components/PaintedDoorModal/hooks.js
new file mode 100644
index 0000000..0b4dfa8
--- /dev/null
+++ b/src/widgets/RecommendationsPaintedDoorBtn/components/PaintedDoorModal/hooks.js
@@ -0,0 +1,18 @@
+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,
+ };
+};
diff --git a/src/widgets/RecommendationsPaintedDoorBtn/components/PaintedDoorModal/hooks.test.js b/src/widgets/RecommendationsPaintedDoorBtn/components/PaintedDoorModal/hooks.test.js
new file mode 100644
index 0000000..736ede4
--- /dev/null
+++ b/src/widgets/RecommendationsPaintedDoorBtn/components/PaintedDoorModal/hooks.test.js
@@ -0,0 +1,30 @@
+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);
+ });
+ });
+});
diff --git a/src/widgets/RecommendationsPaintedDoorBtn/components/PaintedDoorModal/index.jsx b/src/widgets/RecommendationsPaintedDoorBtn/components/PaintedDoorModal/index.jsx
new file mode 100644
index 0000000..94f44a2
--- /dev/null
+++ b/src/widgets/RecommendationsPaintedDoorBtn/components/PaintedDoorModal/index.jsx
@@ -0,0 +1,70 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import { ModalDialog, ActionRow } from '@edx/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 (
+
+
+
+
+ {formatMessage(messages.recommendationsModalHeading)}
+
+
+
+
+
{formatMessage(messages.recommendationsFeatureText)}
+
{formatMessage(messages.recommendationsAlertText)}
+
+
+
+
+
+ {formatMessage(messages.modalSkipButton)}
+
+
+ {formatMessage(messages.modalCountMeButton)}
+
+
+
+
+
+ );
+};
+
+ModalView.defaultProps = {
+ isOpen: false,
+};
+
+ModalView.propTypes = {
+ onClose: PropTypes.func.isRequired,
+ isOpen: PropTypes.bool,
+ variation: PropTypes.string.isRequired,
+};
+
+export default ModalView;
diff --git a/src/widgets/RecommendationsPaintedDoorBtn/components/PaintedDoorModal/index.scss b/src/widgets/RecommendationsPaintedDoorBtn/components/PaintedDoorModal/index.scss
new file mode 100644
index 0000000..c03b309
--- /dev/null
+++ b/src/widgets/RecommendationsPaintedDoorBtn/components/PaintedDoorModal/index.scss
@@ -0,0 +1,15 @@
+@import "@edx/paragon/scss/core/core";
+
+.modal-container {
+ display: none;
+}
+
+@media (max-width: 464px) {
+ .pgn__action-row{
+ flex-direction: column;
+ gap: 5px;
+ button {
+ width: 100%;
+ }
+ }
+}
diff --git a/src/widgets/RecommendationsPaintedDoorBtn/components/PaintedDoorModal/index.test.jsx b/src/widgets/RecommendationsPaintedDoorBtn/components/PaintedDoorModal/index.test.jsx
new file mode 100644
index 0000000..51397b1
--- /dev/null
+++ b/src/widgets/RecommendationsPaintedDoorBtn/components/PaintedDoorModal/index.test.jsx
@@ -0,0 +1,22 @@
+import { shallow } from 'enzyme';
+
+import ModalView from '.';
+
+jest.mock('../../track', () => ({
+ trackPaintedDoorRecommendationHomeSkipBtnClicked: jest.fn(),
+ trackPaintedDoorRecommendationHomeInterestBtnClicked: jest.fn(),
+}));
+
+describe('ModalView', () => {
+ const props = {
+ isOpen: true,
+ onClose: jest.fn(),
+ variation: '',
+ };
+ describe('snapshot', () => {
+ test('should renders default ModalView', () => {
+ const wrapper = shallow(
);
+ expect(wrapper).toMatchSnapshot();
+ });
+ });
+});
diff --git a/src/widgets/RecommendationsPaintedDoorBtn/components/RecommendationsPanelButton.jsx b/src/widgets/RecommendationsPaintedDoorBtn/components/RecommendationsPanelButton.jsx
new file mode 100644
index 0000000..d1af79b
--- /dev/null
+++ b/src/widgets/RecommendationsPaintedDoorBtn/components/RecommendationsPanelButton.jsx
@@ -0,0 +1,25 @@
+import React from 'react';
+import { Button } from '@edx/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 (
+
+ );
+};
+
+RecommendationsPanelButton.propTypes = {
+ handleClick: PropTypes.func.isRequired,
+};
+
+export default RecommendationsPanelButton;
diff --git a/src/widgets/RecommendationsPaintedDoorBtn/constants.js b/src/widgets/RecommendationsPaintedDoorBtn/constants.js
new file mode 100644
index 0000000..bbdc88a
--- /dev/null
+++ b/src/widgets/RecommendationsPaintedDoorBtn/constants.js
@@ -0,0 +1,3 @@
+export const COLLAPSED_NAVBAR = 'collapsedNavbar';
+export const EXPANDED_NAVBAR = 'expendedNavbar';
+export const RECOMMENDATIONS_PANEL = 'recommendationsPanel';
diff --git a/src/widgets/RecommendationsPaintedDoorBtn/index.jsx b/src/widgets/RecommendationsPaintedDoorBtn/index.jsx
new file mode 100644
index 0000000..1674fa3
--- /dev/null
+++ b/src/widgets/RecommendationsPaintedDoorBtn/index.jsx
@@ -0,0 +1,44 @@
+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 (
+
+ );
+ } if (placement === RECOMMENDATIONS_PANEL) {
+ return (
+
+ );
+ }
+ return null;
+ };
+
+ return (
+ <>
+ {getPaintedDoorButton()}
+
+ >
+ );
+};
+
+RecommendationsPaintedDoorBtn.propTypes = {
+ placement: PropTypes.oneOf([COLLAPSED_NAVBAR, EXPANDED_NAVBAR, RECOMMENDATIONS_PANEL]).isRequired,
+ experimentVariation: PropTypes.string.isRequired,
+};
+
+export default RecommendationsPaintedDoorBtn;
diff --git a/src/widgets/RecommendationsPaintedDoorBtn/index.test.jsx b/src/widgets/RecommendationsPaintedDoorBtn/index.test.jsx
new file mode 100644
index 0000000..c399cde
--- /dev/null
+++ b/src/widgets/RecommendationsPaintedDoorBtn/index.test.jsx
@@ -0,0 +1,95 @@
+import React from 'react';
+import { mount, shallow } from 'enzyme';
+import { Button, ModalDialog } from '@edx/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(
)).toMatchSnapshot();
+ });
+
+ it('renders painted door modal', () => {
+ const wrapper = shallow(
);
+
+ expect(wrapper.find(ModalDialog)).toBeTruthy();
+ });
+
+ it('renders painted door navbar button', () => {
+ props = {
+ ...props,
+ placement: EXPANDED_NAVBAR,
+ };
+ const wrapper = shallow(
);
+
+ expect(wrapper.find(NavbarButton).exists()).toBe(true);
+ expect(wrapper.find(RecommendationsPanelButton).exists()).toBe(false);
+ });
+
+ it('renders painted door recommendations panel button', () => {
+ props = {
+ ...props,
+ placement: RECOMMENDATIONS_PANEL,
+ };
+ const wrapper = shallow(
);
+
+ expect(wrapper.find(NavbarButton).exists()).toBe(false);
+ expect(wrapper.find(RecommendationsPanelButton).exists()).toBe(true);
+ });
+
+ it('test no button (null) rendered for invalid placement', () => {
+ props = {
+ ...props,
+ placement: '',
+ };
+ const wrapper = shallow(
);
+
+ expect(wrapper.find(NavbarButton).exists()).toBe(false);
+ expect(wrapper.find(RecommendationsPanelButton).exists()).toBe(false);
+ });
+
+ it('test track event is fired on navbar button click', () => {
+ props = {
+ ...props,
+ placement: EXPANDED_NAVBAR,
+ };
+ const wrapper = mount(
);
+ const navbarButton = wrapper.find(NavbarButton);
+
+ navbarButton.find(Button).simulate('click');
+
+ expect(trackPaintedDoorRecommendationHomeBtnClicked).toHaveBeenCalled();
+ });
+
+ it('test track event is fired on recommendations panel button click', () => {
+ props = {
+ ...props,
+ placement: RECOMMENDATIONS_PANEL,
+ };
+ const wrapper = mount(
);
+ const navbarButton = wrapper.find(RecommendationsPanelButton);
+
+ navbarButton.find(Button).simulate('click');
+
+ expect(trackPaintedDoorRecommendationHomeBtnClicked).toHaveBeenCalled();
+ });
+});
diff --git a/src/widgets/RecommendationsPaintedDoorBtn/messages.js b/src/widgets/RecommendationsPaintedDoorBtn/messages.js
new file mode 100644
index 0000000..7f4d53f
--- /dev/null
+++ b/src/widgets/RecommendationsPaintedDoorBtn/messages.js
@@ -0,0 +1,41 @@
+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;
diff --git a/src/widgets/RecommendationsPaintedDoorBtn/track.js b/src/widgets/RecommendationsPaintedDoorBtn/track.js
new file mode 100644
index 0000000..d201a01
--- /dev/null
+++ b/src/widgets/RecommendationsPaintedDoorBtn/track.js
@@ -0,0 +1,35 @@
+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,
+ });
+};
diff --git a/src/widgets/RecommendationsPaintedDoorBtn/track.test.js b/src/widgets/RecommendationsPaintedDoorBtn/track.test.js
new file mode 100644
index 0000000..e236663
--- /dev/null
+++ b/src/widgets/RecommendationsPaintedDoorBtn/track.test.js
@@ -0,0 +1,58 @@
+import { createEventTracker } from 'data/services/segment/utils';
+import {
+ eventNames,
+ trackPaintedDoorRecommendationHomeBtnClicked,
+ trackPaintedDoorVariationGroup,
+ trackPaintedDoorRecommendationHomeSkipBtnClicked,
+ trackPaintedDoorRecommendationHomeInterestBtnClicked,
+} from './track';
+
+jest.mock('data/services/segment/utils', () => ({
+ createEventTracker: jest.fn((args) => ({ createEventTracker: args })),
+}));
+
+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,
+ },
+ );
+ });
+});
diff --git a/src/widgets/RecommendationsPanel/LoadedView.jsx b/src/widgets/RecommendationsPanel/LoadedView.jsx
index e8d713d..817b535 100644
--- a/src/widgets/RecommendationsPanel/LoadedView.jsx
+++ b/src/widgets/RecommendationsPanel/LoadedView.jsx
@@ -12,6 +12,9 @@ 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,
@@ -19,6 +22,11 @@ export const LoadedView = ({
}) => {
const { formatMessage } = useIntl();
const { courseSearchUrl } = reduxHooks.usePlatformSettingsData();
+ const {
+ experimentVariation,
+ isPaintedDoorWidgetBtnVariation,
+ experimentLoading,
+ } = usePaintedDoorExperimentContext();
return (
@@ -35,15 +43,19 @@ export const LoadedView = ({
))}
-
+ {!experimentLoading && isPaintedDoorWidgetBtnVariation ? (
+
+ ) : (
+
+ )}
);
diff --git a/src/widgets/RecommendationsPanel/LoadedView.test.jsx b/src/widgets/RecommendationsPanel/LoadedView.test.jsx
index 20b7a4b..3456ff9 100644
--- a/src/widgets/RecommendationsPanel/LoadedView.test.jsx
+++ b/src/widgets/RecommendationsPanel/LoadedView.test.jsx
@@ -1,9 +1,12 @@
import React from 'react';
import { shallow } from 'enzyme';
+import { Button } from '@edx/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: {
@@ -19,22 +22,62 @@ 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,
};
- describe('snapshot', () => {
+ let mockExperimentContext = {
+ experimentVariation: '',
+ isPaintedDoorWidgetBtnVariation: true,
+ experimentLoading: false,
+ };
+ describe('RecommendationPanelLoadedView', () => {
test('without personalize recommendation', () => {
+ usePaintedDoorExperimentContext.mockReturnValueOnce(mockExperimentContext);
const el = shallow(
);
expect(el).toMatchSnapshot();
expect(el.find('h3').text()).toEqual(messages.popularCoursesHeading.defaultMessage);
});
+
test('with personalize recommendation', () => {
+ usePaintedDoorExperimentContext.mockReturnValueOnce(mockExperimentContext);
const el = shallow(
);
expect(el).toMatchSnapshot();
expect(el.find('h3').text()).toEqual(messages.recommendationsHeading.defaultMessage);
});
+
+ test('test painted door button is rendered if user is in variation', () => {
+ usePaintedDoorExperimentContext.mockReturnValueOnce(mockExperimentContext);
+ const wrapper = shallow(
);
+ expect(wrapper.find(RecommendationsPaintedDoorBtn).exists()).toEqual(true);
+ });
+
+ test('test explore courses button is returned if user is not in variation', () => {
+ mockExperimentContext = {
+ ...mockExperimentContext,
+ isPaintedDoorWidgetBtnVariation: false,
+ };
+ usePaintedDoorExperimentContext.mockReturnValueOnce(mockExperimentContext);
+ const wrapper = shallow(
);
+ expect(wrapper.find(RecommendationsPaintedDoorBtn).exists()).toEqual(false);
+ expect(wrapper.find(Button).text()).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(
);
+ expect(wrapper.find(RecommendationsPaintedDoorBtn).exists()).toEqual(false);
+ expect(wrapper.find(Button).text()).toEqual(messages.exploreCoursesButton.defaultMessage);
+ });
});
});
diff --git a/src/widgets/RecommendationsPanel/__snapshots__/LoadedView.test.jsx.snap b/src/widgets/RecommendationsPanel/__snapshots__/LoadedView.test.jsx.snap
index c04c032..11182a9 100644
--- a/src/widgets/RecommendationsPanel/__snapshots__/LoadedView.test.jsx.snap
+++ b/src/widgets/RecommendationsPanel/__snapshots__/LoadedView.test.jsx.snap
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`RecommendationsPanel LoadedView snapshot with personalize recommendation 1`] = `
+exports[`RecommendationsPanel LoadedView RecommendationPanelLoadedView with personalize recommendation 1`] = `
`;
-exports[`RecommendationsPanel LoadedView snapshot without personalize recommendation 1`] = `
+exports[`RecommendationsPanel LoadedView RecommendationPanelLoadedView without personalize recommendation 1`] = `