MM-11603 Fix select_team ui to have failed request scenario (#2063)

* MM-11603 Fix select_team ui to have failed request scenario

* Change error title and description
This commit is contained in:
Sudheer 2018-09-04 18:18:22 +05:30 committed by Elias Nahum
parent 2d695c2269
commit 0e6ffab1e0
6 changed files with 758 additions and 9 deletions

View file

@ -14,6 +14,19 @@ export default class FailedNetworkAction extends PureComponent {
static propTypes = {
onRetry: PropTypes.func,
theme: PropTypes.object.isRequired,
errorTitle: PropTypes.object,
errorDescription: PropTypes.object,
};
static defaultProps = {
errorTitle: {
id: 'mobile.failed_network_action.title',
defaultMessage: 'No internet connection',
},
errorDescription: {
id: 'mobile.failed_network_action.description',
defaultMessage: 'There seems to be a problem with your internet connection. Make sure you have an active connection and try again.',
},
};
render() {
@ -28,13 +41,13 @@ export default class FailedNetworkAction extends PureComponent {
width={76}
/>
<FormattedText
id='mobile.failed_network_action.title'
defaultMessage='No internet connection'
id={this.props.errorTitle.id}
defaultMessage={this.props.errorTitle.defaultMessage}
style={style.title}
/>
<FormattedText
id='mobile.failed_network_action.description'
defaultMessage='There seems to be a problem with your internet connection. Make sure you have an active connection and try again.'
id={this.props.errorDescription.id}
defaultMessage={this.props.errorDescription.message}
style={style.description}
/>
{onRetry &&

View file

@ -0,0 +1,609 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`SelectTeam should match snapshot for fail of teams 1`] = `
ShallowWrapper {
"length": 1,
Symbol(enzyme.__root__): [Circular],
Symbol(enzyme.__unrendered__): <SelectTeam
actions={
Object {
"getTeams": [Function],
"handleTeamChange": [MockFunction],
"joinTeam": [MockFunction],
"logout": [MockFunction],
"markChannelAsRead": [MockFunction],
}
}
currentChannelId="someId"
currentUrl="test"
joinTeamRequest={Object {}}
navigator={
Object {
"setOnNavigatorEvent": [MockFunction] {
"calls": Array [
Array [
[Function],
],
],
},
}
}
teams={Array []}
teamsRequest={
Object {
"status": "failure",
}
}
theme={Object {}}
userWithoutTeams={false}
/>,
Symbol(enzyme.__renderer__): Object {
"batchedUpdates": [Function],
"getNode": [Function],
"render": [Function],
"simulateEvent": [Function],
"unmount": [Function],
},
Symbol(enzyme.__node__): Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {
"errorDescription": Object {
"defaultMessage": "Make sure you have an active connection and try again.",
"id": "mobile.failed_network_action.shortDescription",
},
"errorTitle": Object {
"defaultMessage": "Team Not Found",
"id": "error.team_not_found.title",
},
"onRetry": [Function],
"theme": Object {},
},
"ref": null,
"rendered": null,
"type": [Function],
},
Symbol(enzyme.__nodes__): Array [
Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {
"errorDescription": Object {
"defaultMessage": "Make sure you have an active connection and try again.",
"id": "mobile.failed_network_action.shortDescription",
},
"errorTitle": Object {
"defaultMessage": "Team Not Found",
"id": "error.team_not_found.title",
},
"onRetry": [Function],
"theme": Object {},
},
"ref": null,
"rendered": null,
"type": [Function],
},
],
Symbol(enzyme.__options__): Object {
"adapter": ReactSixteenAdapter {
"options": Object {
"enableComponentDidUpdateOnSetState": true,
},
},
},
}
`;
exports[`SelectTeam should match snapshot for teams 1`] = `
ShallowWrapper {
"length": 1,
Symbol(enzyme.__root__): [Circular],
Symbol(enzyme.__unrendered__): <SelectTeam
actions={
Object {
"getTeams": [Function],
"handleTeamChange": [MockFunction],
"joinTeam": [MockFunction],
"logout": [MockFunction],
"markChannelAsRead": [MockFunction],
}
}
currentChannelId="someId"
currentUrl="test"
joinTeamRequest={Object {}}
navigator={
Object {
"setOnNavigatorEvent": [MockFunction] {
"calls": Array [
Array [
[Function],
],
],
},
}
}
teams={
Array [
Object {
"id": "kemjcpu9bi877yegqjs18ndp4r",
"invite_id": "ojsnudhqzbfzpk6e4n6ip1hwae",
"name": "test",
},
]
}
teamsRequest={
Object {
"status": "success",
}
}
theme={Object {}}
userWithoutTeams={false}
/>,
Symbol(enzyme.__renderer__): Object {
"batchedUpdates": [Function],
"getNode": [Function],
"render": [Function],
"simulateEvent": [Function],
"unmount": [Function],
},
Symbol(enzyme.__node__): Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {
"children": Array [
<Connect(StatusBar) />,
<Component
style={
Object {
"alignItems": "center",
"flexDirection": "row",
"marginHorizontal": 16,
"marginTop": 20,
}
}
>
<Component
style={
Object {
"marginRight": 15,
}
}
>
<InjectIntl(FormattedText)
defaultMessage="Open teams you can join"
id="mobile.select_team.join_open"
style={
Object {
"color": undefined,
"fontSize": 13,
}
}
/>
</Component>
<Component
style={
Object {
"backgroundColor": undefined,
"height": 1,
"width": "100%",
}
}
/>
</Component>,
<FlatList
data={
Array [
Object {
"id": "kemjcpu9bi877yegqjs18ndp4r",
"invite_id": "ojsnudhqzbfzpk6e4n6ip1hwae",
"name": "test",
},
]
}
disableVirtualization={false}
horizontal={false}
initialNumToRender={10}
keyExtractor={[Function]}
maxToRenderPerBatch={10}
numColumns={1}
onEndReachedThreshold={2}
renderItem={[Function]}
scrollEventThrottle={50}
updateCellsBatchingPeriod={50}
viewabilityConfig={
Object {
"viewAreaCoveragePercentThreshold": 3,
"waitForInteraction": false,
}
}
windowSize={21}
/>,
],
"style": Object {
"backgroundColor": undefined,
"flex": 1,
},
},
"ref": null,
"rendered": Array [
Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {},
"ref": null,
"rendered": null,
"type": [Function],
},
Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {
"children": Array [
<Component
style={
Object {
"marginRight": 15,
}
}
>
<InjectIntl(FormattedText)
defaultMessage="Open teams you can join"
id="mobile.select_team.join_open"
style={
Object {
"color": undefined,
"fontSize": 13,
}
}
/>
</Component>,
<Component
style={
Object {
"backgroundColor": undefined,
"height": 1,
"width": "100%",
}
}
/>,
],
"style": Object {
"alignItems": "center",
"flexDirection": "row",
"marginHorizontal": 16,
"marginTop": 20,
},
},
"ref": null,
"rendered": Array [
Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {
"children": <InjectIntl(FormattedText)
defaultMessage="Open teams you can join"
id="mobile.select_team.join_open"
style={
Object {
"color": undefined,
"fontSize": 13,
}
}
/>,
"style": Object {
"marginRight": 15,
},
},
"ref": null,
"rendered": Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {
"defaultMessage": "Open teams you can join",
"id": "mobile.select_team.join_open",
"style": Object {
"color": undefined,
"fontSize": 13,
},
},
"ref": null,
"rendered": null,
"type": [Function],
},
"type": [Function],
},
Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {
"style": Object {
"backgroundColor": undefined,
"height": 1,
"width": "100%",
},
},
"ref": null,
"rendered": null,
"type": [Function],
},
],
"type": [Function],
},
Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {
"data": Array [
Object {
"id": "kemjcpu9bi877yegqjs18ndp4r",
"invite_id": "ojsnudhqzbfzpk6e4n6ip1hwae",
"name": "test",
},
],
"disableVirtualization": false,
"horizontal": false,
"initialNumToRender": 10,
"keyExtractor": [Function],
"maxToRenderPerBatch": 10,
"numColumns": 1,
"onEndReachedThreshold": 2,
"renderItem": [Function],
"scrollEventThrottle": 50,
"updateCellsBatchingPeriod": 50,
"viewabilityConfig": Object {
"viewAreaCoveragePercentThreshold": 3,
"waitForInteraction": false,
},
"windowSize": 21,
},
"ref": null,
"rendered": null,
"type": [Function],
},
],
"type": [Function],
},
Symbol(enzyme.__nodes__): Array [
Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {
"children": Array [
<Connect(StatusBar) />,
<Component
style={
Object {
"alignItems": "center",
"flexDirection": "row",
"marginHorizontal": 16,
"marginTop": 20,
}
}
>
<Component
style={
Object {
"marginRight": 15,
}
}
>
<InjectIntl(FormattedText)
defaultMessage="Open teams you can join"
id="mobile.select_team.join_open"
style={
Object {
"color": undefined,
"fontSize": 13,
}
}
/>
</Component>
<Component
style={
Object {
"backgroundColor": undefined,
"height": 1,
"width": "100%",
}
}
/>
</Component>,
<FlatList
data={
Array [
Object {
"id": "kemjcpu9bi877yegqjs18ndp4r",
"invite_id": "ojsnudhqzbfzpk6e4n6ip1hwae",
"name": "test",
},
]
}
disableVirtualization={false}
horizontal={false}
initialNumToRender={10}
keyExtractor={[Function]}
maxToRenderPerBatch={10}
numColumns={1}
onEndReachedThreshold={2}
renderItem={[Function]}
scrollEventThrottle={50}
updateCellsBatchingPeriod={50}
viewabilityConfig={
Object {
"viewAreaCoveragePercentThreshold": 3,
"waitForInteraction": false,
}
}
windowSize={21}
/>,
],
"style": Object {
"backgroundColor": undefined,
"flex": 1,
},
},
"ref": null,
"rendered": Array [
Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {},
"ref": null,
"rendered": null,
"type": [Function],
},
Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {
"children": Array [
<Component
style={
Object {
"marginRight": 15,
}
}
>
<InjectIntl(FormattedText)
defaultMessage="Open teams you can join"
id="mobile.select_team.join_open"
style={
Object {
"color": undefined,
"fontSize": 13,
}
}
/>
</Component>,
<Component
style={
Object {
"backgroundColor": undefined,
"height": 1,
"width": "100%",
}
}
/>,
],
"style": Object {
"alignItems": "center",
"flexDirection": "row",
"marginHorizontal": 16,
"marginTop": 20,
},
},
"ref": null,
"rendered": Array [
Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {
"children": <InjectIntl(FormattedText)
defaultMessage="Open teams you can join"
id="mobile.select_team.join_open"
style={
Object {
"color": undefined,
"fontSize": 13,
}
}
/>,
"style": Object {
"marginRight": 15,
},
},
"ref": null,
"rendered": Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {
"defaultMessage": "Open teams you can join",
"id": "mobile.select_team.join_open",
"style": Object {
"color": undefined,
"fontSize": 13,
},
},
"ref": null,
"rendered": null,
"type": [Function],
},
"type": [Function],
},
Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {
"style": Object {
"backgroundColor": undefined,
"height": 1,
"width": "100%",
},
},
"ref": null,
"rendered": null,
"type": [Function],
},
],
"type": [Function],
},
Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {
"data": Array [
Object {
"id": "kemjcpu9bi877yegqjs18ndp4r",
"invite_id": "ojsnudhqzbfzpk6e4n6ip1hwae",
"name": "test",
},
],
"disableVirtualization": false,
"horizontal": false,
"initialNumToRender": 10,
"keyExtractor": [Function],
"maxToRenderPerBatch": 10,
"numColumns": 1,
"onEndReachedThreshold": 2,
"renderItem": [Function],
"scrollEventThrottle": 50,
"updateCellsBatchingPeriod": 50,
"viewabilityConfig": Object {
"viewAreaCoveragePercentThreshold": 3,
"waitForInteraction": false,
},
"windowSize": 21,
},
"ref": null,
"rendered": null,
"type": [Function],
},
],
"type": [Function],
},
],
Symbol(enzyme.__options__): Object {
"adapter": ReactSixteenAdapter {
"options": Object {
"enableComponentDidUpdateOnSetState": true,
},
},
},
}
`;

View file

@ -28,7 +28,7 @@ function mapStateToProps(state) {
}
return {
teamsRequest: state.requests.teams.getMyTeams,
teamsRequest: state.requests.teams.getTeams,
teams: Object.values(getJoinableTeams(state)).sort(sortTeams),
currentChannelId: getCurrentChannelId(state),
joinTeamRequest: state.requests.teams.joinTeam,

View file

@ -15,6 +15,7 @@ import {
import {RequestStatus} from 'mattermost-redux/constants';
import EventEmitter from 'mattermost-redux/utils/event_emitter';
import FailedNetworkAction from 'app/components/failed_network_action';
import FormattedText from 'app/components/formatted_text';
import Loading from 'app/components/loading';
import StatusBar from 'app/components/status_bar';
@ -28,6 +29,16 @@ const VIEWABILITY_CONFIG = ListTypes.VISIBILITY_CONFIG_DEFAULTS;
const TEAMS_PER_PAGE = 200;
const errorTitle = {
id: 'error.team_not_found.title',
defaultMessage: 'Team Not Found',
};
const errorDescription = {
id: 'mobile.failed_network_action.shortDescription',
defaultMessage: 'Make sure you have an active connection and try again.',
};
export default class SelectTeam extends PureComponent {
static propTypes = {
actions: PropTypes.shape({
@ -44,6 +55,7 @@ export default class SelectTeam extends PureComponent {
userWithoutTeams: PropTypes.bool,
teams: PropTypes.array.isRequired,
theme: PropTypes.object,
teamsRequest: PropTypes.object.isRequired,
};
constructor(props) {
@ -57,9 +69,7 @@ export default class SelectTeam extends PureComponent {
}
componentDidMount() {
this.props.actions.getTeams(0, TEAMS_PER_PAGE).then(() => {
this.buildData(this.props);
});
this.getTeams();
}
componentWillReceiveProps(nextProps) {
@ -77,6 +87,14 @@ export default class SelectTeam extends PureComponent {
}
}
getTeams = () => {
this.setState({loading: true});
this.props.actions.getTeams(0, TEAMS_PER_PAGE).then(() => {
this.setState({loading: false});
this.buildData(this.props);
});
}
buildData = (props) => {
if (props.teams.length) {
this.setState({teams: props.teams});
@ -213,10 +231,21 @@ export default class SelectTeam extends PureComponent {
const {teams} = this.state;
const styles = getStyleSheet(theme);
if (this.state.joining) {
if (this.state.joining || this.state.loading) {
return <Loading/>;
}
if (this.props.teamsRequest.status === RequestStatus.FAILURE) {
return (
<FailedNetworkAction
onRetry={this.getTeams}
theme={theme}
errorTitle={errorTitle}
errorDescription={errorDescription}
/>
);
}
return (
<View style={styles.container}>
<StatusBar/>

View file

@ -0,0 +1,97 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import {configure, shallow} from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import {RequestStatus} from 'mattermost-redux/constants';
configure({adapter: new Adapter()});
import SelectTeam from './select_team.js';
jest.mock('rn-fetch-blob', () => ({
fs: {
dirs: {
DocumentDir: () => jest.fn(),
CacheDir: () => jest.fn(),
},
},
}));
jest.mock('rn-fetch-blob/fs', () => ({
dirs: {
DocumentDir: () => jest.fn(),
CacheDir: () => jest.fn(),
},
}));
jest.mock('app/utils/theme', () => {
const original = require.requireActual('app/utils/theme');
return {
...original,
changeOpacity: jest.fn(),
};
});
const getTeams = async () => {
return {
error: {},
};
};
describe('SelectTeam', () => {
const actions = {
getTeams,
handleTeamChange: jest.fn(),
joinTeam: jest.fn(),
logout: jest.fn(),
markChannelAsRead: jest.fn(),
};
const baseProps = {
actions,
currentChannelId: 'someId',
currentUrl: 'test',
joinTeamRequest: {},
navigator: {
setOnNavigatorEvent: jest.fn(),
},
userWithoutTeams: false,
teams: [],
theme: {},
teamsRequest: {
status: RequestStatus.FAILURE,
},
};
test('should match snapshot for fail of teams', async () => {
const wrapper = shallow(
<SelectTeam {...baseProps}/>,
);
expect(wrapper.state('loading')).toEqual(true);
await getTeams();
expect(wrapper.state('loading')).toEqual(false);
wrapper.update();
expect(wrapper).toMatchSnapshot();
});
test('should match snapshot for teams', async () => {
const props = {
...baseProps,
teams: [{
id: 'kemjcpu9bi877yegqjs18ndp4r',
invite_id: 'ojsnudhqzbfzpk6e4n6ip1hwae',
name: 'test',
}],
teamsRequest: {
status: RequestStatus.SUCCESS,
},
};
const wrapper = shallow(
<SelectTeam {...props}/>,
);
await getTeams();
wrapper.update();
expect(wrapper).toMatchSnapshot();
});
});

View file

@ -2455,6 +2455,7 @@
"mobile.failed_network_action.description": "There seems to be a problem with your internet connection. Make sure you have an active connection and try again.",
"mobile.failed_network_action.retry": "Try Again",
"mobile.failed_network_action.title": "No internet connection",
"mobile.failed_network_action.shortDescription": "Make sure you have an active connection and try again.",
"mobile.file_upload.browse": "Browse Files",
"mobile.file_upload.camera": "Take Photo or Video",
"mobile.file_upload.library": "Photo Library",