summaryrefslogtreecommitdiffstats
path: root/webapp
diff options
context:
space:
mode:
authorJoram Wilander <jwawilander@gmail.com>2017-05-17 11:29:41 -0400
committerCorey Hulen <corey@hulen.com>2017-05-17 08:29:41 -0700
commit017cd2a9575149bb87f382f441b9c960b6816c9d (patch)
treecc1530ac9ab8796bf67f85eb11fa3aba114fd3df /webapp
parenta84a300947e3995945db2789dbf062c2e18c7b8e (diff)
downloadchat-017cd2a9575149bb87f382f441b9c960b6816c9d.tar.gz
chat-017cd2a9575149bb87f382f441b9c960b6816c9d.tar.bz2
chat-017cd2a9575149bb87f382f441b9c960b6816c9d.zip
PLT-6406 Migrate new channel modal to be pure and use redux (#6416)
* Migrate new channel modal to be pure and use redux * Add component tests
Diffstat (limited to 'webapp')
-rw-r--r--webapp/components/new_channel_flow.jsx2
-rw-r--r--webapp/components/new_channel_modal/index.js21
-rw-r--r--webapp/components/new_channel_modal/new_channel_modal.jsx (renamed from webapp/components/new_channel_modal.jsx)118
-rw-r--r--webapp/package.json1
-rw-r--r--webapp/tests/components/__snapshots__/new_channel_modal.test.jsx.snap733
-rw-r--r--webapp/tests/components/new_channel_modal.test.jsx79
6 files changed, 910 insertions, 44 deletions
diff --git a/webapp/components/new_channel_flow.jsx b/webapp/components/new_channel_flow.jsx
index 91dd04c0c..69c2f1c4c 100644
--- a/webapp/components/new_channel_flow.jsx
+++ b/webapp/components/new_channel_flow.jsx
@@ -5,7 +5,7 @@ import * as Utils from 'utils/utils.jsx';
import TeamStore from 'stores/team_store.jsx';
import {cleanUpUrlable} from 'utils/url.jsx';
-import NewChannelModal from './new_channel_modal.jsx';
+import NewChannelModal from 'components/new_channel_modal';
import ChangeURLModal from './change_url_modal.jsx';
import {FormattedMessage} from 'react-intl';
diff --git a/webapp/components/new_channel_modal/index.js b/webapp/components/new_channel_modal/index.js
new file mode 100644
index 000000000..770084fbb
--- /dev/null
+++ b/webapp/components/new_channel_modal/index.js
@@ -0,0 +1,21 @@
+// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import {connect} from 'react-redux';
+import {getBool} from 'mattermost-redux/selectors/entities/preferences';
+import {isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
+import {isCurrentUserCurrentTeamAdmin} from 'mattermost-redux/selectors/entities/teams';
+import {Preferences} from 'mattermost-redux/constants';
+
+import NewChannelModal from './new_channel_modal.jsx';
+
+function mapStateToProps(state, ownProps) {
+ return {
+ ...ownProps,
+ ctrlSend: getBool(state, Preferences.CATEGORY_ADVANCED_SETTINGS, 'send_on_ctrl_enter'),
+ isTeamAdmin: isCurrentUserCurrentTeamAdmin(state),
+ isSystemAdmin: isCurrentUserSystemAdmin(state)
+ };
+}
+
+export default connect(mapStateToProps)(NewChannelModal);
diff --git a/webapp/components/new_channel_modal.jsx b/webapp/components/new_channel_modal/new_channel_modal.jsx
index 49103b7a8..48c2ddd15 100644
--- a/webapp/components/new_channel_modal.jsx
+++ b/webapp/components/new_channel_modal/new_channel_modal.jsx
@@ -10,26 +10,88 @@ import * as Utils from 'utils/utils.jsx';
import * as ChannelUtils from 'utils/channel_utils.jsx';
import Constants from 'utils/constants.jsx';
-import UserStore from 'stores/user_store.jsx';
-import TeamStore from 'stores/team_store.jsx';
-import PreferenceStore from 'stores/preference_store.jsx';
-
import {FormattedMessage} from 'react-intl';
import {Modal} from 'react-bootstrap';
import React from 'react';
+import PropTypes from 'prop-types';
+
+export default class NewChannelModal extends React.PureComponent {
+ static propTypes = {
+
+ /**
+ * Set whether to show the modal or not
+ */
+ show: PropTypes.bool.isRequired,
+
+ /**
+ * The type of channel to create, 'O' or 'P'
+ */
+ channelType: PropTypes.string.isRequired,
+
+ /**
+ * The data needed to create the channel
+ */
+ channelData: PropTypes.object.isRequired,
+
+ /**
+ * Set to force form submission on CTRL/CMD + ENTER instead of ENTER
+ */
+ ctrlSend: PropTypes.bool,
+
+ /**
+ * Set to show options available to team admins
+ */
+ isTeamAdmin: PropTypes.bool,
+
+ /**
+ * Set to show options available to system admins
+ */
+ isSystemAdmin: PropTypes.bool,
+
+ /**
+ * Server error from failed channel creation
+ */
+ serverError: PropTypes.node,
+
+ /**
+ * Function used to submit the channel
+ */
+ onSubmitChannel: PropTypes.func.isRequired,
+
+ /**
+ * Function to call when modal is dimissed
+ */
+ onModalDismissed: PropTypes.func.isRequired,
+
+ /**
+ * Function to call when modal has exited
+ */
+ onModalExited: PropTypes.func,
+
+ /**
+ * Function to call to switch channel type
+ */
+ onTypeSwitched: PropTypes.func.isRequired,
+
+ /**
+ * Function to call when edit URL button is pressed
+ */
+ onChangeURLPressed: PropTypes.func.isRequired,
+
+ /**
+ * Function to call when channel data is modified
+ */
+ onDataChanged: PropTypes.func.isRequired
+ }
-export default class NewChannelModal extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
this.onEnterKeyDown = this.onEnterKeyDown.bind(this);
- this.onPreferenceChange = this.onPreferenceChange.bind(this);
-
- this.ctrlSend = PreferenceStore.getBool(Constants.Preferences.CATEGORY_ADVANCED_SETTINGS, 'send_on_ctrl_enter');
this.state = {
displayNameError: ''
@@ -53,22 +115,12 @@ export default class NewChannelModal extends React.Component {
if (UserAgent.isInternetExplorer()) {
$('body').addClass('browser--ie');
}
-
- PreferenceStore.addChangeListener(this.onPreferenceChange);
- }
-
- componentWillUnmount() {
- PreferenceStore.removeChangeListener(this.onPreferenceChange);
- }
-
- onPreferenceChange() {
- this.ctrlSend = PreferenceStore.getBool(Constants.Preferences.CATEGORY_ADVANCED_SETTINGS, 'send_on_ctrl_enter');
}
onEnterKeyDown(e) {
- if (this.ctrlSend && e.keyCode === Constants.KeyCodes.ENTER && e.ctrlKey) {
+ if (this.props.ctrlSend && e.keyCode === Constants.KeyCodes.ENTER && e.ctrlKey) {
this.handleSubmit(e);
- } else if (!this.ctrlSend && e.keyCode === Constants.KeyCodes.ENTER && !e.shiftKey && !e.altKey) {
+ } else if (!this.props.ctrlSend && e.keyCode === Constants.KeyCodes.ENTER && !e.shiftKey && !e.altKey) {
this.handleSubmit(e);
}
}
@@ -140,14 +192,13 @@ export default class NewChannelModal extends React.Component {
</a>
);
- const isAdmin = TeamStore.isTeamAdminForCurrentTeam() || UserStore.isSystemAdminForCurrentUser();
- const isSystemAdmin = UserStore.isSystemAdminForCurrentUser();
+ const isAdmin = this.props.isTeamAdmin || this.props.isSystemAdmin;
- if (!ChannelUtils.showCreateOption(Constants.OPEN_CHANNEL, isAdmin, isSystemAdmin)) {
+ if (!ChannelUtils.showCreateOption(Constants.OPEN_CHANNEL, isAdmin, this.props.isSystemAdmin)) {
createPublicChannelLink = null;
}
- if (!ChannelUtils.showCreateOption(Constants.PRIVATE_CHANNEL, isAdmin, isSystemAdmin)) {
+ if (!ChannelUtils.showCreateOption(Constants.PRIVATE_CHANNEL, isAdmin, this.props.isSystemAdmin)) {
createPrivateChannelLink = null;
}
@@ -338,22 +389,3 @@ export default class NewChannelModal extends React.Component {
);
}
}
-
-NewChannelModal.defaultProps = {
- show: false,
- channelType: 'O',
- serverError: null
-};
-NewChannelModal.propTypes = {
- show: React.PropTypes.bool.isRequired,
- channelType: React.PropTypes.string.isRequired,
- channelData: React.PropTypes.object.isRequired,
- serverError: React.PropTypes.node,
- onSubmitChannel: React.PropTypes.func.isRequired,
- onModalDismissed: React.PropTypes.func.isRequired,
- onModalExited: React.PropTypes.func,
- onTypeSwitched: React.PropTypes.func.isRequired,
- onChangeURLPressed: React.PropTypes.func.isRequired,
- onDataChanged: React.PropTypes.func.isRequired
-};
-
diff --git a/webapp/package.json b/webapp/package.json
index 44f1d9386..84f012c55 100644
--- a/webapp/package.json
+++ b/webapp/package.json
@@ -26,6 +26,7 @@
"object-assign": "4.1.1",
"pdfjs-dist": "1.7.363",
"perfect-scrollbar": "0.6.16",
+ "prop-types": "15.5.9",
"react": "15.4.2",
"react-addons-pure-render-mixin": "15.4.2",
"react-bootstrap": "0.30.8",
diff --git a/webapp/tests/components/__snapshots__/new_channel_modal.test.jsx.snap b/webapp/tests/components/__snapshots__/new_channel_modal.test.jsx.snap
new file mode 100644
index 000000000..67194d321
--- /dev/null
+++ b/webapp/tests/components/__snapshots__/new_channel_modal.test.jsx.snap
@@ -0,0 +1,733 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`components/NewChannelModal should match snapshot, modal not showing 1`] = `
+<span>
+ <Modal
+ animation={true}
+ autoFocus={true}
+ backdrop={true}
+ bsClass="modal"
+ bsSize="large"
+ dialogClassName="new-channel__modal"
+ dialogComponentClass={[Function]}
+ enforceFocus={true}
+ keyboard={true}
+ manager={
+ ModalManager {
+ "containers": Array [],
+ "data": Array [],
+ "handleContainerOverflow": true,
+ "hideSiblingNodes": true,
+ "modals": Array [],
+ }
+ }
+ onHide={[Function]}
+ renderBackdrop={[Function]}
+ restoreFocus={true}
+ show={true}
+ >
+ <ModalHeader
+ aria-label="Close"
+ bsClass="modal-header"
+ closeButton={true}
+ >
+ <ModalTitle
+ bsClass="modal-title"
+ componentClass="h4"
+ >
+ <FormattedMessage
+ defaultMessage="New Channel"
+ id="channel_modal.modalTitle"
+ values={Object {}}
+ />
+ </ModalTitle>
+ </ModalHeader>
+ <form
+ className="form-horizontal"
+ role="form"
+ >
+ <ModalBody
+ bsClass="modal-body"
+ componentClass="div"
+ >
+ <div>
+ <div
+ className="modal-intro"
+ >
+ <FormattedMessage
+ defaultMessage="Create a new public channel anyone can join. "
+ id="channel_modal.publicChannel2"
+ values={Object {}}
+ />
+ <a
+ href="#"
+ onClick={[Function]}
+ >
+ <FormattedMessage
+ defaultMessage="Create a private channel"
+ id="channel_modal.privateGroup2"
+ values={Object {}}
+ />
+ </a>
+ </div>
+ </div>
+ <div
+ className="form-group"
+ >
+ <label
+ className="col-sm-3 form__label control-label"
+ >
+ <FormattedMessage
+ defaultMessage="Name"
+ id="channel_modal.name"
+ values={Object {}}
+ />
+ </label>
+ <div
+ className="col-sm-9"
+ >
+ <input
+ autoFocus={true}
+ className="form-control"
+ maxLength={22}
+ onChange={[Function]}
+ placeholder="E.g.: \\"Bugs\\", \\"Marketing\\", \\"客户支持\\""
+ tabIndex="1"
+ type="text"
+ value="testchannel"
+ />
+ <p
+ className="input__help dark"
+ >
+ URL: /testchannel (
+ <a
+ href="#"
+ onClick={[Function]}
+ >
+ <FormattedMessage
+ defaultMessage="Edit"
+ id="channel_modal.edit"
+ values={Object {}}
+ />
+ </a>
+ )
+ </p>
+ </div>
+ </div>
+ <div
+ className="form-group"
+ >
+ <div
+ className="col-sm-3"
+ >
+ <label
+ className="form__label control-label"
+ >
+ <FormattedMessage
+ defaultMessage="Purpose"
+ id="channel_modal.purpose"
+ values={Object {}}
+ />
+ </label>
+ <label
+ className="form__label light"
+ >
+ <FormattedMessage
+ defaultMessage="(optional)"
+ id="channel_modal.optional"
+ values={Object {}}
+ />
+ </label>
+ </div>
+ <div
+ className="col-sm-9"
+ >
+ <textarea
+ className="form-control no-resize"
+ maxLength="250"
+ onChange={[Function]}
+ placeholder="E.g.: \\"A channel to file bugs and improvements\\""
+ rows="4"
+ tabIndex="2"
+ value=""
+ />
+ <p
+ className="input__help"
+ >
+ <FormattedMessage
+ defaultMessage="Describe how this channel should be used."
+ id="channel_modal.descriptionHelp"
+ values={Object {}}
+ />
+ </p>
+ </div>
+ </div>
+ <div
+ className="form-group less"
+ >
+ <div
+ className="col-sm-3"
+ >
+ <label
+ className="form__label control-label"
+ >
+ <FormattedMessage
+ defaultMessage="Header"
+ id="channel_modal.header"
+ values={Object {}}
+ />
+ </label>
+ <label
+ className="form__label light"
+ >
+ <FormattedMessage
+ defaultMessage="(optional)"
+ id="channel_modal.optional"
+ values={Object {}}
+ />
+ </label>
+ </div>
+ <div
+ className="col-sm-9"
+ >
+ <textarea
+ className="form-control no-resize"
+ maxLength="1024"
+ onChange={[Function]}
+ placeholder="E.g.: \\"[Link Title](http://example.com)\\""
+ rows="4"
+ tabIndex="2"
+ value=""
+ />
+ <p
+ className="input__help"
+ >
+ <FormattedMessage
+ defaultMessage="Set text that will appear in the header of the channel beside the channel name. For example, include frequently used links by typing [Link Title](http://example.com)."
+ id="channel_modal.headerHelp"
+ values={Object {}}
+ />
+ </p>
+ </div>
+ </div>
+ </ModalBody>
+ <ModalFooter
+ bsClass="modal-footer"
+ componentClass="div"
+ >
+ <button
+ className="btn btn-default"
+ onClick={[Function]}
+ type="button"
+ >
+ <FormattedMessage
+ defaultMessage="Cancel"
+ id="channel_modal.cancel"
+ values={Object {}}
+ />
+ </button>
+ <button
+ className="btn btn-primary"
+ onClick={[Function]}
+ tabIndex="3"
+ type="submit"
+ >
+ <FormattedMessage
+ defaultMessage="Create New Channel"
+ id="channel_modal.createNew"
+ values={Object {}}
+ />
+ </button>
+ </ModalFooter>
+ </form>
+ </Modal>
+</span>
+`;
+
+exports[`components/NewChannelModal should match snapshot, modal showing 1`] = `
+<span>
+ <Modal
+ animation={true}
+ autoFocus={true}
+ backdrop={true}
+ bsClass="modal"
+ bsSize="large"
+ dialogClassName="new-channel__modal"
+ dialogComponentClass={[Function]}
+ enforceFocus={true}
+ keyboard={true}
+ manager={
+ ModalManager {
+ "containers": Array [],
+ "data": Array [],
+ "handleContainerOverflow": true,
+ "hideSiblingNodes": true,
+ "modals": Array [],
+ }
+ }
+ onHide={[Function]}
+ renderBackdrop={[Function]}
+ restoreFocus={true}
+ show={true}
+ >
+ <ModalHeader
+ aria-label="Close"
+ bsClass="modal-header"
+ closeButton={true}
+ >
+ <ModalTitle
+ bsClass="modal-title"
+ componentClass="h4"
+ >
+ <FormattedMessage
+ defaultMessage="New Channel"
+ id="channel_modal.modalTitle"
+ values={Object {}}
+ />
+ </ModalTitle>
+ </ModalHeader>
+ <form
+ className="form-horizontal"
+ role="form"
+ >
+ <ModalBody
+ bsClass="modal-body"
+ componentClass="div"
+ >
+ <div>
+ <div
+ className="modal-intro"
+ >
+ <FormattedMessage
+ defaultMessage="Create a new public channel anyone can join. "
+ id="channel_modal.publicChannel2"
+ values={Object {}}
+ />
+ <a
+ href="#"
+ onClick={[Function]}
+ >
+ <FormattedMessage
+ defaultMessage="Create a private channel"
+ id="channel_modal.privateGroup2"
+ values={Object {}}
+ />
+ </a>
+ </div>
+ </div>
+ <div
+ className="form-group"
+ >
+ <label
+ className="col-sm-3 form__label control-label"
+ >
+ <FormattedMessage
+ defaultMessage="Name"
+ id="channel_modal.name"
+ values={Object {}}
+ />
+ </label>
+ <div
+ className="col-sm-9"
+ >
+ <input
+ autoFocus={true}
+ className="form-control"
+ maxLength={22}
+ onChange={[Function]}
+ placeholder="E.g.: \\"Bugs\\", \\"Marketing\\", \\"客户支持\\""
+ tabIndex="1"
+ type="text"
+ value="testchannel"
+ />
+ <p
+ className="input__help dark"
+ >
+ URL: /testchannel (
+ <a
+ href="#"
+ onClick={[Function]}
+ >
+ <FormattedMessage
+ defaultMessage="Edit"
+ id="channel_modal.edit"
+ values={Object {}}
+ />
+ </a>
+ )
+ </p>
+ </div>
+ </div>
+ <div
+ className="form-group"
+ >
+ <div
+ className="col-sm-3"
+ >
+ <label
+ className="form__label control-label"
+ >
+ <FormattedMessage
+ defaultMessage="Purpose"
+ id="channel_modal.purpose"
+ values={Object {}}
+ />
+ </label>
+ <label
+ className="form__label light"
+ >
+ <FormattedMessage
+ defaultMessage="(optional)"
+ id="channel_modal.optional"
+ values={Object {}}
+ />
+ </label>
+ </div>
+ <div
+ className="col-sm-9"
+ >
+ <textarea
+ className="form-control no-resize"
+ maxLength="250"
+ onChange={[Function]}
+ placeholder="E.g.: \\"A channel to file bugs and improvements\\""
+ rows="4"
+ tabIndex="2"
+ value=""
+ />
+ <p
+ className="input__help"
+ >
+ <FormattedMessage
+ defaultMessage="Describe how this channel should be used."
+ id="channel_modal.descriptionHelp"
+ values={Object {}}
+ />
+ </p>
+ </div>
+ </div>
+ <div
+ className="form-group less"
+ >
+ <div
+ className="col-sm-3"
+ >
+ <label
+ className="form__label control-label"
+ >
+ <FormattedMessage
+ defaultMessage="Header"
+ id="channel_modal.header"
+ values={Object {}}
+ />
+ </label>
+ <label
+ className="form__label light"
+ >
+ <FormattedMessage
+ defaultMessage="(optional)"
+ id="channel_modal.optional"
+ values={Object {}}
+ />
+ </label>
+ </div>
+ <div
+ className="col-sm-9"
+ >
+ <textarea
+ className="form-control no-resize"
+ maxLength="1024"
+ onChange={[Function]}
+ placeholder="E.g.: \\"[Link Title](http://example.com)\\""
+ rows="4"
+ tabIndex="2"
+ value=""
+ />
+ <p
+ className="input__help"
+ >
+ <FormattedMessage
+ defaultMessage="Set text that will appear in the header of the channel beside the channel name. For example, include frequently used links by typing [Link Title](http://example.com)."
+ id="channel_modal.headerHelp"
+ values={Object {}}
+ />
+ </p>
+ </div>
+ </div>
+ </ModalBody>
+ <ModalFooter
+ bsClass="modal-footer"
+ componentClass="div"
+ >
+ <button
+ className="btn btn-default"
+ onClick={[Function]}
+ type="button"
+ >
+ <FormattedMessage
+ defaultMessage="Cancel"
+ id="channel_modal.cancel"
+ values={Object {}}
+ />
+ </button>
+ <button
+ className="btn btn-primary"
+ onClick={[Function]}
+ tabIndex="3"
+ type="submit"
+ >
+ <FormattedMessage
+ defaultMessage="Create New Channel"
+ id="channel_modal.createNew"
+ values={Object {}}
+ />
+ </button>
+ </ModalFooter>
+ </form>
+ </Modal>
+</span>
+`;
+
+exports[`components/NewChannelModal should match snapshot, private channel filled in header and purpose 1`] = `
+<span>
+ <Modal
+ animation={true}
+ autoFocus={true}
+ backdrop={true}
+ bsClass="modal"
+ bsSize="large"
+ dialogClassName="new-channel__modal"
+ dialogComponentClass={[Function]}
+ enforceFocus={true}
+ keyboard={true}
+ manager={
+ ModalManager {
+ "containers": Array [],
+ "data": Array [],
+ "handleContainerOverflow": true,
+ "hideSiblingNodes": true,
+ "modals": Array [],
+ }
+ }
+ onHide={[Function]}
+ renderBackdrop={[Function]}
+ restoreFocus={true}
+ show={true}
+ >
+ <ModalHeader
+ aria-label="Close"
+ bsClass="modal-header"
+ closeButton={true}
+ >
+ <ModalTitle
+ bsClass="modal-title"
+ componentClass="h4"
+ >
+ <FormattedMessage
+ defaultMessage="New Channel"
+ id="channel_modal.modalTitle"
+ values={Object {}}
+ />
+ </ModalTitle>
+ </ModalHeader>
+ <form
+ className="form-horizontal"
+ role="form"
+ >
+ <ModalBody
+ bsClass="modal-body"
+ componentClass="div"
+ >
+ <div>
+ <div
+ className="modal-intro"
+ >
+ <FormattedMessage
+ defaultMessage="Create a new private channel with restricted membership. "
+ id="channel_modal.privateGroup1"
+ values={Object {}}
+ />
+ <a
+ href="#"
+ onClick={[Function]}
+ >
+ <FormattedMessage
+ defaultMessage="Create a public channel"
+ id="channel_modal.publicChannel1"
+ values={Object {}}
+ />
+ </a>
+ </div>
+ </div>
+ <div
+ className="form-group"
+ >
+ <label
+ className="col-sm-3 form__label control-label"
+ >
+ <FormattedMessage
+ defaultMessage="Name"
+ id="channel_modal.name"
+ values={Object {}}
+ />
+ </label>
+ <div
+ className="col-sm-9"
+ >
+ <input
+ autoFocus={true}
+ className="form-control"
+ maxLength={22}
+ onChange={[Function]}
+ placeholder="E.g.: \\"Bugs\\", \\"Marketing\\", \\"客户支持\\""
+ tabIndex="1"
+ type="text"
+ value="testchannel"
+ />
+ <p
+ className="input__help dark"
+ >
+ URL: /testchannel (
+ <a
+ href="#"
+ onClick={[Function]}
+ >
+ <FormattedMessage
+ defaultMessage="Edit"
+ id="channel_modal.edit"
+ values={Object {}}
+ />
+ </a>
+ )
+ </p>
+ </div>
+ </div>
+ <div
+ className="form-group"
+ >
+ <div
+ className="col-sm-3"
+ >
+ <label
+ className="form__label control-label"
+ >
+ <FormattedMessage
+ defaultMessage="Purpose"
+ id="channel_modal.purpose"
+ values={Object {}}
+ />
+ </label>
+ <label
+ className="form__label light"
+ >
+ <FormattedMessage
+ defaultMessage="(optional)"
+ id="channel_modal.optional"
+ values={Object {}}
+ />
+ </label>
+ </div>
+ <div
+ className="col-sm-9"
+ >
+ <textarea
+ className="form-control no-resize"
+ maxLength="250"
+ onChange={[Function]}
+ placeholder="E.g.: \\"A channel to file bugs and improvements\\""
+ rows="4"
+ tabIndex="2"
+ value="some purpose"
+ />
+ <p
+ className="input__help"
+ >
+ <FormattedMessage
+ defaultMessage="Describe how this channel should be used."
+ id="channel_modal.descriptionHelp"
+ values={Object {}}
+ />
+ </p>
+ </div>
+ </div>
+ <div
+ className="form-group less"
+ >
+ <div
+ className="col-sm-3"
+ >
+ <label
+ className="form__label control-label"
+ >
+ <FormattedMessage
+ defaultMessage="Header"
+ id="channel_modal.header"
+ values={Object {}}
+ />
+ </label>
+ <label
+ className="form__label light"
+ >
+ <FormattedMessage
+ defaultMessage="(optional)"
+ id="channel_modal.optional"
+ values={Object {}}
+ />
+ </label>
+ </div>
+ <div
+ className="col-sm-9"
+ >
+ <textarea
+ className="form-control no-resize"
+ maxLength="1024"
+ onChange={[Function]}
+ placeholder="E.g.: \\"[Link Title](http://example.com)\\""
+ rows="4"
+ tabIndex="2"
+ value="some header"
+ />
+ <p
+ className="input__help"
+ >
+ <FormattedMessage
+ defaultMessage="Set text that will appear in the header of the channel beside the channel name. For example, include frequently used links by typing [Link Title](http://example.com)."
+ id="channel_modal.headerHelp"
+ values={Object {}}
+ />
+ </p>
+ </div>
+ </div>
+ </ModalBody>
+ <ModalFooter
+ bsClass="modal-footer"
+ componentClass="div"
+ >
+ <button
+ className="btn btn-default"
+ onClick={[Function]}
+ type="button"
+ >
+ <FormattedMessage
+ defaultMessage="Cancel"
+ id="channel_modal.cancel"
+ values={Object {}}
+ />
+ </button>
+ <button
+ className="btn btn-primary"
+ onClick={[Function]}
+ tabIndex="3"
+ type="submit"
+ >
+ <FormattedMessage
+ defaultMessage="Create New Channel"
+ id="channel_modal.createNew"
+ values={Object {}}
+ />
+ </button>
+ </ModalFooter>
+ </form>
+ </Modal>
+</span>
+`;
diff --git a/webapp/tests/components/new_channel_modal.test.jsx b/webapp/tests/components/new_channel_modal.test.jsx
new file mode 100644
index 000000000..358a839a3
--- /dev/null
+++ b/webapp/tests/components/new_channel_modal.test.jsx
@@ -0,0 +1,79 @@
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import React from 'react';
+import {shallow} from 'enzyme';
+
+import Constants from 'utils/constants.jsx';
+
+import NewChannelModal from 'components/new_channel_modal/new_channel_modal.jsx';
+
+describe('components/NewChannelModal', () => {
+ afterEach(() => {
+ global.window.mm_config = null;
+ global.window.mm_license = null;
+ });
+
+ test('should match snapshot, modal not showing', () => {
+ function emptyFunction() {} //eslint-disable-line no-empty-function
+
+ global.window.mm_license = {};
+ global.window.mm_license.IsLicensed = 'false';
+
+ const wrapper = shallow(
+ <NewChannelModal
+ show={true}
+ channelType={Constants.OPEN_CHANNEL}
+ channelData={{name: 'testchannel', displayName: 'testchannel', header: '', purpose: ''}}
+ onSubmitChannel={emptyFunction}
+ onModalDismissed={emptyFunction}
+ onTypeSwitched={emptyFunction}
+ onChangeURLPressed={emptyFunction}
+ onDataChanged={emptyFunction}
+ />
+ );
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ test('should match snapshot, modal showing', () => {
+ function emptyFunction() {} //eslint-disable-line no-empty-function
+
+ global.window.mm_license = {};
+ global.window.mm_license.IsLicensed = 'false';
+
+ const wrapper = shallow(
+ <NewChannelModal
+ show={true}
+ channelType={Constants.OPEN_CHANNEL}
+ channelData={{name: 'testchannel', displayName: 'testchannel', header: '', purpose: ''}}
+ onSubmitChannel={emptyFunction}
+ onModalDismissed={emptyFunction}
+ onTypeSwitched={emptyFunction}
+ onChangeURLPressed={emptyFunction}
+ onDataChanged={emptyFunction}
+ />
+ );
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ test('should match snapshot, private channel filled in header and purpose', () => {
+ function emptyFunction() {} //eslint-disable-line no-empty-function
+
+ global.window.mm_license = {};
+ global.window.mm_license.IsLicensed = 'false';
+
+ const wrapper = shallow(
+ <NewChannelModal
+ show={true}
+ channelType={Constants.PRIVATE_CHANNEL}
+ channelData={{name: 'testchannel', displayName: 'testchannel', header: 'some header', purpose: 'some purpose'}}
+ onSubmitChannel={emptyFunction}
+ onModalDismissed={emptyFunction}
+ onTypeSwitched={emptyFunction}
+ onChangeURLPressed={emptyFunction}
+ onDataChanged={emptyFunction}
+ />
+ );
+ expect(wrapper).toMatchSnapshot();
+ });
+});