diff --git a/app/components/__mocks__/react.js b/app/components/__mocks__/react.js
new file mode 100644
index 000000000..96927d51e
--- /dev/null
+++ b/app/components/__mocks__/react.js
@@ -0,0 +1,6 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import * as React from 'react';
+
+module.exports = {...React, memo: (x) => x};
diff --git a/app/components/__snapshots__/fade.test.js.snap b/app/components/__snapshots__/fade.test.js.snap
new file mode 100644
index 000000000..d576df934
--- /dev/null
+++ b/app/components/__snapshots__/fade.test.js.snap
@@ -0,0 +1,39 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Fade should render {opacity: 0} 1`] = `
+
+
+ text
+
+
+`;
+
+exports[`Fade should render {opacity: 1} 1`] = `
+
+
+ text
+
+
+`;
diff --git a/app/components/__snapshots__/send_button.test.js.snap b/app/components/__snapshots__/send_button.test.js.snap
new file mode 100644
index 000000000..37886e755
--- /dev/null
+++ b/app/components/__snapshots__/send_button.test.js.snap
@@ -0,0 +1,103 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`SendButton should change theme backgroundColor to 0.3 opacity 1`] = `
+
+
+
+
+
+`;
+
+exports[`SendButton should match snapshot 1`] = `
+
+
+
+
+
+`;
+
+exports[`SendButton should render theme backgroundColor 1`] = `
+
+
+
+
+
+`;
diff --git a/app/components/fade.js b/app/components/fade.js
new file mode 100644
index 000000000..4e132fdd2
--- /dev/null
+++ b/app/components/fade.js
@@ -0,0 +1,51 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React, {PureComponent} from 'react';
+import PropTypes from 'prop-types';
+import {Animated} from 'react-native';
+
+export const FADE_DURATION = 300;
+
+export default class Fade extends PureComponent {
+ static propTypes = {
+ children: PropTypes.node.isRequired,
+ style: PropTypes.object,
+ visible: PropTypes.bool.isRequired,
+ };
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ fadeAnim: new Animated.Value(props.visible ? 1 : 0),
+ };
+ }
+
+ componentDidUpdate(prevProps) {
+ if (prevProps.visible !== this.props.visible) {
+ Animated.timing(
+ this.state.fadeAnim,
+ {
+ toValue: prevProps.visible ? 0 : 1,
+ duration: FADE_DURATION,
+ }
+ ).start();
+ }
+ }
+
+ render() {
+ const {fadeAnim} = this.state;
+
+ return (
+
+ {this.props.children}
+
+ );
+ }
+}
diff --git a/app/components/fade.test.js b/app/components/fade.test.js
new file mode 100644
index 000000000..ea921be73
--- /dev/null
+++ b/app/components/fade.test.js
@@ -0,0 +1,78 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React from 'react';
+import {Animated, Text} from 'react-native';
+import {shallow} from 'enzyme';
+
+import Fade, {FADE_DURATION} from './fade';
+
+jest.useFakeTimers();
+
+describe('Fade', () => {
+ const baseProps = {
+ visible: true,
+ disabled: true,
+ };
+
+ function getWrapper(props = {}) {
+ const dummyText = 'text';
+
+ return shallow(
+
+ {dummyText}
+
+ );
+ }
+
+ function getAnimValue(begin, end) {
+ const animValue = new Animated.Value(begin);
+
+ animValue.setValue(end);
+ animValue.stopTracking();
+
+ return animValue;
+ }
+
+ test('should render {opacity: 1}', () => {
+ const wrapper = getWrapper({visible: true});
+
+ expect(wrapper.getElement()).toMatchSnapshot();
+ expect(wrapper).toHaveStyle('opacity', new Animated.Value(1));
+ });
+
+ test('should render {opacity: 0}', () => {
+ const wrapper = getWrapper({visible: false});
+
+ expect(wrapper.getElement()).toMatchSnapshot();
+ expect(wrapper).toHaveStyle('opacity', new Animated.Value(0));
+ });
+
+ test('should change opacity from 1 to 0', () => {
+ const wrapper = getWrapper({visible: true});
+
+ expect(wrapper).toHaveStyle('opacity', new Animated.Value(1));
+ wrapper.setProps({visible: false});
+ jest.advanceTimersByTime(FADE_DURATION);
+ expect(wrapper).toHaveStyle('opacity', getAnimValue(1, 0));
+ });
+
+ test('should not change opacity when disabled flag is switched', () => {
+ const wrapper = getWrapper({disabled: false});
+
+ expect(wrapper).toHaveStyle('opacity', new Animated.Value(1));
+ wrapper.setProps({disabled: true});
+ expect(wrapper).toHaveStyle('opacity', new Animated.Value(1));
+ });
+
+ test('should not change opacity when props stay the same', () => {
+ const wrapper = getWrapper({visible: true});
+
+ expect(wrapper).toHaveStyle('opacity', new Animated.Value(1));
+ wrapper.setProps({visible: true});
+ expect(wrapper).toHaveStyle('opacity', new Animated.Value(1));
+ });
+});
diff --git a/app/components/post_textbox/post_textbox.js b/app/components/post_textbox/post_textbox.js
index 333cd36e1..8e1e7f5cf 100644
--- a/app/components/post_textbox/post_textbox.js
+++ b/app/components/post_textbox/post_textbox.js
@@ -3,7 +3,7 @@
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
-import {Alert, BackHandler, Keyboard, Platform, Text, TextInput, TouchableOpacity, View} from 'react-native';
+import {Alert, BackHandler, Keyboard, Platform, Text, TextInput, View} from 'react-native';
import {intlShape} from 'react-intl';
import Button from 'react-native-button';
import {General, RequestStatus} from 'mattermost-redux/constants';
@@ -12,6 +12,7 @@ import {getFormattedFileSize} from 'mattermost-redux/utils/file_utils';
import AttachmentButton from 'app/components/attachment_button';
import Autocomplete from 'app/components/autocomplete';
+import Fade from 'app/components/fade';
import FileUploadPreview from 'app/components/file_upload_preview';
import {INITIAL_HEIGHT, INSERT_TO_COMMENT, INSERT_TO_DRAFT, IS_REACTION_REGEX, MAX_CONTENT_HEIGHT, MAX_FILE_COUNT} from 'app/constants/post_textbox';
import {confirmOutOfOfficeDisabled} from 'app/utils/status';
@@ -19,14 +20,13 @@ import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
import {t} from 'app/utils/i18n';
import FormattedMarkdownText from 'app/components/formatted_markdown_text';
import FormattedText from 'app/components/formatted_text';
+import SendButton from 'app/components/send_button';
import Typing from './components/typing';
const AUTOCOMPLETE_MARGIN = 20;
const AUTOCOMPLETE_MAX_HEIGHT = 200;
-let PaperPlane = null;
-
export default class PostTextbox extends PureComponent {
static propTypes = {
actions: PropTypes.shape({
@@ -122,21 +122,19 @@ export default class PostTextbox extends PureComponent {
canSend = () => {
const {files, maxMessageLength, uploadFileRequestStatus} = this.props;
const {value} = this.state;
- const valueLength = value.trim().length;
+ const messageLength = value.trim().length;
- if (files.length) {
- const filesLoading = [];
- files.forEach((file) => {
- if (file.loading) {
- filesLoading.push(file);
- }
- });
-
- const loadingComplete = filesLoading.length === 0;
- return valueLength <= maxMessageLength && uploadFileRequestStatus !== RequestStatus.STARTED && loadingComplete;
+ if (messageLength > maxMessageLength) {
+ return false;
}
- return valueLength > 0 && valueLength <= maxMessageLength;
+ if (files.length) {
+ const loadingComplete = !this.isFileLoading();
+ const alreadySendingFiles = uploadFileRequestStatus === RequestStatus.STARTED;
+ return loadingComplete && !alreadySendingFiles;
+ }
+
+ return messageLength > 0;
};
changeDraft = (text) => {
@@ -294,52 +292,15 @@ export default class PostTextbox extends PureComponent {
this.props.actions.initUploadFiles(images, this.props.rootId);
};
- renderSendButton = () => {
- const {files, theme} = this.props;
- const style = getStyleSheet(theme);
+ isFileLoading() {
+ const {files} = this.props;
- const canSend = this.canSend();
- const imagesLoading = files.filter((f) => f.loading).length > 0;
+ return files.some((file) => file.loading);
+ }
- let button = null;
-
- if (canSend || imagesLoading) {
- if (!PaperPlane) {
- PaperPlane = require('app/components/paper_plane').default;
- }
-
- const icon = (
-
- );
-
- if (imagesLoading) {
- button = (
-
-
- {icon}
-
-
- );
- } else if (canSend) {
- button = (
-
-
- {icon}
-
-
- );
- }
- }
-
- return button;
- };
+ isSendButtonVisible() {
+ return this.canSend() || this.isFileLoading();
+ }
sendMessage = () => {
const {actions, currentUserId, channelId, files, rootId} = this.props;
@@ -644,7 +605,13 @@ export default class PostTextbox extends PureComponent {
disableFullscreenUI={true}
editable={!channelIsReadOnly}
/>
- {this.renderSendButton()}
+
+
+
)}
@@ -656,9 +623,6 @@ export default class PostTextbox extends PureComponent {
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
return {
- disableButton: {
- backgroundColor: changeOpacity(theme.buttonBg, 0.3),
- },
input: {
color: '#000',
flex: 1,
@@ -708,19 +672,6 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
marginLeft: 10,
marginRight: 10,
},
- sendButtonContainer: {
- justifyContent: 'flex-end',
- paddingHorizontal: 5,
- paddingVertical: 3,
- },
- sendButton: {
- backgroundColor: theme.buttonBg,
- borderRadius: 18,
- height: 28,
- width: 28,
- alignItems: 'center',
- justifyContent: 'center',
- },
archivedWrapper: {
paddingLeft: 20,
paddingRight: 20,
diff --git a/app/components/send_button.js b/app/components/send_button.js
new file mode 100644
index 000000000..b508e57aa
--- /dev/null
+++ b/app/components/send_button.js
@@ -0,0 +1,78 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React, {memo} from 'react';
+import {TouchableOpacity, View} from 'react-native';
+
+import PropTypes from 'prop-types';
+
+import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
+
+let PaperPlane = null;
+
+function SendButton(props) {
+ const {theme} = props;
+ const style = getStyleSheet(theme);
+
+ if (!PaperPlane) {
+ PaperPlane = require('app/components/paper_plane').default;
+ }
+
+ const icon = (
+
+ );
+
+ if (props.disabled) {
+ return (
+
+
+ {icon}
+
+
+ );
+ }
+
+ return (
+
+
+ {icon}
+
+
+ );
+}
+
+SendButton.propTypes = {
+ handleSendMessage: PropTypes.func.isRequired,
+ disabled: PropTypes.bool.isRequired,
+ theme: PropTypes.object.isRequired,
+};
+
+const getStyleSheet = makeStyleSheetFromTheme((theme) => {
+ return {
+ disableButton: {
+ backgroundColor: changeOpacity(theme.buttonBg, 0.3),
+ },
+ sendButtonContainer: {
+ justifyContent: 'flex-end',
+ paddingHorizontal: 5,
+ paddingVertical: 3,
+ },
+ sendButton: {
+ backgroundColor: theme.buttonBg,
+ borderRadius: 18,
+ height: 28,
+ width: 28,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ };
+});
+
+export default memo(SendButton);
diff --git a/app/components/send_button.test.js b/app/components/send_button.test.js
new file mode 100644
index 000000000..cb205ffce
--- /dev/null
+++ b/app/components/send_button.test.js
@@ -0,0 +1,47 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React from 'react';
+import {shallow} from 'enzyme';
+
+import Preferences from 'mattermost-redux/constants/preferences';
+
+import SendButton from 'app/components/send_button';
+import {changeOpacity} from 'app/utils/theme';
+
+describe('SendButton', () => {
+ const baseProps = {
+ theme: Preferences.THEMES.default,
+ handleSendMessage: jest.fn(),
+ disabled: false,
+ };
+
+ function getWrapper(props = {}) {
+ return shallow(
+
+ );
+ }
+
+ test('should match snapshot', () => {
+ const wrapper = getWrapper();
+
+ expect(wrapper.getElement()).toMatchSnapshot();
+ });
+
+ test('should render theme backgroundColor', () => {
+ const wrapper = getWrapper();
+
+ expect(wrapper.getElement()).toMatchSnapshot();
+ expect(wrapper.childAt(0)).toHaveStyle('backgroundColor', baseProps.theme.buttonBg);
+ });
+
+ test('should change theme backgroundColor to 0.3 opacity', () => {
+ const wrapper = getWrapper({disabled: true});
+
+ expect(wrapper.getElement()).toMatchSnapshot();
+ expect(wrapper.childAt(0)).toHaveStyle('backgroundColor', changeOpacity(baseProps.theme.buttonBg, 0.3));
+ });
+});
diff --git a/package-lock.json b/package-lock.json
index 487b0af0a..970dc516d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1974,7 +1974,7 @@
},
"array-equal": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz",
+ "resolved": "http://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz",
"integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=",
"dev": true
},
@@ -2700,6 +2700,7 @@
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true,
+ "optional": true,
"requires": {
"is-extendable": "^0.1.0"
}
@@ -2744,7 +2745,8 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"is-glob": {
"version": "4.0.0",
@@ -2798,6 +2800,12 @@
"integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
"dev": true
},
+ "circular-json-es6": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/circular-json-es6/-/circular-json-es6-2.0.2.tgz",
+ "integrity": "sha512-ODYONMMNb3p658Zv+Pp+/XPa5s6q7afhz3Tzyvo+VRh9WIrJ64J76ZC4GQxnlye/NesTn09jvOiuE8+xxfpwhQ==",
+ "dev": true
+ },
"class-utils": {
"version": "0.3.6",
"resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
@@ -3110,7 +3118,7 @@
"dependencies": {
"core-js": {
"version": "1.2.7",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
+ "resolved": "http://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
"integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
},
"fbjs": {
@@ -3141,7 +3149,7 @@
},
"css-select": {
"version": "1.2.0",
- "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
+ "resolved": "http://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
"integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
"dev": true,
"requires": {
@@ -3228,6 +3236,27 @@
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="
},
+ "deep-equal-ident": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/deep-equal-ident/-/deep-equal-ident-1.1.1.tgz",
+ "integrity": "sha1-BvS4nlNxDNbOpKd4HHqVZkLejck=",
+ "dev": true,
+ "requires": {
+ "lodash.isequal": "^3.0"
+ },
+ "dependencies": {
+ "lodash.isequal": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-3.0.4.tgz",
+ "integrity": "sha1-HDXrO27wzR/1F0Pj6jz3/f/ay2Q=",
+ "dev": true,
+ "requires": {
+ "lodash._baseisequal": "^3.0.0",
+ "lodash._bindcallback": "^3.0.0"
+ }
+ }
+ }
+ },
"deep-freeze": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/deep-freeze/-/deep-freeze-0.0.1.tgz",
@@ -3564,6 +3593,16 @@
"semver": "^5.6.0"
}
},
+ "enzyme-matchers": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/enzyme-matchers/-/enzyme-matchers-7.0.2.tgz",
+ "integrity": "sha512-hsWb4Mw+F0eJ9q6ljTK2RqLwsrdoKfr5IXmKtDaTPeOEFXsVl6L2RX2REdevvn2KJfSxkcKaCGwPldOSc1l9tQ==",
+ "dev": true,
+ "requires": {
+ "circular-json-es6": "^2.0.1",
+ "deep-equal-ident": "^1.1.1"
+ }
+ },
"enzyme-to-json": {
"version": "3.3.5",
"resolved": "https://registry.npmjs.org/enzyme-to-json/-/enzyme-to-json-3.3.5.tgz",
@@ -4131,7 +4170,7 @@
},
"external-editor": {
"version": "2.2.0",
- "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
+ "resolved": "http://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
"integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==",
"requires": {
"chardet": "^0.4.0",
@@ -4322,7 +4361,7 @@
"dependencies": {
"json5": {
"version": "0.5.1",
- "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
+ "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
"dev": true
}
@@ -4784,7 +4823,8 @@
},
"ansi-regex": {
"version": "2.1.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"aproba": {
"version": "1.2.0",
@@ -4802,11 +4842,13 @@
},
"balanced-match": {
"version": "1.0.0",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
+ "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -4819,15 +4861,18 @@
},
"code-point-at": {
"version": "1.1.0",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"concat-map": {
"version": "0.0.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"console-control-strings": {
"version": "1.1.0",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"core-util-is": {
"version": "1.0.2",
@@ -4930,7 +4975,8 @@
},
"inherits": {
"version": "2.0.3",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"ini": {
"version": "1.3.5",
@@ -4940,6 +4986,7 @@
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
+ "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -4952,17 +4999,20 @@
"minimatch": {
"version": "3.0.4",
"bundled": true,
+ "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "0.0.8",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
+ "optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -4979,6 +5029,7 @@
"mkdirp": {
"version": "0.5.1",
"bundled": true,
+ "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -5051,7 +5102,8 @@
},
"number-is-nan": {
"version": "1.0.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"object-assign": {
"version": "4.1.1",
@@ -5061,6 +5113,7 @@
"once": {
"version": "1.4.0",
"bundled": true,
+ "optional": true,
"requires": {
"wrappy": "1"
}
@@ -5136,7 +5189,8 @@
},
"safe-buffer": {
"version": "5.1.2",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -5166,6 +5220,7 @@
"string-width": {
"version": "1.0.2",
"bundled": true,
+ "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -5183,6 +5238,7 @@
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
+ "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -5221,11 +5277,13 @@
},
"wrappy": {
"version": "1.0.2",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"yallist": {
"version": "3.0.3",
- "bundled": true
+ "bundled": true,
+ "optional": true
}
}
},
@@ -7393,6 +7451,15 @@
}
}
},
+ "jest-environment-enzyme": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/jest-environment-enzyme/-/jest-environment-enzyme-7.0.2.tgz",
+ "integrity": "sha512-cBBWX3ZCR4JJR6ml6cTYLH1fdBZ2QEbywY6yrkgTP6OZgE+Nh6Agu0g99uJha2F36+zRFS/xkk8AIEAJvLtzQQ==",
+ "dev": true,
+ "requires": {
+ "jest-environment-jsdom": "^24.0.0"
+ }
+ },
"jest-environment-jsdom": {
"version": "24.0.0",
"resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.0.0.tgz",
@@ -7414,6 +7481,17 @@
"jest-util": "^24.0.0"
}
},
+ "jest-enzyme": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/jest-enzyme/-/jest-enzyme-7.0.2.tgz",
+ "integrity": "sha512-7N9YhFmyPkDcVyvifyWePkJaZQX/wON4D6uD8qmGSc2ZaXjj+fkEPMaZ1+Kqnp75FTHaJZ+NVigpmoQiys+J2w==",
+ "dev": true,
+ "requires": {
+ "enzyme-matchers": "^7.0.2",
+ "enzyme-to-json": "^3.3.0",
+ "jest-environment-enzyme": "^7.0.2"
+ }
+ },
"jest-get-type": {
"version": "24.0.0",
"resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.0.0.tgz",
@@ -9479,7 +9557,7 @@
},
"load-json-file": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
+ "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
"integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
"requires": {
"graceful-fs": "^4.1.2",
@@ -9539,6 +9617,29 @@
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.11.tgz",
"integrity": "sha512-DHb1ub+rMjjrxqlB3H56/6MXtm1lSksDp2rA2cNWjG8mlDUYFhUj3Di2Zn5IwSU87xLv8tNIQ7sSwE/YOX/D/Q=="
},
+ "lodash._baseisequal": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/lodash._baseisequal/-/lodash._baseisequal-3.0.7.tgz",
+ "integrity": "sha1-2AJfdjOdKTQnZ9zIh85cuVpbUfE=",
+ "dev": true,
+ "requires": {
+ "lodash.isarray": "^3.0.0",
+ "lodash.istypedarray": "^3.0.0",
+ "lodash.keys": "^3.0.0"
+ }
+ },
+ "lodash._bindcallback": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz",
+ "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=",
+ "dev": true
+ },
+ "lodash._getnative": {
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
+ "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=",
+ "dev": true
+ },
"lodash.assign": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
@@ -9577,6 +9678,18 @@
"integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=",
"dev": true
},
+ "lodash.isarguments": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
+ "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=",
+ "dev": true
+ },
+ "lodash.isarray": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
+ "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=",
+ "dev": true
+ },
"lodash.isboolean": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
@@ -9585,7 +9698,7 @@
},
"lodash.isempty": {
"version": "4.4.0",
- "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz",
+ "resolved": "http://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz",
"integrity": "sha1-b4bL7di+TsmHvpqvM8loTbGzHn4="
},
"lodash.isequal": {
@@ -9616,6 +9729,23 @@
"integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=",
"dev": true
},
+ "lodash.istypedarray": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.istypedarray/-/lodash.istypedarray-3.0.6.tgz",
+ "integrity": "sha1-yaR3SYYHUB2OhJTSg7h8OSgc72I=",
+ "dev": true
+ },
+ "lodash.keys": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
+ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=",
+ "dev": true,
+ "requires": {
+ "lodash._getnative": "^3.0.0",
+ "lodash.isarguments": "^3.0.0",
+ "lodash.isarray": "^3.0.0"
+ }
+ },
"lodash.once": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
@@ -10160,7 +10290,7 @@
},
"minimist": {
"version": "1.2.0",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
},
"mixin-deep": {
@@ -10184,7 +10314,7 @@
},
"mkdirp": {
"version": "0.5.1",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"requires": {
"minimist": "0.0.8"
@@ -10192,7 +10322,7 @@
"dependencies": {
"minimist": {
"version": "0.0.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
}
}
@@ -11841,7 +11971,7 @@
"dependencies": {
"minimist": {
"version": "0.0.10",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
+ "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
"integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="
},
"wordwrap": {
@@ -11896,14 +12026,14 @@
},
"get-stream": {
"version": "3.0.0",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
}
}
},
"os-tmpdir": {
"version": "1.0.2",
- "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
},
"output-file-sync": {
@@ -12049,7 +12179,7 @@
},
"path-is-absolute": {
"version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"path-is-inside": {
@@ -12099,7 +12229,7 @@
},
"pify": {
"version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
},
"pirates": {
@@ -12825,7 +12955,7 @@
"dependencies": {
"core-js": {
"version": "1.2.7",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
+ "resolved": "http://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
"integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
},
"fbjs": {
@@ -12990,7 +13120,7 @@
},
"readable-stream": {
"version": "2.3.6",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"requires": {
"core-util-is": "~1.0.0",
@@ -13025,7 +13155,8 @@
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
"integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"braces": {
"version": "2.3.2",
@@ -13311,7 +13442,8 @@
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
- "dev": true
+ "dev": true,
+ "optional": true
},
"micromatch": {
"version": "3.1.10",
@@ -13988,7 +14120,7 @@
},
"safe-regex": {
"version": "1.1.0",
- "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+ "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
"requires": {
"ret": "~0.1.10"
@@ -14337,7 +14469,7 @@
"dependencies": {
"async": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/async/-/async-2.0.0.tgz",
+ "resolved": "http://registry.npmjs.org/async/-/async-2.0.0.tgz",
"integrity": "sha1-0JAK04WvE4BFQKEJxCFm4657K50=",
"dev": true,
"requires": {
@@ -14436,7 +14568,7 @@
},
"serialize-error": {
"version": "2.1.0",
- "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz",
+ "resolved": "http://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz",
"integrity": "sha1-ULZ51WNc34Rme9yOWa9OW4HV9go="
},
"serve-static": {
@@ -14557,7 +14689,7 @@
},
"xmlbuilder": {
"version": "8.2.2",
- "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz",
+ "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz",
"integrity": "sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M="
}
}
@@ -14779,7 +14911,7 @@
},
"inquirer": {
"version": "5.2.0",
- "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz",
+ "resolved": "http://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz",
"integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==",
"dev": true,
"requires": {
@@ -15182,7 +15314,7 @@
},
"strip-ansi": {
"version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"requires": {
"ansi-regex": "^2.0.0"
@@ -15195,7 +15327,7 @@
},
"strip-eof": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
},
"strip-json-comments": {
@@ -15400,7 +15532,7 @@
},
"through": {
"version": "2.3.8",
- "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
},
"through2": {
@@ -16141,7 +16273,7 @@
},
"wrap-ansi": {
"version": "2.1.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+ "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
"requires": {
"string-width": "^1.0.1",
diff --git a/package.json b/package.json
index 83135296a..42e42241d 100644
--- a/package.json
+++ b/package.json
@@ -93,6 +93,7 @@
"eslint-plugin-react": "7.12.4",
"jest": "24.1.0",
"jest-cli": "24.1.0",
+ "jest-enzyme": "7.0.2",
"jsdom-global": "3.0.2",
"metro-react-native-babel-preset": "0.51.1",
"mmjstool": "github:mattermost/mattermost-utilities",
@@ -130,7 +131,8 @@
],
"preset": "react-native",
"setupFilesAfterEnv": [
- "/test/setup.js"
+ "/test/setup.js",
+ "/node_modules/jest-enzyme/lib/index.js"
],
"testPathIgnorePatterns": [
"/node_modules/"