MM-15220 Support generic error message in interactive dialog (#3259)

This commit is contained in:
Paulo Bittencourt 2019-10-02 10:47:24 -04:00 committed by Ben Schumacher
parent 2f65ff853d
commit be4bddc52a
2 changed files with 80 additions and 12 deletions

View file

@ -8,6 +8,7 @@ import {Navigation} from 'react-native-navigation';
import {checkDialogElementForError, checkIfErrorsMatchElements} from 'mattermost-redux/utils/integration_utils';
import ErrorText from 'app/components/error_text';
import StatusBar from 'app/components/status_bar';
import FormattedText from 'app/components/formatted_text';
@ -48,10 +49,13 @@ export default class InteractiveDialog extends PureComponent {
this.state = {
values,
error: null,
errors: {},
isLandscape: this.isLandscape(),
submitting: false,
};
this.scrollView = React.createRef();
}
componentDidMount() {
@ -123,17 +127,29 @@ export default class InteractiveDialog extends PureComponent {
this.submitted = true;
if (!data || !data.errors || Object.keys(data.errors).length === 0) {
let hasErrors = false;
if (data) {
if (data.errors &&
Object.keys(data.errors).length >= 0 &&
checkIfErrorsMatchElements(data.errors, elements)
) {
hasErrors = true;
this.setState({errors: data.errors});
}
if (data.error) {
hasErrors = true;
this.setState({error: data.error});
if (this.scrollView?.current) {
this.scrollView.current.scrollTo({x: 0, y: 0});
}
}
}
if (!hasErrors) {
this.handleHide();
return;
}
if (checkIfErrorsMatchElements(data.errors, elements)) {
this.setState({errors: data.errors});
return;
}
this.handleHide();
}
notifyOnCancelIfNeeded = () => {
@ -168,13 +184,22 @@ export default class InteractiveDialog extends PureComponent {
render() {
const {introductionText, elements, theme} = this.props;
const {errors, isLandscape, values} = this.state;
const {error, errors, isLandscape, values} = this.state;
const style = getStyleFromTheme(theme);
return (
<View style={style.container}>
<ScrollView style={style.scrollView}>
<ScrollView
ref={this.scrollView}
style={style.scrollView}
>
<StatusBar/>
{error && (
<ErrorText
textStyle={style.errorContainer}
error={error}
/>
)}
{Boolean(introductionText) &&
<DialogIntroductionText
value={introductionText}
@ -216,6 +241,12 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
container: {
backgroundColor: changeOpacity(theme.centerChannelColor, 0.03),
},
errorContainer: {
marginTop: 15,
marginLeft: 15,
fontSize: 14,
fontWeight: 'bold',
},
scrollView: {
marginBottom: 20,
marginTop: 10,

View file

@ -7,6 +7,8 @@ import Preferences from 'mattermost-redux/constants/preferences';
import InteractiveDialog from './interactive_dialog';
import ErrorText from 'app/components/error_text';
describe('InteractiveDialog', () => {
const baseProps = {
url: 'http://mattermost.com',
@ -18,7 +20,8 @@ describe('InteractiveDialog', () => {
state: 'somestate',
theme: Preferences.THEMES.default,
actions: {
submitInteractiveDialog: jest.fn(),
submitInteractiveDialog: jest.fn(() => ({})),
dismissModal: jest.fn(),
},
componentId: 'component-id',
};
@ -140,4 +143,38 @@ describe('InteractiveDialog', () => {
expect(baseProps.actions.submitInteractiveDialog).toHaveBeenCalledTimes(1);
expect(baseProps.actions.submitInteractiveDialog).toHaveBeenCalledWith(dialog);
});
describe('generic error message', () => {
test('should show error when submit returns an error', async () => {
const props = {
...baseProps,
actions: {
...baseProps.actions,
submitInteractiveDialog: async () => ({
data: {error: 'This is an error message.'},
}),
},
};
const wrapper = shallow(
<InteractiveDialog {...props}/>
);
wrapper.instance().scrollView = {current: {scrollTo: jest.fn()}};
await wrapper.instance().handleSubmit();
expect(wrapper.find(ErrorText).find({error: 'This is an error message.'})).toHaveLength(1);
expect(wrapper.instance().scrollView.current.scrollTo).toHaveBeenCalledWith({x: 0, y: 0});
});
test('should show no error when submit does not return an error', async () => {
const wrapper = shallow(
<InteractiveDialog {...baseProps}/>
);
wrapper.instance().scrollView = {current: {scrollTo: jest.fn()}};
await wrapper.instance().handleSubmit();
expect(wrapper.find(ErrorText)).not.toExist();
expect(wrapper.instance().scrollView.current.scrollTo).not.toHaveBeenCalled();
});
});
});