From 29b98ec383e47f28e7e190434f872072815cb6cb Mon Sep 17 00:00:00 2001 From: 94117nl Date: Tue, 4 Jul 2017 07:58:45 -0500 Subject: [PATCH] PLT-6445 Migrate add_command.jsx to be pure and use Redux (#6804) * Migrate add_command.jsx to be pure and use redux * Add basic test for AddCommand component --- .../{ => add_command}/add_command.jsx | 85 ++-- .../components/add_command/index.js | 25 ++ webapp/routes/route_integrations.jsx | 2 +- .../__snapshots__/add_command.test.jsx.snap | 396 ++++++++++++++++++ .../integrations/add_command.test.jsx | 30 ++ 5 files changed, 495 insertions(+), 43 deletions(-) rename webapp/components/integrations/components/{ => add_command}/add_command.jsx (93%) create mode 100644 webapp/components/integrations/components/add_command/index.js create mode 100644 webapp/tests/components/integrations/__snapshots__/add_command.test.jsx.snap create mode 100644 webapp/tests/components/integrations/add_command.test.jsx diff --git a/webapp/components/integrations/components/add_command.jsx b/webapp/components/integrations/components/add_command/add_command.jsx similarity index 93% rename from webapp/components/integrations/components/add_command.jsx rename to webapp/components/integrations/components/add_command/add_command.jsx index 2141dda4a6..28f6115f90 100644 --- a/webapp/components/integrations/components/add_command.jsx +++ b/webapp/components/integrations/components/add_command/add_command.jsx @@ -1,4 +1,4 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. import React from 'react'; @@ -6,8 +6,6 @@ import PropTypes from 'prop-types'; import * as Utils from 'utils/utils.jsx'; -import {addCommand} from 'actions/integration_actions.jsx'; - import BackstageHeader from 'components/backstage/components/backstage_header.jsx'; import {FormattedMessage} from 'react-intl'; import FormError from 'components/form_error.jsx'; @@ -18,29 +16,31 @@ import Constants from 'utils/constants.jsx'; const REQUEST_POST = 'P'; const REQUEST_GET = 'G'; -export default class AddCommand extends React.Component { - static get propTypes() { - return { - team: PropTypes.object - }; +export default class AddCommand extends React.PureComponent { + static propTypes = { + + /** + * The team data + */ + team: PropTypes.object, + + /** + * The request state for addCommand action. Contains status and error + */ + addCommandRequest: PropTypes.object.isRequired, + + actions: PropTypes.shape({ + + /** + * The function to call to add new command + */ + addCommand: PropTypes.func.isRequired + }).isRequired } constructor(props) { super(props); - this.handleSubmit = this.handleSubmit.bind(this); - - this.updateDisplayName = this.updateDisplayName.bind(this); - this.updateDescription = this.updateDescription.bind(this); - this.updateTrigger = this.updateTrigger.bind(this); - this.updateUrl = this.updateUrl.bind(this); - this.updateMethod = this.updateMethod.bind(this); - this.updateUsername = this.updateUsername.bind(this); - this.updateIconUrl = this.updateIconUrl.bind(this); - this.updateAutocomplete = this.updateAutocomplete.bind(this); - this.updateAutocompleteHint = this.updateAutocompleteHint.bind(this); - this.updateAutocompleteDescription = this.updateAutocompleteDescription.bind(this); - this.state = { displayName: '', description: '', @@ -58,7 +58,7 @@ export default class AddCommand extends React.Component { }; } - handleSubmit(e) { + handleSubmit = (e) => { e.preventDefault(); if (this.state.saving) { @@ -134,7 +134,8 @@ export default class AddCommand extends React.Component { return; } - if (command.trigger.length < Constants.MIN_TRIGGER_LENGTH || command.trigger.length > Constants.MAX_TRIGGER_LENGTH) { + if (command.trigger.length < Constants.MIN_TRIGGER_LENGTH || + command.trigger.length > Constants.MAX_TRIGGER_LENGTH) { this.setState({ saving: false, clientError: ( @@ -166,75 +167,75 @@ export default class AddCommand extends React.Component { return; } - addCommand( - command, + this.props.actions.addCommand(command).then( (data) => { - browserHistory.push('/' + this.props.team.name + '/integrations/commands/confirm?type=commands&id=' + data.id); - }, - (err) => { - this.setState({ - saving: false, - serverError: err.message - }); + if (data) { + browserHistory.push(`/${this.props.team.name}/integrations/commands/confirm?type=commands&id=${data.id}`); + } else { + this.setState({ + saving: false, + serverError: this.props.addCommandRequest.error.message + }); + } } ); } - updateDisplayName(e) { + updateDisplayName = (e) => { this.setState({ displayName: e.target.value }); } - updateDescription(e) { + updateDescription = (e) => { this.setState({ description: e.target.value }); } - updateTrigger(e) { + updateTrigger = (e) => { this.setState({ trigger: e.target.value }); } - updateUrl(e) { + updateUrl = (e) => { this.setState({ url: e.target.value }); } - updateMethod(e) { + updateMethod = (e) => { this.setState({ method: e.target.value }); } - updateUsername(e) { + updateUsername = (e) => { this.setState({ username: e.target.value }); } - updateIconUrl(e) { + updateIconUrl = (e) => { this.setState({ iconUrl: e.target.value }); } - updateAutocomplete(e) { + updateAutocomplete = (e) => { this.setState({ autocomplete: e.target.checked }); } - updateAutocompleteHint(e) { + updateAutocompleteHint = (e) => { this.setState({ autocompleteHint: e.target.value }); } - updateAutocompleteDescription(e) { + updateAutocompleteDescription = (e) => { this.setState({ autocompleteDescription: e.target.value }); diff --git a/webapp/components/integrations/components/add_command/index.js b/webapp/components/integrations/components/add_command/index.js new file mode 100644 index 0000000000..9ac7db220b --- /dev/null +++ b/webapp/components/integrations/components/add_command/index.js @@ -0,0 +1,25 @@ +// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import {connect} from 'react-redux'; +import {bindActionCreators} from 'redux'; +import {addCommand} from 'mattermost-redux/actions/integrations'; + +import AddCommand from './add_command.jsx'; + +function mapStateToProps(state, ownProps) { + return { + ...ownProps, + addCommandRequest: state.requests.integrations.addCommand + }; +} + +function mapDispatchToProps(dispatch) { + return { + actions: bindActionCreators({ + addCommand + }, dispatch) + }; +} + +export default connect(mapStateToProps, mapDispatchToProps)(AddCommand); diff --git a/webapp/routes/route_integrations.jsx b/webapp/routes/route_integrations.jsx index c7c7497b85..dd3ebe6630 100644 --- a/webapp/routes/route_integrations.jsx +++ b/webapp/routes/route_integrations.jsx @@ -74,7 +74,7 @@ export default { { path: 'add', getComponents: (location, callback) => { - System.import('components/integrations/components/add_command.jsx').then(RouteUtils.importComponentSuccess(callback)); + System.import('components/integrations/components/add_command').then(RouteUtils.importComponentSuccess(callback)); } }, { diff --git a/webapp/tests/components/integrations/__snapshots__/add_command.test.jsx.snap b/webapp/tests/components/integrations/__snapshots__/add_command.test.jsx.snap new file mode 100644 index 0000000000..99e5d7ad83 --- /dev/null +++ b/webapp/tests/components/integrations/__snapshots__/add_command.test.jsx.snap @@ -0,0 +1,396 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`components/integrations/AddCommand should match snapshot 1`] = ` +
+ + + + + + +
+
+
+ +
+ +
+ +
+
+
+
+ +
+ +
+ +
+
+
+
+ +
+ +
+ +
+
+ +
+
+ + + , + } + } + /> +
+
+
+
+ +
+ +
+ +
+
+
+
+ +
+ +
+ +
+
+
+
+ +
+ +
+ +
+
+
+
+ +
+ +
+ +
+
+
+
+ +
+ +
+ +
+
+
+
+ + + + + + + +
+
+
+
+`; diff --git a/webapp/tests/components/integrations/add_command.test.jsx b/webapp/tests/components/integrations/add_command.test.jsx new file mode 100644 index 0000000000..cf8a31e079 --- /dev/null +++ b/webapp/tests/components/integrations/add_command.test.jsx @@ -0,0 +1,30 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import React from 'react'; +import {shallow} from 'enzyme'; + +import * as Utils from 'utils/utils.jsx'; +import AddCommand from 'components/integrations/components/add_command/add_command.jsx'; + +describe('components/integrations/AddCommand', () => { + test('should match snapshot', () => { + function emptyFunction() {} //eslint-disable-line no-empty-function + const teamId = Utils.generateId(); + + const wrapper = shallow( + + ); + expect(wrapper).toMatchSnapshot(); + }); +});