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',