From a1474d9e89fc96145b7ec148bc9eb9b161dca936 Mon Sep 17 00:00:00 2001 From: Miguel Alatzar Date: Thu, 6 Feb 2020 11:55:15 -0700 Subject: [PATCH] [MM-22236] Check against Permissions.RESULTS.GRANTED (#3892) * Check agains Permissions.RESULTS.GRANTED * Fix file and image upload as well * Fix permissions * Make linter happy * Use toHaveBeenCalledWith --- .../post_textbox/components/camera_button.js | 74 +++++++++---------- .../components/camera_button.test.js | 39 +++++++++- .../components/file_upload_button.js | 12 ++- .../components/file_upload_button.test.js | 33 +++++++++ .../components/image_upload_button.js | 74 +++++++++---------- .../components/image_upload_button.test.js | 39 +++++++++- 6 files changed, 186 insertions(+), 85 deletions(-) diff --git a/app/components/post_textbox/components/camera_button.js b/app/components/post_textbox/components/camera_button.js index 5c37a11a3..e5d24649a 100644 --- a/app/components/post_textbox/components/camera_button.js +++ b/app/components/post_textbox/components/camera_button.js @@ -103,47 +103,45 @@ export default class AttachmentButton extends PureComponent { }; hasCameraPermission = async () => { - if (Platform.OS === 'ios') { - const {formatMessage} = this.context.intl; - let permissionRequest; - const targetSource = Permissions.PERMISSIONS.IOS.CAMERA; - const hasPermission = await Permissions.check(targetSource); + const {formatMessage} = this.context.intl; + const targetSource = Platform.OS === 'ios' ? + Permissions.PERMISSIONS.IOS.CAMERA : + Permissions.PERMISSIONS.ANDROID.CAMERA; + const hasPermission = await Permissions.check(targetSource); - switch (hasPermission) { - case Permissions.RESULTS.DENIED: - case Permissions.RESULTS.UNAVAILABLE: - permissionRequest = await Permissions.request(targetSource); - if (permissionRequest !== Permissions.RESULTS.AUTHORIZED) { - return false; - } - break; - case Permissions.RESULTS.BLOCKED: { - const grantOption = { - text: formatMessage({ - id: 'mobile.permission_denied_retry', - defaultMessage: 'Settings', - }), - onPress: () => Permissions.openSettings(), - }; + switch (hasPermission) { + case Permissions.RESULTS.DENIED: + case Permissions.RESULTS.UNAVAILABLE: { + const permissionRequest = await Permissions.request(targetSource); - const {title, text} = this.getPermissionDeniedMessage(); + return permissionRequest === Permissions.RESULTS.GRANTED; + } + case Permissions.RESULTS.BLOCKED: { + const grantOption = { + text: formatMessage({ + id: 'mobile.permission_denied_retry', + defaultMessage: 'Settings', + }), + onPress: () => Permissions.openSettings(), + }; - Alert.alert( - title, - text, - [ - grantOption, - { - text: formatMessage({ - id: 'mobile.permission_denied_dismiss', - defaultMessage: 'Don\'t Allow', - }), - }, - ], - ); - return false; - } - } + const {title, text} = this.getPermissionDeniedMessage(); + + Alert.alert( + title, + text, + [ + grantOption, + { + text: formatMessage({ + id: 'mobile.permission_denied_dismiss', + defaultMessage: 'Don\'t Allow', + }), + }, + ], + ); + return false; + } } return true; diff --git a/app/components/post_textbox/components/camera_button.test.js b/app/components/post_textbox/components/camera_button.test.js index 0ee8b47bd..1c5f3674d 100644 --- a/app/components/post_textbox/components/camera_button.test.js +++ b/app/components/post_textbox/components/camera_button.test.js @@ -2,7 +2,7 @@ // See LICENSE.txt for license information. import React from 'react'; -import {Alert} from 'react-native'; +import {Alert, Platform} from 'react-native'; import {shallow} from 'enzyme'; import Permissions from 'react-native-permissions'; @@ -63,4 +63,41 @@ describe('CameraButton', () => { expect(Alert.alert).toHaveBeenCalled(); expect(hasPermission).toBe(false); }); + + test('hasCameraPermission returns true when permission has been granted', async () => { + const platformPermissions = [{ + platform: 'ios', + permission: Permissions.PERMISSIONS.IOS.CAMERA, + }, { + platform: 'android', + permission: Permissions.PERMISSIONS.ANDROID.CAMERA, + }]; + + for (let i = 0; i < platformPermissions.length; i++) { + const {platform, permission} = platformPermissions[i]; + Platform.OS = platform; + + const check = jest.spyOn(Permissions, 'check'); + const request = jest.spyOn(Permissions, 'request'); + request.mockReturnValue(Permissions.RESULTS.GRANTED); + + const wrapper = shallow( + , + {context: {intl: {formatMessage}}}, + ); + const instance = wrapper.instance(); + + check.mockReturnValueOnce(Permissions.RESULTS.DENIED); + let hasPermission = await instance.hasCameraPermission(); // eslint-disable-line no-await-in-loop + expect(check).toHaveBeenCalledWith(permission); + expect(request).toHaveBeenCalled(); + expect(hasPermission).toBe(true); + + check.mockReturnValueOnce(Permissions.RESULTS.UNAVAILABLE); + hasPermission = await instance.hasCameraPermission(); // eslint-disable-line no-await-in-loop + expect(check).toHaveBeenCalledWith(permission); + expect(request).toHaveBeenCalled(); + expect(hasPermission).toBe(true); + } + }); }); \ No newline at end of file diff --git a/app/components/post_textbox/components/file_upload_button.js b/app/components/post_textbox/components/file_upload_button.js index 1766cee2a..6324e2ec1 100644 --- a/app/components/post_textbox/components/file_upload_button.js +++ b/app/components/post_textbox/components/file_upload_button.js @@ -95,18 +95,16 @@ export default class FileUploadButton extends PureComponent { hasStoragePermission = async () => { if (Platform.OS === 'android') { const {formatMessage} = this.context.intl; - let permissionRequest; const storagePermission = Permissions.PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE; 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) { - return false; - } - break; + case Permissions.RESULTS.UNAVAILABLE: { + const permissionRequest = await Permissions.request(storagePermission); + + return permissionRequest === Permissions.RESULTS.GRANTED; + } case Permissions.RESULTS.BLOCKED: { const {title, text} = this.getPermissionDeniedMessage(); diff --git a/app/components/post_textbox/components/file_upload_button.test.js b/app/components/post_textbox/components/file_upload_button.test.js index bec71a5a8..501e32c67 100644 --- a/app/components/post_textbox/components/file_upload_button.test.js +++ b/app/components/post_textbox/components/file_upload_button.test.js @@ -73,4 +73,37 @@ describe('FileUploadButton', () => { expect(Alert.alert).toHaveBeenCalled(); expect(hasPermission).toBe(false); }); + + test('hasStoragePermission returns true when permission has been granted', async () => { + const wrapper = shallow( + , + {context: {intl: {formatMessage}}}, + ); + const instance = wrapper.instance(); + const check = jest.spyOn(Permissions, 'check'); + const request = jest.spyOn(Permissions, 'request'); + + // On iOS storage permissions are not checked + Platform.OS = 'ios'; + let hasPermission = await instance.hasStoragePermission(); + expect(check).not.toHaveBeenCalled(); + expect(request).not.toHaveBeenCalled(); + expect(hasPermission).toBe(true); + + Platform.OS = 'android'; + request.mockReturnValue(Permissions.RESULTS.GRANTED); + const permission = Permissions.PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE; + + check.mockReturnValueOnce(Permissions.RESULTS.DENIED); + hasPermission = await instance.hasStoragePermission(); + expect(check).toHaveBeenCalledWith(permission); + expect(request).toHaveBeenCalled(); + expect(hasPermission).toBe(true); + + check.mockReturnValueOnce(Permissions.RESULTS.UNAVAILABLE); + hasPermission = await instance.hasStoragePermission(); + expect(check).toHaveBeenCalledWith(permission); + expect(request).toHaveBeenCalled(); + expect(hasPermission).toBe(true); + }); }); \ No newline at end of file diff --git a/app/components/post_textbox/components/image_upload_button.js b/app/components/post_textbox/components/image_upload_button.js index 07294aa25..4ecab9468 100644 --- a/app/components/post_textbox/components/image_upload_button.js +++ b/app/components/post_textbox/components/image_upload_button.js @@ -105,47 +105,45 @@ export default class ImageUploadButton extends PureComponent { }; hasPhotoPermission = async () => { - if (Platform.OS === 'ios') { - const {formatMessage} = this.context.intl; - let permissionRequest; - const targetSource = Permissions.PERMISSIONS.IOS.PHOTO_LIBRARY; - const hasPermission = await Permissions.check(targetSource); + const {formatMessage} = this.context.intl; + const targetSource = Platform.OS === 'ios' ? + Permissions.PERMISSIONS.IOS.PHOTO_LIBRARY : + Permissions.PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE; + const hasPermission = await Permissions.check(targetSource); - switch (hasPermission) { - case Permissions.RESULTS.DENIED: - case Permissions.RESULTS.UNAVAILABLE: - permissionRequest = await Permissions.request(targetSource); - if (permissionRequest !== Permissions.RESULTS.AUTHORIZED) { - return false; - } - break; - case Permissions.RESULTS.BLOCKED: { - const grantOption = { - text: formatMessage({ - id: 'mobile.permission_denied_retry', - defaultMessage: 'Settings', - }), - onPress: () => Permissions.openSettings(), - }; + switch (hasPermission) { + case Permissions.RESULTS.DENIED: + case Permissions.RESULTS.UNAVAILABLE: { + const permissionRequest = await Permissions.request(targetSource); - const {title, text} = this.getPermissionDeniedMessage(); + return permissionRequest === Permissions.RESULTS.GRANTED; + } + case Permissions.RESULTS.BLOCKED: { + const grantOption = { + text: formatMessage({ + id: 'mobile.permission_denied_retry', + defaultMessage: 'Settings', + }), + onPress: () => Permissions.openSettings(), + }; - Alert.alert( - title, - text, - [ - grantOption, - { - text: formatMessage({ - id: 'mobile.permission_denied_dismiss', - defaultMessage: 'Don\'t Allow', - }), - }, - ], - ); - return false; - } - } + const {title, text} = this.getPermissionDeniedMessage(); + + Alert.alert( + title, + text, + [ + grantOption, + { + text: formatMessage({ + id: 'mobile.permission_denied_dismiss', + defaultMessage: 'Don\'t Allow', + }), + }, + ], + ); + return false; + } } return true; diff --git a/app/components/post_textbox/components/image_upload_button.test.js b/app/components/post_textbox/components/image_upload_button.test.js index dddd94b62..20a444cc1 100644 --- a/app/components/post_textbox/components/image_upload_button.test.js +++ b/app/components/post_textbox/components/image_upload_button.test.js @@ -2,7 +2,7 @@ // See LICENSE.txt for license information. import React from 'react'; -import {Alert} from 'react-native'; +import {Alert, Platform} from 'react-native'; import {shallow} from 'enzyme'; import Permissions from 'react-native-permissions'; @@ -64,4 +64,41 @@ describe('ImageUploadButton', () => { expect(Alert.alert).toHaveBeenCalled(); expect(hasPermission).toBe(false); }); + + test('hasPhotoPermission returns true when permission has been granted', async () => { + const platformPermissions = [{ + platform: 'ios', + permission: Permissions.PERMISSIONS.IOS.PHOTO_LIBRARY, + }, { + platform: 'android', + permission: Permissions.PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE, + }]; + + for (let i = 0; i < platformPermissions.length; i++) { + const {platform, permission} = platformPermissions[i]; + Platform.OS = platform; + + const check = jest.spyOn(Permissions, 'check'); + const request = jest.spyOn(Permissions, 'request'); + request.mockReturnValue(Permissions.RESULTS.GRANTED); + + const wrapper = shallow( + , + {context: {intl: {formatMessage}}}, + ); + const instance = wrapper.instance(); + + check.mockReturnValueOnce(Permissions.RESULTS.DENIED); + let hasPermission = await instance.hasPhotoPermission(); // eslint-disable-line no-await-in-loop + expect(check).toHaveBeenCalledWith(permission); + expect(request).toHaveBeenCalled(); + expect(hasPermission).toBe(true); + + check.mockReturnValueOnce(Permissions.RESULTS.UNAVAILABLE); + hasPermission = await instance.hasPhotoPermission(); // eslint-disable-line no-await-in-loop + expect(check).toHaveBeenCalledWith(permission); + expect(request).toHaveBeenCalled(); + expect(hasPermission).toBe(true); + } + }); }); \ No newline at end of file