refactor ChannelLink and add test into it (#2280)

This commit is contained in:
Saturnino Abril 2018-10-19 19:59:33 +08:00 committed by Elias Nahum
parent 7a65d83894
commit b763c92fc1
5 changed files with 174 additions and 23 deletions

View file

@ -0,0 +1,25 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ChannelLink should match snapshot 1`] = `
<Component
style={
Object {
"color": "#3d3c40",
"fontSize": 15,
"lineHeight": 20,
}
}
>
<Component
onPress={[Function]}
style={
Object {
"color": "#2389d7",
}
}
>
~First Channel
</Component>
</Component>
`;

View file

@ -5,6 +5,8 @@ import React from 'react';
import PropTypes from 'prop-types';
import {Text} from 'react-native';
import {getChannelFromChannelName} from './channel_link_utils';
import CustomPropTypes from 'app/constants/custom_prop_types';
export default class ChannelLink extends React.PureComponent {
@ -24,32 +26,14 @@ export default class ChannelLink extends React.PureComponent {
super(props);
this.state = {
channel: this.getChannelFromChannelName(props),
channel: getChannelFromChannelName(props.channelName, props.channelsByName),
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.channelName !== this.props.channelName || nextProps.channelsByName !== this.props.channelsByName) {
this.setState({
channel: this.getChannelFromChannelName(nextProps),
});
}
}
getChannelFromChannelName(props) {
let channelName = props.channelName;
while (channelName.length > 0) {
if (props.channelsByName[channelName]) {
return props.channelsByName[channelName];
}
// Repeatedly trim off trailing punctuation in case this is at the end of a sentence
if ((/[_-]$/).test(channelName)) {
channelName = channelName.substring(0, channelName.length - 1);
} else {
break;
}
static getDerivedStateFromProps(nextProps, prevState) {
const nextChannel = getChannelFromChannelName(nextProps.channelName, nextProps.channelsByName);
if (nextChannel !== prevState.channel) {
return {channel: nextChannel};
}
return null;

View file

@ -0,0 +1,75 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import {shallow} from 'enzyme';
import {Text} from 'react-native';
import ChannelLink from './channel_link';
describe('ChannelLink', () => {
const channelsByName = {
firstChannel: {id: 'channel_id_1', name: 'firstChannel', display_name: 'First Channel'},
secondChannel: {id: 'channel_id_2', name: 'secondChannel', display_name: 'Second Channel'},
};
const baseProps = {
channelName: 'firstChannel',
linkStyle: {color: '#2389d7'},
onChannelLinkPress: jest.fn(),
textStyle: {color: '#3d3c40', fontSize: 15, lineHeight: 20},
channelsByName,
actions: {
handleSelectChannel: jest.fn(),
setChannelDisplayName: jest.fn(),
},
};
test('should match snapshot', () => {
const wrapper = shallow(
<ChannelLink {...baseProps}/>
);
expect(wrapper.getElement()).toMatchSnapshot();
expect(wrapper.find(Text).length).toBe(2);
// inner text with highlight
let innerText = wrapper.find(Text).last();
expect(innerText.props().onPress).toBeDefined();
expect(innerText.props().style.color).toBe('#2389d7');
expect(innerText.props().children).toContain(channelsByName.firstChannel.display_name);
// text for channel name with punctuation
const punctuation = '-_';
wrapper.setProps({channelName: baseProps.channelName + punctuation});
expect(wrapper.find(Text).length).toBe(2);
innerText = wrapper.find(Text).last();
const outerText = wrapper.find(Text).first();
expect(innerText.props().onPress).toBeDefined();
expect(innerText.props().children).toContain(channelsByName.firstChannel.display_name);
expect(outerText.props().children).toContain(punctuation);
// text for not found channel
const notFoundChannel = 'notFoundChannel';
wrapper.setProps({channelName: notFoundChannel});
expect(wrapper.find(Text).length).toBe(1);
innerText = wrapper.find(Text).first();
expect(innerText.props().children).toContain(notFoundChannel);
expect(innerText.props().onPress).not.toBeDefined();
});
test('should call props.actions and onChannelLinkPress on handlePress', () => {
const wrapper = shallow(
<ChannelLink {...baseProps}/>
);
const channel = channelsByName.firstChannel;
wrapper.setState({channel});
wrapper.instance().handlePress();
expect(baseProps.actions.handleSelectChannel).toHaveBeenCalledTimes(1);
expect(baseProps.actions.handleSelectChannel).toBeCalledWith(channel.id);
expect(baseProps.actions.setChannelDisplayName).toHaveBeenCalledTimes(1);
expect(baseProps.actions.setChannelDisplayName).toBeCalledWith(channel.display_name);
expect(baseProps.onChannelLinkPress).toHaveBeenCalledTimes(1);
expect(baseProps.onChannelLinkPress).toBeCalledWith(channel);
});
});

View file

@ -0,0 +1,21 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
export function getChannelFromChannelName(name, channelsByName) {
let channelName = name;
while (channelName.length > 0) {
if (channelsByName[channelName]) {
return channelsByName[channelName];
}
// Repeatedly trim off trailing punctuation in case this is at the end of a sentence
if ((/[_-]$/).test(channelName)) {
channelName = channelName.substring(0, channelName.length - 1);
} else {
break;
}
}
return null;
}

View file

@ -0,0 +1,46 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {getChannelFromChannelName} from './channel_link_utils';
describe('should match return value on getChannelFromChannelName', () => {
const channelsByName = {
firstChannel: {id: 'channel_id_1', name: 'firstChannel', display_name: 'First Channel'},
secondChannel: {id: 'channel_id_2', name: 'secondChannel', display_name: 'Second Channel'},
};
const testCases = [
{
name: 'regular mention',
input: {channelName: 'firstChannel', channelsByName},
output: channelsByName.firstChannel,
},
{
name: 'another mention',
input: {channelName: 'secondChannel', channelsByName},
output: channelsByName.secondChannel,
},
{
name: 'channel mention with trailing punctuation',
input: {channelName: 'firstChannel-', channelsByName},
output: channelsByName.firstChannel,
},
{
name: 'channel mention with trailing punctuations',
input: {channelName: 'firstChannel-_', channelsByName},
output: channelsByName.firstChannel,
},
{
name: 'channel mention not found in channelsByName',
input: {channelName: 'otherChannel', channelsByName},
output: null,
},
];
for (const testCase of testCases) {
const {name, input, output} = testCase;
test(name, () => {
expect(getChannelFromChannelName(input.channelName, input.channelsByName)).toEqual(output);
});
}
});