From ce5c30e9ca3a4a3b5ce7bb9cbb4678aa3aa0469d Mon Sep 17 00:00:00 2001 From: Courtney Pattison Date: Mon, 29 Apr 2019 07:54:00 -0700 Subject: [PATCH] [MM-9454] Added fade to send button (#2677) * [MM-9454] Added jest-enzyme to devDependencies * [MM-9454] Refactored SendButton as component * [MM-9454] Added fade to SendButton * [MM-9454] Changed Fade to PureComponent --- app/components/__mocks__/react.js | 6 + .../__snapshots__/fade.test.js.snap | 39 ++++ .../__snapshots__/send_button.test.js.snap | 103 +++++++++ app/components/fade.js | 51 +++++ app/components/fade.test.js | 78 +++++++ app/components/post_textbox/post_textbox.js | 103 +++------ app/components/send_button.js | 78 +++++++ app/components/send_button.test.js | 47 ++++ package-lock.json | 212 ++++++++++++++---- package.json | 4 +- 10 files changed, 604 insertions(+), 117 deletions(-) create mode 100644 app/components/__mocks__/react.js create mode 100644 app/components/__snapshots__/fade.test.js.snap create mode 100644 app/components/__snapshots__/send_button.test.js.snap create mode 100644 app/components/fade.js create mode 100644 app/components/fade.test.js create mode 100644 app/components/send_button.js create mode 100644 app/components/send_button.test.js 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/"