diff --git a/app/components/post_textbox/components/__snapshots__/camera_button.test.js.snap b/app/components/post_textbox/components/__snapshots__/camera_button.test.js.snap new file mode 100644 index 000000000..e3f79946c --- /dev/null +++ b/app/components/post_textbox/components/__snapshots__/camera_button.test.js.snap @@ -0,0 +1,16 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CameraButton should match snapshot 1`] = ` + + + +`; diff --git a/app/components/post_textbox/components/__snapshots__/file_upload_button.test.js.snap b/app/components/post_textbox/components/__snapshots__/file_upload_button.test.js.snap new file mode 100644 index 000000000..2d07d9c8d --- /dev/null +++ b/app/components/post_textbox/components/__snapshots__/file_upload_button.test.js.snap @@ -0,0 +1,16 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`FileUploadButton should match snapshot 1`] = ` + + + +`; diff --git a/app/components/post_textbox/components/__snapshots__/image_upload_button.test.js.snap b/app/components/post_textbox/components/__snapshots__/image_upload_button.test.js.snap new file mode 100644 index 000000000..80fdc5f7e --- /dev/null +++ b/app/components/post_textbox/components/__snapshots__/image_upload_button.test.js.snap @@ -0,0 +1,16 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ImageUploadButton should match snapshot 1`] = ` + + + +`; diff --git a/app/components/post_textbox/components/cameraButton.js b/app/components/post_textbox/components/camera_button.js similarity index 89% rename from app/components/post_textbox/components/cameraButton.js rename to app/components/post_textbox/components/camera_button.js index 2b1eb1501..5c37a11a3 100644 --- a/app/components/post_textbox/components/cameraButton.js +++ b/app/components/post_textbox/components/camera_button.js @@ -107,9 +107,10 @@ export default class AttachmentButton extends PureComponent { const {formatMessage} = this.context.intl; let permissionRequest; const targetSource = Permissions.PERMISSIONS.IOS.CAMERA; - const hasPermissionToStorage = await Permissions.check(targetSource); + const hasPermission = await Permissions.check(targetSource); - switch (hasPermissionToStorage) { + switch (hasPermission) { + case Permissions.RESULTS.DENIED: case Permissions.RESULTS.UNAVAILABLE: permissionRequest = await Permissions.request(targetSource); if (permissionRequest !== Permissions.RESULTS.AUTHORIZED) { @@ -117,17 +118,13 @@ export default class AttachmentButton extends PureComponent { } break; case Permissions.RESULTS.BLOCKED: { - const canOpenSettings = await Permissions.canOpenSettings(); - let grantOption = null; - if (canOpenSettings) { - grantOption = { - text: formatMessage({ - id: 'mobile.permission_denied_retry', - defaultMessage: 'Settings', - }), - onPress: () => Permissions.openSettings(), - }; - } + const grantOption = { + text: formatMessage({ + id: 'mobile.permission_denied_retry', + defaultMessage: 'Settings', + }), + onPress: () => Permissions.openSettings(), + }; const {title, text} = this.getPermissionDeniedMessage(); diff --git a/app/components/post_textbox/components/camera_button.test.js b/app/components/post_textbox/components/camera_button.test.js new file mode 100644 index 000000000..0ee8b47bd --- /dev/null +++ b/app/components/post_textbox/components/camera_button.test.js @@ -0,0 +1,66 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; +import {Alert} from 'react-native'; +import {shallow} from 'enzyme'; +import Permissions from 'react-native-permissions'; + +import Preferences from 'mattermost-redux/constants/preferences'; + +import CameraButton from './camera_button'; + +jest.mock('react-intl'); +jest.mock('react-native-image-picker', () => ({ + launchCamera: jest.fn(), +})); + +describe('CameraButton', () => { + const formatMessage = jest.fn(); + const baseProps = { + fileCount: 0, + maxFileCount: 5, + onShowFileMaxWarning: jest.fn(), + theme: Preferences.THEMES.default, + uploadFiles: jest.fn(), + buttonContainerStyle: {}, + }; + + test('should match snapshot', () => { + const wrapper = shallow(); + + expect(wrapper.getElement()).toMatchSnapshot(); + }); + + test('should return permission false if permission is denied in iOS', async () => { + jest.spyOn(Permissions, 'check').mockReturnValue(Permissions.RESULTS.UNAVAILABLE); + jest.spyOn(Permissions, 'request').mockReturnValue(Permissions.RESULTS.DENIED); + + const wrapper = shallow( + , + {context: {intl: {formatMessage}}}, + ); + + const hasPermission = await wrapper.instance().hasCameraPermission(); + expect(Permissions.check).toHaveBeenCalled(); + expect(Permissions.request).toHaveBeenCalled(); + expect(Alert.alert).not.toHaveBeenCalled(); + expect(hasPermission).toBe(false); + }); + + test('should show permission denied alert and return permission false if permission is blocked in iOS', async () => { + jest.spyOn(Permissions, 'check').mockReturnValue(Permissions.RESULTS.BLOCKED); + jest.spyOn(Alert, 'alert').mockReturnValue(true); + + const wrapper = shallow( + , + {context: {intl: {formatMessage}}}, + ); + + const hasPermission = await wrapper.instance().hasCameraPermission(); + expect(Permissions.check).toHaveBeenCalled(); + expect(Permissions.request).not.toHaveBeenCalled(); + expect(Alert.alert).toHaveBeenCalled(); + expect(hasPermission).toBe(false); + }); +}); \ No newline at end of file diff --git a/app/components/post_textbox/components/fileUploadButton.js b/app/components/post_textbox/components/file_upload_button.js similarity index 99% rename from app/components/post_textbox/components/fileUploadButton.js rename to app/components/post_textbox/components/file_upload_button.js index e790b6b14..1766cee2a 100644 --- a/app/components/post_textbox/components/fileUploadButton.js +++ b/app/components/post_textbox/components/file_upload_button.js @@ -100,6 +100,7 @@ export default class FileUploadButton extends PureComponent { const hasPermissionToStorage = await Permissions.check(storagePermission); switch (hasPermissionToStorage) { + case Permissions.RESULTS.DENIED: case Permissions.RESULTS.UNAVAILABLE: permissionRequest = await Permissions.request(storagePermission); if (permissionRequest !== Permissions.RESULTS.AUTHORIZED) { diff --git a/app/components/post_textbox/components/file_upload_button.test.js b/app/components/post_textbox/components/file_upload_button.test.js new file mode 100644 index 000000000..bec71a5a8 --- /dev/null +++ b/app/components/post_textbox/components/file_upload_button.test.js @@ -0,0 +1,76 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; +import {Alert, Platform} from 'react-native'; +import {shallow} from 'enzyme'; +import Permissions from 'react-native-permissions'; + +import Preferences from 'mattermost-redux/constants/preferences'; + +import FileUploadButton from './file_upload_button'; + +jest.mock('react-intl'); +jest.mock('react-native-image-picker', () => ({ + launchCamera: jest.fn(), +})); + +describe('FileUploadButton', () => { + const formatMessage = jest.fn(); + const baseProps = { + blurTextBox: jest.fn(), + browseFileTypes: '*', + fileCount: 0, + maxFileCount: 5, + onShowFileMaxWarning: jest.fn(), + theme: Preferences.THEMES.default, + uploadFiles: jest.fn(), + buttonContainerStyle: {}, + }; + + beforeAll(() => { + Platform.OS = 'android'; + }); + + afterAll(() => { + Platform.OS = 'ios'; + }); + + test('should match snapshot', () => { + const wrapper = shallow(); + + expect(wrapper.getElement()).toMatchSnapshot(); + }); + + test('should return permission false if permission is denied in Android', async () => { + jest.spyOn(Permissions, 'check').mockReturnValue(Permissions.RESULTS.UNAVAILABLE); + jest.spyOn(Permissions, 'request').mockReturnValue(Permissions.RESULTS.DENIED); + + const wrapper = shallow( + , + {context: {intl: {formatMessage}}}, + ); + + const hasPermission = await wrapper.instance().hasStoragePermission(); + expect(Permissions.check).toHaveBeenCalled(); + expect(Permissions.request).toHaveBeenCalled(); + expect(Alert.alert).not.toHaveBeenCalled(); + expect(hasPermission).toBe(false); + }); + + test('should show permission denied alert and return permission false if permission is blocked in Android', async () => { + jest.spyOn(Permissions, 'check').mockReturnValue(Permissions.RESULTS.BLOCKED); + jest.spyOn(Alert, 'alert').mockReturnValue(true); + + const wrapper = shallow( + , + {context: {intl: {formatMessage}}}, + ); + + const hasPermission = await wrapper.instance().hasStoragePermission(); + expect(Permissions.check).toHaveBeenCalled(); + expect(Permissions.request).not.toHaveBeenCalled(); + expect(Alert.alert).toHaveBeenCalled(); + expect(hasPermission).toBe(false); + }); +}); \ No newline at end of file diff --git a/app/components/post_textbox/components/imageUploadButton.js b/app/components/post_textbox/components/image_upload_button.js similarity index 90% rename from app/components/post_textbox/components/imageUploadButton.js rename to app/components/post_textbox/components/image_upload_button.js index 334a44165..07294aa25 100644 --- a/app/components/post_textbox/components/imageUploadButton.js +++ b/app/components/post_textbox/components/image_upload_button.js @@ -109,9 +109,10 @@ export default class ImageUploadButton extends PureComponent { const {formatMessage} = this.context.intl; let permissionRequest; const targetSource = Permissions.PERMISSIONS.IOS.PHOTO_LIBRARY; - const hasPermissionToStorage = await Permissions.check(targetSource); + const hasPermission = await Permissions.check(targetSource); - switch (hasPermissionToStorage) { + switch (hasPermission) { + case Permissions.RESULTS.DENIED: case Permissions.RESULTS.UNAVAILABLE: permissionRequest = await Permissions.request(targetSource); if (permissionRequest !== Permissions.RESULTS.AUTHORIZED) { @@ -119,17 +120,13 @@ export default class ImageUploadButton extends PureComponent { } break; case Permissions.RESULTS.BLOCKED: { - const canOpenSettings = await Permissions.canOpenSettings(); - let grantOption = null; - if (canOpenSettings) { - grantOption = { - text: formatMessage({ - id: 'mobile.permission_denied_retry', - defaultMessage: 'Settings', - }), - onPress: () => Permissions.openSettings(), - }; - } + const grantOption = { + text: formatMessage({ + id: 'mobile.permission_denied_retry', + defaultMessage: 'Settings', + }), + onPress: () => Permissions.openSettings(), + }; const {title, text} = this.getPermissionDeniedMessage(); diff --git a/app/components/post_textbox/components/image_upload_button.test.js b/app/components/post_textbox/components/image_upload_button.test.js new file mode 100644 index 000000000..dddd94b62 --- /dev/null +++ b/app/components/post_textbox/components/image_upload_button.test.js @@ -0,0 +1,67 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; +import {Alert} from 'react-native'; +import {shallow} from 'enzyme'; +import Permissions from 'react-native-permissions'; + +import Preferences from 'mattermost-redux/constants/preferences'; + +import ImageUploadButton from './image_upload_button'; + +jest.mock('react-intl'); +jest.mock('react-native-image-picker', () => ({ + launchCamera: jest.fn(), +})); + +describe('ImageUploadButton', () => { + const formatMessage = jest.fn(); + const baseProps = { + blurTextBox: jest.fn(), + fileCount: 0, + maxFileCount: 5, + onShowFileMaxWarning: jest.fn(), + theme: Preferences.THEMES.default, + uploadFiles: jest.fn(), + buttonContainerStyle: {}, + }; + + test('should match snapshot', () => { + const wrapper = shallow(); + + expect(wrapper.getElement()).toMatchSnapshot(); + }); + + test('should return permission false if permission is denied in iOS', async () => { + jest.spyOn(Permissions, 'check').mockReturnValue(Permissions.RESULTS.UNAVAILABLE); + jest.spyOn(Permissions, 'request').mockReturnValue(Permissions.RESULTS.DENIED); + + const wrapper = shallow( + , + {context: {intl: {formatMessage}}}, + ); + + const hasPermission = await wrapper.instance().hasPhotoPermission(); + expect(Permissions.check).toHaveBeenCalled(); + expect(Permissions.request).toHaveBeenCalled(); + expect(Alert.alert).not.toHaveBeenCalled(); + expect(hasPermission).toBe(false); + }); + + test('should show permission denied alert and return permission false if permission is blocked in iOS', async () => { + jest.spyOn(Permissions, 'check').mockReturnValue(Permissions.RESULTS.BLOCKED); + jest.spyOn(Alert, 'alert').mockReturnValue(true); + + const wrapper = shallow( + , + {context: {intl: {formatMessage}}}, + ); + + const hasPermission = await wrapper.instance().hasPhotoPermission(); + expect(Permissions.check).toHaveBeenCalled(); + expect(Permissions.request).not.toHaveBeenCalled(); + expect(Alert.alert).toHaveBeenCalled(); + expect(hasPermission).toBe(false); + }); +}); \ No newline at end of file diff --git a/app/components/post_textbox/post_textbox.test.js b/app/components/post_textbox/post_textbox.test.js index b22cd463e..aff9d8601 100644 --- a/app/components/post_textbox/post_textbox.test.js +++ b/app/components/post_textbox/post_textbox.test.js @@ -14,9 +14,9 @@ import PasteableTextInput from 'app/components/pasteable_text_input'; import EphemeralStore from 'app/store/ephemeral_store'; import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'; -import FileUploadButton from './components/fileUploadButton'; -import ImageUploadButton from './components/imageUploadButton'; -import CameraButton from './components/cameraButton'; +import FileUploadButton from './components/file_upload_button'; +import ImageUploadButton from './components/image_upload_button'; +import CameraButton from './components/camera_button'; import PostTextbox from './post_textbox.ios'; diff --git a/app/components/post_textbox/post_textbox_base.js b/app/components/post_textbox/post_textbox_base.js index 803ad2100..1fe70d29c 100644 --- a/app/components/post_textbox/post_textbox_base.js +++ b/app/components/post_textbox/post_textbox_base.js @@ -28,9 +28,9 @@ import {General, RequestStatus} from 'mattermost-redux/constants'; import EventEmitter from 'mattermost-redux/utils/event_emitter'; import {getFormattedFileSize} from 'mattermost-redux/utils/file_utils'; -import FileUploadButton from './components/fileUploadButton'; -import ImageUploadButton from './components/imageUploadButton'; -import CameraButton from './components/cameraButton'; +import FileUploadButton from './components/file_upload_button'; +import ImageUploadButton from './components/image_upload_button'; +import CameraButton from './components/camera_button'; import FormattedMarkdownText from 'app/components/formatted_markdown_text'; import FormattedText from 'app/components/formatted_text'; import PasteableTextInput from 'app/components/pasteable_text_input'; diff --git a/packager/moduleNames.js b/packager/moduleNames.js index 6dbeaf184..af36f03ef 100644 --- a/packager/moduleNames.js +++ b/packager/moduleNames.js @@ -119,9 +119,9 @@ module.exports = [ 'app/components/post_list/post_list.js', 'app/components/post_profile_picture/index.js', 'app/components/post_profile_picture/post_profile_picture.js', - 'app/components/post_textbox/components/cameraButton.js', - 'app/components/post_textbox/components/fileUploadButton.js', - 'app/components/post_textbox/components/imageUploadButton.js', + 'app/components/post_textbox/components/camera_button.js', + 'app/components/post_textbox/components/file_upload_button.js', + 'app/components/post_textbox/components/image_upload_button.js', 'app/components/post_textbox/components/typing/index.js', 'app/components/post_textbox/components/typing/typing.js', 'app/components/post_textbox/index.js', diff --git a/packager/modulePaths.js b/packager/modulePaths.js index bb5ef1067..cc3358c1f 100644 --- a/packager/modulePaths.js +++ b/packager/modulePaths.js @@ -91,9 +91,9 @@ module.exports = [ './node_modules/app/components/post_list/post_list.js', './node_modules/app/components/post_profile_picture/index.js', './node_modules/app/components/post_profile_picture/post_profile_picture.js', - './node_modules/app/components/post_textbox/components/cameraButton.js', - './node_modules/app/components/post_textbox/components/fileUploadButton.js', - './node_modules/app/components/post_textbox/components/imageUploadButton.js', + './node_modules/app/components/post_textbox/components/camera_button.js', + './node_modules/app/components/post_textbox/components/file_upload_button.js', + './node_modules/app/components/post_textbox/components/image_upload_button.js', './node_modules/app/components/post_textbox/components/typing/index.js', './node_modules/app/components/post_textbox/components/typing/typing.js', './node_modules/app/components/post_textbox/index.js',