feat: add a button to return to studio (#322)
This commit is contained in:
@@ -14,8 +14,13 @@ export const EditorPage = ({
|
||||
studioEndpointUrl,
|
||||
onClose,
|
||||
}) => (
|
||||
<ErrorBoundary>
|
||||
<Provider store={store}>
|
||||
<Provider store={store}>
|
||||
<ErrorBoundary
|
||||
{...{
|
||||
learningContextId: courseId,
|
||||
studioEndpointUrl,
|
||||
}}
|
||||
>
|
||||
<Editor
|
||||
{...{
|
||||
onClose,
|
||||
@@ -26,8 +31,8 @@ export const EditorPage = ({
|
||||
studioEndpointUrl,
|
||||
}}
|
||||
/>
|
||||
</Provider>
|
||||
</ErrorBoundary>
|
||||
</ErrorBoundary>
|
||||
</Provider>
|
||||
);
|
||||
EditorPage.defaultProps = {
|
||||
blockId: null,
|
||||
|
||||
@@ -12,6 +12,11 @@ const props = {
|
||||
};
|
||||
jest.mock('react-redux', () => ({
|
||||
Provider: 'Provider',
|
||||
connect: (mapStateToProps, mapDispatchToProps) => (component) => ({
|
||||
mapStateToProps,
|
||||
mapDispatchToProps,
|
||||
component,
|
||||
}),
|
||||
}));
|
||||
jest.mock('./Editor', () => 'Editor');
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import ErrorBoundary from './sharedComponents/ErrorBoundary';
|
||||
import { VideoSelector } from './VideoSelector';
|
||||
import VideoSelector from './VideoSelector';
|
||||
import store from './data/store';
|
||||
|
||||
const VideoSelectorPage = ({
|
||||
@@ -10,8 +10,13 @@ const VideoSelectorPage = ({
|
||||
lmsEndpointUrl,
|
||||
studioEndpointUrl,
|
||||
}) => (
|
||||
<ErrorBoundary>
|
||||
<Provider store={store}>
|
||||
<Provider store={store}>
|
||||
<ErrorBoundary
|
||||
{...{
|
||||
learningContextId: courseId,
|
||||
studioEndpointUrl,
|
||||
}}
|
||||
>
|
||||
<VideoSelector
|
||||
{...{
|
||||
learningContextId: courseId,
|
||||
@@ -19,8 +24,8 @@ const VideoSelectorPage = ({
|
||||
studioEndpointUrl,
|
||||
}}
|
||||
/>
|
||||
</Provider>
|
||||
</ErrorBoundary>
|
||||
</ErrorBoundary>
|
||||
</Provider>
|
||||
);
|
||||
|
||||
VideoSelectorPage.defaultProps = {
|
||||
|
||||
@@ -10,6 +10,11 @@ const props = {
|
||||
|
||||
jest.mock('react-redux', () => ({
|
||||
Provider: 'Provider',
|
||||
connect: (mapStateToProps, mapDispatchToProps) => (component) => ({
|
||||
mapStateToProps,
|
||||
mapDispatchToProps,
|
||||
component,
|
||||
}),
|
||||
}));
|
||||
jest.mock('./VideoSelector', () => 'VideoSelector');
|
||||
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Editor Page snapshots props besides blockType default to null 1`] = `
|
||||
<ErrorBoundary>
|
||||
<Provider
|
||||
store={
|
||||
Object {
|
||||
"dispatch": [Function],
|
||||
"getState": [Function],
|
||||
"replaceReducer": [Function],
|
||||
"subscribe": [Function],
|
||||
Symbol(Symbol.observable): [Function],
|
||||
}
|
||||
<Provider
|
||||
store={
|
||||
Object {
|
||||
"dispatch": [Function],
|
||||
"getState": [Function],
|
||||
"replaceReducer": [Function],
|
||||
"subscribe": [Function],
|
||||
Symbol(Symbol.observable): [Function],
|
||||
}
|
||||
}
|
||||
>
|
||||
<ErrorBoundary
|
||||
learningContextId={null}
|
||||
studioEndpointUrl={null}
|
||||
>
|
||||
<Editor
|
||||
blockId={null}
|
||||
@@ -21,22 +24,25 @@ exports[`Editor Page snapshots props besides blockType default to null 1`] = `
|
||||
onClose={null}
|
||||
studioEndpointUrl={null}
|
||||
/>
|
||||
</Provider>
|
||||
</ErrorBoundary>
|
||||
</ErrorBoundary>
|
||||
</Provider>
|
||||
`;
|
||||
|
||||
exports[`Editor Page snapshots rendering correctly with expected Input 1`] = `
|
||||
<ErrorBoundary>
|
||||
<Provider
|
||||
store={
|
||||
Object {
|
||||
"dispatch": [Function],
|
||||
"getState": [Function],
|
||||
"replaceReducer": [Function],
|
||||
"subscribe": [Function],
|
||||
Symbol(Symbol.observable): [Function],
|
||||
}
|
||||
<Provider
|
||||
store={
|
||||
Object {
|
||||
"dispatch": [Function],
|
||||
"getState": [Function],
|
||||
"replaceReducer": [Function],
|
||||
"subscribe": [Function],
|
||||
Symbol(Symbol.observable): [Function],
|
||||
}
|
||||
}
|
||||
>
|
||||
<ErrorBoundary
|
||||
learningContextId="course-v1:edX+DemoX+Demo_Course"
|
||||
studioEndpointUrl="fakeurl.com"
|
||||
>
|
||||
<Editor
|
||||
blockId="block-v1:edX+DemoX+Demo_Course+type@html+block@030e35c4756a4ddc8d40b95fbbfff4d4"
|
||||
@@ -46,6 +52,6 @@ exports[`Editor Page snapshots rendering correctly with expected Input 1`] = `
|
||||
onClose={[MockFunction props.onClose]}
|
||||
studioEndpointUrl="fakeurl.com"
|
||||
/>
|
||||
</Provider>
|
||||
</ErrorBoundary>
|
||||
</ErrorBoundary>
|
||||
</Provider>
|
||||
`;
|
||||
|
||||
@@ -1,45 +1,51 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Video Selector Page snapshots rendering correctly with expected Input 1`] = `
|
||||
<ErrorBoundary>
|
||||
<Provider
|
||||
store={
|
||||
Object {
|
||||
"dispatch": [Function],
|
||||
"getState": [Function],
|
||||
"replaceReducer": [Function],
|
||||
"subscribe": [Function],
|
||||
Symbol(Symbol.observable): [Function],
|
||||
}
|
||||
<Provider
|
||||
store={
|
||||
Object {
|
||||
"dispatch": [Function],
|
||||
"getState": [Function],
|
||||
"replaceReducer": [Function],
|
||||
"subscribe": [Function],
|
||||
Symbol(Symbol.observable): [Function],
|
||||
}
|
||||
}
|
||||
>
|
||||
<ErrorBoundary
|
||||
learningContextId="course-v1:edX+DemoX+Demo_Course"
|
||||
studioEndpointUrl="fakeurl.com"
|
||||
>
|
||||
<Component
|
||||
<VideoSelector
|
||||
learningContextId="course-v1:edX+DemoX+Demo_Course"
|
||||
lmsEndpointUrl="evenfakerurl.com"
|
||||
studioEndpointUrl="fakeurl.com"
|
||||
/>
|
||||
</Provider>
|
||||
</ErrorBoundary>
|
||||
</ErrorBoundary>
|
||||
</Provider>
|
||||
`;
|
||||
|
||||
exports[`Video Selector Page snapshots rendering with props to null 1`] = `
|
||||
<ErrorBoundary>
|
||||
<Provider
|
||||
store={
|
||||
Object {
|
||||
"dispatch": [Function],
|
||||
"getState": [Function],
|
||||
"replaceReducer": [Function],
|
||||
"subscribe": [Function],
|
||||
Symbol(Symbol.observable): [Function],
|
||||
}
|
||||
<Provider
|
||||
store={
|
||||
Object {
|
||||
"dispatch": [Function],
|
||||
"getState": [Function],
|
||||
"replaceReducer": [Function],
|
||||
"subscribe": [Function],
|
||||
Symbol(Symbol.observable): [Function],
|
||||
}
|
||||
}
|
||||
>
|
||||
<ErrorBoundary
|
||||
learningContextId={null}
|
||||
studioEndpointUrl={null}
|
||||
>
|
||||
<Component
|
||||
<VideoSelector
|
||||
learningContextId={null}
|
||||
lmsEndpointUrl={null}
|
||||
studioEndpointUrl={null}
|
||||
/>
|
||||
</Provider>
|
||||
</ErrorBoundary>
|
||||
</ErrorBoundary>
|
||||
</Provider>
|
||||
`;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Button, Container, Row, Col,
|
||||
@@ -6,6 +7,8 @@ import {
|
||||
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import messages from './messages';
|
||||
import { navigateTo } from '../../hooks';
|
||||
import { selectors } from '../../data/redux';
|
||||
|
||||
/**
|
||||
* An error page that displays a generic message for unexpected errors. Also contains a "Try
|
||||
@@ -13,36 +16,74 @@ import messages from './messages';
|
||||
*/
|
||||
export const ErrorPage = ({
|
||||
message,
|
||||
studioEndpointUrl,
|
||||
learningContextId,
|
||||
// redux
|
||||
unitData,
|
||||
// injected
|
||||
intl,
|
||||
}) => (
|
||||
<Container fluid className="py-5 justify-content-center align-items-start text-center">
|
||||
<Row>
|
||||
<Col>
|
||||
<p className="text-muted">
|
||||
{intl.formatMessage(messages.unexpectedError)}
|
||||
</p>
|
||||
{message && (
|
||||
<div role="alert" className="my-4">
|
||||
<p>{message}</p>
|
||||
</div>
|
||||
)}
|
||||
<Button onClick={global.location.reload()}>
|
||||
{intl.formatMessage(messages.unexpectedErrorButtonLabel)}
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
);
|
||||
}) => {
|
||||
const outlineType = learningContextId?.startsWith('library-v1') ? 'library' : 'course';
|
||||
const outlineUrl = `${studioEndpointUrl}/${outlineType}/${learningContextId}`;
|
||||
const unitUrl = unitData?.data ? `${studioEndpointUrl}/container/${unitData?.data.ancestors[0].id}` : null;
|
||||
|
||||
return (
|
||||
<Container fluid className="py-5 justify-content-center align-items-start text-center">
|
||||
<Row>
|
||||
<Col>
|
||||
<p className="text-muted">
|
||||
{intl.formatMessage(messages.unexpectedError)}
|
||||
</p>
|
||||
{message && (
|
||||
<div role="alert" className="my-4">
|
||||
<p>{message}</p>
|
||||
</div>
|
||||
)}
|
||||
<Row className="justify-content-center">
|
||||
{learningContextId && (unitUrl && outlineType !== 'library' ? (
|
||||
<Button className="mr-2" variant="outline-primary" onClick={() => navigateTo(unitUrl)}>
|
||||
{intl.formatMessage(messages.returnToUnitPageLabel)}
|
||||
</Button>
|
||||
) : (
|
||||
<Button className="mr-2" variant="outline-primary" onClick={() => navigateTo(outlineUrl)}>
|
||||
{intl.formatMessage(messages.returnToOutlineLabel, { outlineType })}
|
||||
</Button>
|
||||
))}
|
||||
<Button className="ml-2" onClick={() => global.location.reload()}>
|
||||
{intl.formatMessage(messages.unexpectedErrorButtonLabel)}
|
||||
</Button>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
ErrorPage.propTypes = {
|
||||
message: PropTypes.string,
|
||||
learningContextId: PropTypes.string.isRequired,
|
||||
studioEndpointUrl: PropTypes.string.isRequired,
|
||||
// redux
|
||||
unitData: PropTypes.shape({
|
||||
data: PropTypes.shape({
|
||||
ancestors: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
id: PropTypes.string,
|
||||
}),
|
||||
),
|
||||
}),
|
||||
}),
|
||||
// injected
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
ErrorPage.defaultProps = {
|
||||
message: null,
|
||||
unitData: null,
|
||||
};
|
||||
|
||||
export default injectIntl(ErrorPage);
|
||||
export const mapStateToProps = (state) => ({
|
||||
unitData: selectors.app.unitUrl(state),
|
||||
});
|
||||
|
||||
export default injectIntl(connect(mapStateToProps)(ErrorPage));
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { selectors } from '../../data/redux';
|
||||
import { formatMessage } from '../../../testUtils';
|
||||
import { ErrorPage, mapStateToProps } from './ErrorPage';
|
||||
|
||||
jest.mock('../../data/redux', () => ({
|
||||
selectors: {
|
||||
app: {
|
||||
unitUrl: jest.fn(state => ({ unitUrl: state })),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
describe('Editor Page', () => {
|
||||
const emptyProps = {
|
||||
learningContextId: null,
|
||||
studioEndpointUrl: null,
|
||||
intl: { formatMessage },
|
||||
};
|
||||
const passedProps = {
|
||||
learningContextId: 'course-v1:edX+DemoX+Demo_Course',
|
||||
studioEndpointUrl: 'fakeurl.com',
|
||||
message: 'cUStomMEssagE',
|
||||
intl: { formatMessage },
|
||||
};
|
||||
const unitData = {
|
||||
data: {
|
||||
ancestors: [{ id: 'SomeID' }],
|
||||
},
|
||||
};
|
||||
|
||||
describe('rendered with empty props', () => {
|
||||
it('should only have one button (try again)', () => {
|
||||
const wrapper = shallow(<ErrorPage {...emptyProps} />);
|
||||
const buttonText = wrapper.find('Button').text();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
expect(buttonText).toEqual('Try again');
|
||||
});
|
||||
});
|
||||
|
||||
describe('rendered with pass through props defined', () => {
|
||||
const wrapper = shallow(<ErrorPage {...passedProps} />);
|
||||
describe('shows two buttons', () => {
|
||||
it('the first button should correspond to returning to the course outline', () => {
|
||||
const firstButtonText = wrapper.find('Button').at(0).text();
|
||||
const secondButtonText = wrapper.find('Button').at(1).text();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
expect(firstButtonText).toEqual('Return to course outline');
|
||||
expect(secondButtonText).toEqual('Try again');
|
||||
});
|
||||
it('the first button should correspond to returning to the unit page', () => {
|
||||
const returnToUnitPageWrapper = shallow(<ErrorPage {...passedProps} unitData={unitData} />);
|
||||
expect(returnToUnitPageWrapper).toMatchSnapshot();
|
||||
const firstButtonText = returnToUnitPageWrapper.find('Button').at(0).text();
|
||||
const secondButtonText = returnToUnitPageWrapper.find('Button').at(1).text();
|
||||
expect(returnToUnitPageWrapper).toMatchSnapshot();
|
||||
expect(firstButtonText).toEqual('Return to unit page');
|
||||
expect(secondButtonText).toEqual('Try again');
|
||||
});
|
||||
});
|
||||
it('should have custom message', () => {
|
||||
const customMessageText = wrapper.find('div').children().at(0).text();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
expect(customMessageText).toEqual('cUStomMEssagE');
|
||||
});
|
||||
});
|
||||
describe('mapStateToProps() function', () => {
|
||||
const testState = { A: 'pple', B: 'anana', C: 'ucumber' };
|
||||
test('unitData should equal unitUrl from app.unitUrl', () => {
|
||||
expect(
|
||||
mapStateToProps(testState).unitData,
|
||||
).toEqual(selectors.app.unitUrl(testState));
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,196 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Editor Page rendered with empty props should only have one button (try again) 1`] = `
|
||||
<Container
|
||||
className="py-5 justify-content-center align-items-start text-center"
|
||||
fluid={true}
|
||||
>
|
||||
<Row>
|
||||
<Col>
|
||||
<p
|
||||
className="text-muted"
|
||||
>
|
||||
An unexpected error occurred. Please click the button below to refresh the page.
|
||||
</p>
|
||||
<Row
|
||||
className="justify-content-center"
|
||||
>
|
||||
<Button
|
||||
className="ml-2"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Try again
|
||||
</Button>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
`;
|
||||
|
||||
exports[`Editor Page rendered with pass through props defined should have custom message 1`] = `
|
||||
<Container
|
||||
className="py-5 justify-content-center align-items-start text-center"
|
||||
fluid={true}
|
||||
>
|
||||
<Row>
|
||||
<Col>
|
||||
<p
|
||||
className="text-muted"
|
||||
>
|
||||
An unexpected error occurred. Please click the button below to refresh the page.
|
||||
</p>
|
||||
<div
|
||||
className="my-4"
|
||||
role="alert"
|
||||
>
|
||||
<p>
|
||||
cUStomMEssagE
|
||||
</p>
|
||||
</div>
|
||||
<Row
|
||||
className="justify-content-center"
|
||||
>
|
||||
<Button
|
||||
className="mr-2"
|
||||
onClick={[Function]}
|
||||
variant="outline-primary"
|
||||
>
|
||||
Return to course outline
|
||||
</Button>
|
||||
<Button
|
||||
className="ml-2"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Try again
|
||||
</Button>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
`;
|
||||
|
||||
exports[`Editor Page rendered with pass through props defined shows two buttons the first button should correspond to returning to the course outline 1`] = `
|
||||
<Container
|
||||
className="py-5 justify-content-center align-items-start text-center"
|
||||
fluid={true}
|
||||
>
|
||||
<Row>
|
||||
<Col>
|
||||
<p
|
||||
className="text-muted"
|
||||
>
|
||||
An unexpected error occurred. Please click the button below to refresh the page.
|
||||
</p>
|
||||
<div
|
||||
className="my-4"
|
||||
role="alert"
|
||||
>
|
||||
<p>
|
||||
cUStomMEssagE
|
||||
</p>
|
||||
</div>
|
||||
<Row
|
||||
className="justify-content-center"
|
||||
>
|
||||
<Button
|
||||
className="mr-2"
|
||||
onClick={[Function]}
|
||||
variant="outline-primary"
|
||||
>
|
||||
Return to course outline
|
||||
</Button>
|
||||
<Button
|
||||
className="ml-2"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Try again
|
||||
</Button>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
`;
|
||||
|
||||
exports[`Editor Page rendered with pass through props defined shows two buttons the first button should correspond to returning to the unit page 1`] = `
|
||||
<Container
|
||||
className="py-5 justify-content-center align-items-start text-center"
|
||||
fluid={true}
|
||||
>
|
||||
<Row>
|
||||
<Col>
|
||||
<p
|
||||
className="text-muted"
|
||||
>
|
||||
An unexpected error occurred. Please click the button below to refresh the page.
|
||||
</p>
|
||||
<div
|
||||
className="my-4"
|
||||
role="alert"
|
||||
>
|
||||
<p>
|
||||
cUStomMEssagE
|
||||
</p>
|
||||
</div>
|
||||
<Row
|
||||
className="justify-content-center"
|
||||
>
|
||||
<Button
|
||||
className="mr-2"
|
||||
onClick={[Function]}
|
||||
variant="outline-primary"
|
||||
>
|
||||
Return to unit page
|
||||
</Button>
|
||||
<Button
|
||||
className="ml-2"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Try again
|
||||
</Button>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
`;
|
||||
|
||||
exports[`Editor Page rendered with pass through props defined shows two buttons the first button should correspond to returning to the unit page 2`] = `
|
||||
<Container
|
||||
className="py-5 justify-content-center align-items-start text-center"
|
||||
fluid={true}
|
||||
>
|
||||
<Row>
|
||||
<Col>
|
||||
<p
|
||||
className="text-muted"
|
||||
>
|
||||
An unexpected error occurred. Please click the button below to refresh the page.
|
||||
</p>
|
||||
<div
|
||||
className="my-4"
|
||||
role="alert"
|
||||
>
|
||||
<p>
|
||||
cUStomMEssagE
|
||||
</p>
|
||||
</div>
|
||||
<Row
|
||||
className="justify-content-center"
|
||||
>
|
||||
<Button
|
||||
className="mr-2"
|
||||
onClick={[Function]}
|
||||
variant="outline-primary"
|
||||
>
|
||||
Return to unit page
|
||||
</Button>
|
||||
<Button
|
||||
className="ml-2"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Try again
|
||||
</Button>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
`;
|
||||
@@ -16,7 +16,9 @@ import ErrorPage from './ErrorPage';
|
||||
export default class ErrorBoundary extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { hasError: false };
|
||||
this.state = {
|
||||
hasError: false,
|
||||
};
|
||||
}
|
||||
|
||||
static getDerivedStateFromError() {
|
||||
@@ -30,7 +32,12 @@ export default class ErrorBoundary extends Component {
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
return <ErrorPage />;
|
||||
return (
|
||||
<ErrorPage
|
||||
learningContextId={this.props.learningContextId}
|
||||
studioEndpointUrl={this.props.studioEndpointUrl}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
@@ -39,8 +46,12 @@ export default class ErrorBoundary extends Component {
|
||||
|
||||
ErrorBoundary.propTypes = {
|
||||
children: PropTypes.node,
|
||||
learningContextId: PropTypes.string,
|
||||
studioEndpointUrl: PropTypes.string,
|
||||
};
|
||||
|
||||
ErrorBoundary.defaultProps = {
|
||||
children: null,
|
||||
learningContextId: null,
|
||||
studioEndpointUrl: null,
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@ jest.mock('@edx/frontend-platform/logging', () => ({
|
||||
}));
|
||||
|
||||
// stubbing this to avoid needing to inject a stubbed intl into an internal component
|
||||
jest.mock('./ErrorPage', () => () => <div />);
|
||||
jest.mock('./ErrorPage', () => () => <p>Error Page</p>);
|
||||
|
||||
describe('ErrorBoundary', () => {
|
||||
it('should render children if no error', () => {
|
||||
@@ -21,8 +21,9 @@ describe('ErrorBoundary', () => {
|
||||
</ErrorBoundary>
|
||||
);
|
||||
const wrapper = mount(component);
|
||||
|
||||
const element = wrapper.find('div');
|
||||
|
||||
expect(logError).toHaveBeenCalledTimes(0);
|
||||
expect(element.text()).toEqual('Yay');
|
||||
});
|
||||
|
||||
@@ -35,8 +36,10 @@ describe('ErrorBoundary', () => {
|
||||
<ExplodingComponent />
|
||||
</ErrorBoundary>
|
||||
);
|
||||
mount(component);
|
||||
const wrapper = mount(component);
|
||||
const element = wrapper.find('p');
|
||||
expect(logError).toHaveBeenCalledTimes(1);
|
||||
expect(logError).toHaveBeenCalledWith(new Error('booyah'), { stack: '\n in ExplodingComponent\n in ErrorBoundary (created by WrapperComponent)\n in WrapperComponent' });
|
||||
expect(element.text()).toEqual('Error Page');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,6 +11,16 @@ const messages = defineMessages({
|
||||
defaultMessage: 'Try again',
|
||||
description: 'text for button that tries to reload the app by refreshing the page',
|
||||
},
|
||||
returnToUnitPageLabel: {
|
||||
id: 'unexpected.error.returnToUnitPage.button.text',
|
||||
defaultMessage: 'Return to unit page',
|
||||
description: 'Text for button that navigates back to the unit page',
|
||||
},
|
||||
returnToOutlineLabel: {
|
||||
id: 'unexpected.error.returnToCourseOutline.button.text',
|
||||
defaultMessage: 'Return to {outlineType} outline',
|
||||
description: 'Text for button that navigates back to the course outline',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
|
||||
Reference in New Issue
Block a user