diff --git a/src/App.jsx b/src/App.jsx index f10ea78..4876318 100755 --- a/src/App.jsx +++ b/src/App.jsx @@ -4,14 +4,23 @@ import { useDispatch } from 'react-redux'; import { Helmet } from 'react-helmet'; import { useIntl } from '@edx/frontend-platform/i18n'; -import { AppContext } from '@edx/frontend-platform/react'; +import { ErrorPage, AppContext } from '@edx/frontend-platform/react'; import Footer from '@edx/frontend-component-footer'; +import { Alert } from '@edx/paragon'; +import { RequestKeys } from 'data/constants/requests'; import store from 'data/store'; -import { selectors, actions, thunkActions } from 'data/redux'; -import fakeData from 'data/services/lms/fakeData/courses'; +import { + selectors, + actions, + thunkActions, + hooks as appHooks, +} from 'data/redux'; import LearnerDashboardHeader from 'containers/LearnerDashboardHeader'; import Dashboard from 'containers/Dashboard'; + +import fakeData from 'data/services/lms/fakeData/courses'; + import messages from './messages'; import './App.scss'; @@ -21,6 +30,12 @@ export const App = () => { // TODO: made development-only const { authenticatedUser } = React.useContext(AppContext); const { formatMessage } = useIntl(); + const isFailed = { + initialize: appHooks.useRequestIsFailed(RequestKeys.initialize), + refreshList: appHooks.useRequestIsFailed(RequestKeys.refreshList), + }; + const hasNetworkFailure = isFailed.initialize || isFailed.refreshList; + const { supportEmail } = appHooks.usePlatformSettingsData(); React.useEffect(() => { if (authenticatedUser?.administrator || process.env.NODE_ENV === 'development') { window.loadEmptyData = () => { @@ -49,7 +64,12 @@ export const App = () => {
- + {hasNetworkFailure + ? ( + + + + ) : ()}
diff --git a/src/App.test.jsx b/src/App.test.jsx index 775e196..b9873ae 100644 --- a/src/App.test.jsx +++ b/src/App.test.jsx @@ -1,41 +1,104 @@ import React from 'react'; import { shallow } from 'enzyme'; +import { Helmet } from 'react-helmet'; +import { ErrorPage } from '@edx/frontend-platform/react'; -import { BrowserRouter } from 'react-router-dom'; +import { BrowserRouter as Router } from 'react-router-dom'; import Footer from '@edx/frontend-component-footer'; +import { useIntl } from '@edx/frontend-platform/i18n'; +import { Alert } from '@edx/paragon'; +import { RequestKeys } from 'data/constants/requests'; +import { hooks as appHooks } from 'data/redux'; import Dashboard from 'containers/Dashboard'; +import LearnerDashboardHeader from 'containers/LearnerDashboardHeader'; import { App } from './App'; +import messages from './messages'; jest.mock('@edx/frontend-component-footer', () => 'Footer'); jest.mock('containers/Dashboard', () => 'Dashboard'); jest.mock('containers/LearnerDashboardHeader', () => 'LearnerDashboardHeader'); +jest.mock('data/redux', () => ({ + selectors: 'redux.selectors', + actions: 'redux.actions', + thunkActions: 'redux.thunkActions', + hooks: { + useRequestIsFailed: jest.fn(), + usePlatformSettingsData: jest.fn(), + }, +})); +jest.mock('data/store', () => 'data/store'); const logo = 'fakeLogo.png'; let el; -let router; + +const supportEmail = 'test-support-url'; +appHooks.usePlatformSettingsData.mockReturnValue({ supportEmail }); describe('App router component', () => { - test('snapshot: enabled', () => { - expect(shallow()).toMatchSnapshot(); - }); + process.env.LOGO_POWERED_BY_OPEN_EDX_URL_SVG = logo; + const { formatMessage } = useIntl(); describe('component', () => { - beforeEach(() => { - process.env.LOGO_POWERED_BY_OPEN_EDX_URL_SVG = logo; - el = shallow(); - router = el.find(BrowserRouter); - }); - describe('Router', () => { - test('Routing - ListView is only route', () => { - expect(router.find('main')).toEqual(shallow( + const runBasicTests = () => { + test('snapshot', () => { expect(el).toMatchSnapshot(); }); + it('displays title in helmet component', () => { + expect(el.find(Helmet).find('title').text()).toEqual(useIntl().formatMessage(messages.pageTitle)); + }); + it('displays learner dashboard header', () => { + expect(el.find(LearnerDashboardHeader).length).toEqual(1); + }); + it('wraps the page in a browser router', () => { + expect(el.find(Router)).toMatchObject(el); + }); + test('Footer logo drawn from env variable', () => { + expect(el.find(Footer).props().logo).toEqual(logo); + }); + }; + describe('no network failure', () => { + beforeAll(() => { + appHooks.useRequestIsFailed.mockReturnValue(false); + el = shallow(); + }); + runBasicTests(); + it('loads dashboard', () => { + expect(el.find('main')).toMatchObject(shallow(
, )); }); }); - test('Footer logo drawn from env variable', () => { - expect(router.find(Footer).props().logo).toEqual(logo); + describe('initialize failure', () => { + beforeAll(() => { + appHooks.useRequestIsFailed.mockImplementation((key) => key === RequestKeys.initialize); + el = shallow(); + }); + runBasicTests(); + it('loads error page', () => { + expect(el.find('main')).toEqual(shallow( +
+ + + +
, + )); + }); + }); + describe('refresh failure', () => { + beforeAll(() => { + appHooks.useRequestIsFailed.mockImplementation((key) => key === RequestKeys.refreshList); + el = shallow(); + }); + runBasicTests(); + it('loads error page', () => { + expect(el.find('main')).toEqual(shallow( +
+ + + +
, + )); + }); }); }); }); diff --git a/src/__snapshots__/App.test.jsx.snap b/src/__snapshots__/App.test.jsx.snap index 59c2da2..74e9246 100644 --- a/src/__snapshots__/App.test.jsx.snap +++ b/src/__snapshots__/App.test.jsx.snap @@ -1,6 +1,34 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`App router component snapshot: enabled 1`] = ` +exports[`App router component component initialize failure snapshot 1`] = ` + + + + Learner Home + + +
+ +
+ + + +
+
+
+
+`; + +exports[`App router component component no network failure snapshot 1`] = `