[MM-10303] Fix scrolling issue on profiles when adding user/s to a channel (#1725)

* fix scrolling issue on profiles when adding user/s to a channel

* use existing emptyFunction at utils/general
This commit is contained in:
Saturnino Abril 2018-06-07 01:00:07 +08:00 committed by Elias Nahum
parent 0910bef8ae
commit 37484f104b
4 changed files with 388 additions and 6 deletions

View file

@ -7,15 +7,19 @@ import Adapter from 'enzyme-adapter-react-16';
configure({adapter: new Adapter()});
import {shallowWithIntl} from 'test/intl-test-helper';
import {emptyFunction} from 'app/utils/general';
import {Posts} from 'mattermost-redux/constants';
import CombinedSystemMessage from './combined_system_message';
/* eslint-disable max-nested-callbacks, no-console */
describe('CombinedSystemMessage', () => {
const baseProps = {
actions: {
getProfilesByIds: () => {}, // eslint-disable-line no-empty-function
getProfilesByIds: emptyFunction,
getProfilesByUsernames: emptyFunction,
},
allUserIds: ['user_id_1', 'user_id_2', 'user_id_3'],
currentUserId: 'user_id_3',
@ -31,7 +35,10 @@ describe('CombinedSystemMessage', () => {
test('should match snapshot', () => {
const props = {
...baseProps,
actions: {getProfilesByIds: jest.fn(() => Promise.resolve({data: true}))},
actions: {
getProfilesByIds: jest.fn(() => Promise.resolve({data: true})),
getProfilesByUsernames: emptyFunction,
},
};
const wrapper = shallowWithIntl(
<CombinedSystemMessage {...props}/>
@ -49,7 +56,10 @@ describe('CombinedSystemMessage', () => {
test('should match snapshot', () => {
const props = {
...baseProps,
actions: {getProfilesByIds: jest.fn(() => Promise.resolve({data: true}))},
actions: {
getProfilesByIds: jest.fn(() => Promise.resolve({data: true})),
getProfilesByUsernames: emptyFunction,
},
};
const localeFormat = {
id: ['combined_system_message.first_user_and_second_user_were', 'combined_system_message.removed_from_team'],

View file

@ -0,0 +1,273 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`CustomList should match snapshot 1`] = `
ShallowWrapper {
"length": 1,
Symbol(enzyme.__root__): [Circular],
Symbol(enzyme.__unrendered__): <CustomList
createSections={[Function]}
data={
Array [
Object {
"username": "username_1",
},
Object {
"username": "username_2",
},
]
}
listInitialSize={0}
listPageSize={0}
listScrollRenderAheadDistance={0}
loading={false}
loadingText={
Object {
"defaultMessage": "Loading Members...",
"id": "mobile.loading_members",
}
}
onListEndReached={[Function]}
onListEndReachedThreshold={0}
onRowPress={[Function]}
onRowSelect={[Function]}
renderRow={[Function]}
searching={false}
selectable={true}
showNoResults={false}
showSections={true}
theme={
Object {
"centerChannelBg": "#aaa",
"centerChannelColor": "#aaa",
}
}
/>,
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 [
<ListViewMock
dataSource={
ListViewDataSource {
"items": 2,
}
}
enableEmptySections={true}
initialListSize={0}
onEndReached={[Function]}
onEndReachedThreshold={0}
pageSize={0}
renderFooter={[Function]}
renderRow={[Function]}
renderScrollComponent={[Function]}
renderSectionHeader={[Function]}
renderSeparator={[Function]}
scrollRenderAheadDistance={0}
style={
Object {
"backgroundColor": "#aaa",
"flex": 1,
}
}
/>,
undefined,
],
"style": Object {
"flex": 1,
},
},
"ref": null,
"rendered": Array [
Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {
"dataSource": ListViewDataSource {
"items": 2,
},
"enableEmptySections": true,
"initialListSize": 0,
"onEndReached": [Function],
"onEndReachedThreshold": 0,
"pageSize": 0,
"renderFooter": [Function],
"renderRow": [Function],
"renderScrollComponent": [Function],
"renderSectionHeader": [Function],
"renderSeparator": [Function],
"scrollRenderAheadDistance": 0,
"style": Object {
"backgroundColor": "#aaa",
"flex": 1,
},
},
"ref": null,
"rendered": null,
"type": [Function],
},
undefined,
],
"type": [Function],
},
Symbol(enzyme.__nodes__): Array [
Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {
"children": Array [
<ListViewMock
dataSource={
ListViewDataSource {
"items": 2,
}
}
enableEmptySections={true}
initialListSize={0}
onEndReached={[Function]}
onEndReachedThreshold={0}
pageSize={0}
renderFooter={[Function]}
renderRow={[Function]}
renderScrollComponent={[Function]}
renderSectionHeader={[Function]}
renderSeparator={[Function]}
scrollRenderAheadDistance={0}
style={
Object {
"backgroundColor": "#aaa",
"flex": 1,
}
}
/>,
undefined,
],
"style": Object {
"flex": 1,
},
},
"ref": null,
"rendered": Array [
Object {
"instance": null,
"key": undefined,
"nodeType": "class",
"props": Object {
"dataSource": ListViewDataSource {
"items": 2,
},
"enableEmptySections": true,
"initialListSize": 0,
"onEndReached": [Function],
"onEndReachedThreshold": 0,
"pageSize": 0,
"renderFooter": [Function],
"renderRow": [Function],
"renderScrollComponent": [Function],
"renderSectionHeader": [Function],
"renderSeparator": [Function],
"scrollRenderAheadDistance": 0,
"style": Object {
"backgroundColor": "#aaa",
"flex": 1,
},
},
"ref": null,
"rendered": null,
"type": [Function],
},
undefined,
],
"type": [Function],
},
],
Symbol(enzyme.__options__): Object {
"adapter": ReactSixteenAdapter {
"options": Object {
"enableComponentDidUpdateOnSetState": true,
},
},
},
}
`;
exports[`CustomList should match snapshot, renderFooter 1`] = `null`;
exports[`CustomList should match snapshot, renderFooter 2`] = `
<Component
style={
Object {
"alignItems": "center",
"backgroundColor": "#aaa",
"height": 70,
"justifyContent": "center",
}
}
>
<InjectIntl(FormattedText)
defaultMessage="Loading Members..."
id="mobile.loading_members"
style={
Object {
"color": "rgba(170,170,170,0.6)",
}
}
/>
</Component>
`;
exports[`CustomList should match snapshot, renderSectionHeader 1`] = `
<Component
style={
Object {
"backgroundColor": "#aaa",
}
}
>
<Component
style={
Object {
"backgroundColor": "rgba(170,170,170,0.07)",
"paddingLeft": 10,
"paddingVertical": 2,
}
}
>
<Text
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
style={
Object {
"color": "#aaa",
"fontWeight": "600",
}
}
>
section_id
</Text>
</Component>
</Component>
`;
exports[`CustomList should match snapshot, renderSeparator 1`] = `
<Component
style={
Object {
"backgroundColor": "rgba(170,170,170,0.1)",
"flex": 1,
"height": 1,
}
}
/>
`;

View file

@ -60,10 +60,9 @@ export default class CustomList extends PureComponent {
newData = this.props.createSections(data);
}
const mergedData = Object.assign({}, newData, this.state.data);
const dataSource = showSections ? this.state.dataSource.cloneWithRowsAndSections(mergedData) : this.state.dataSource.cloneWithRows(mergedData);
const dataSource = showSections ? this.state.dataSource.cloneWithRowsAndSections(newData) : this.state.dataSource.cloneWithRows(newData);
this.setState({
data: mergedData,
data: newData,
dataSource,
});
}

View file

@ -0,0 +1,100 @@
// 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';
configure({adapter: new Adapter()});
import {createMembersSections, loadingText} from 'app/utils/member_list';
import CustomList from './index';
describe('CustomList', () => {
function emptyFunc() {} // eslint-disable-line no-empty-function
const baseProps = {
data: [{username: 'username_1'}, {username: 'username_2'}],
theme: {centerChannelBg: '#aaa', centerChannelColor: '#aaa'},
searching: false,
onListEndReached: emptyFunc,
onListEndReachedThreshold: 0,
loading: false,
loadingText,
listPageSize: 0,
listInitialSize: 0,
listScrollRenderAheadDistance: 0,
showSections: true,
onRowPress: emptyFunc,
selectable: true,
onRowSelect: emptyFunc,
renderRow: emptyFunc,
createSections: createMembersSections,
showNoResults: false,
};
test('should match snapshot', () => {
const wrapper = shallow(
<CustomList {...baseProps}/>
);
expect(wrapper).toMatchSnapshot();
expect(wrapper.state('data')).toEqual({U: baseProps.data});
// on componentWillReceiveProps
const newDataProps = [{username: 'username_1'}, {username: 'username_2'}, {username: 'username_3'}];
wrapper.setProps({data: newDataProps});
expect(wrapper.state('data')).toEqual({U: newDataProps});
});
test('should match return value on buildDataSource', () => {
const props = {...baseProps};
const wrapper = shallow(
<CustomList {...props}/>
);
expect(wrapper.instance().buildDataSource(props).data).toEqual({U: [{username: 'username_1'}, {username: 'username_2'}]});
const newDataProps = [{username: 'aaa_1'}, {username: 'aaa_2'}, {username: 'username_1'}, {username: 'username_2'}, {username: 'username_3'}];
props.data = newDataProps;
expect(wrapper.instance().buildDataSource(props).data).toEqual({
A: [{username: 'aaa_1'}, {username: 'aaa_2'}],
U: [{username: 'username_1'}, {username: 'username_2'}, {username: 'username_3'}],
});
});
test('should match snapshot, renderSectionHeader', () => {
const wrapper = shallow(
<CustomList {...baseProps}/>
);
expect(wrapper.instance().renderSectionHeader([], 'section_id')).toMatchSnapshot();
});
test('should call props.renderRow on renderRow', () => {
const props = {...baseProps, renderRow: jest.fn()};
const wrapper = shallow(
<CustomList {...props}/>
);
wrapper.instance().renderRow({id: 'item_id', selected: true}, 'section_id', 'row_id');
expect(props.renderRow).toHaveBeenCalledTimes(1);
});
test('should match snapshot, renderSeparator', () => {
const wrapper = shallow(
<CustomList {...baseProps}/>
);
expect(wrapper.instance().renderSeparator('section_id', 'row_id')).toMatchSnapshot();
});
test('should match snapshot, renderFooter', () => {
const props = {...baseProps};
const wrapper = shallow(
<CustomList {...props}/>
);
// should return null
expect(wrapper.instance().renderFooter()).toMatchSnapshot();
// should return element
wrapper.setProps({loading: true});
expect(wrapper.instance().renderFooter()).toMatchSnapshot();
});
});