refactor ChannelLink and add test into it (#2280)
This commit is contained in:
parent
7a65d83894
commit
b763c92fc1
5 changed files with 174 additions and 23 deletions
|
|
@ -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>
|
||||
`;
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
75
app/components/channel_link/channel_link.test.js
Normal file
75
app/components/channel_link/channel_link.test.js
Normal 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);
|
||||
});
|
||||
});
|
||||
21
app/components/channel_link/channel_link_utils.js
Normal file
21
app/components/channel_link/channel_link_utils.js
Normal 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;
|
||||
}
|
||||
46
app/components/channel_link/channel_link_utils.test.js
Normal file
46
app/components/channel_link/channel_link_utils.test.js
Normal 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);
|
||||
});
|
||||
}
|
||||
});
|
||||
Loading…
Reference in a new issue