Automated cherry pick of #3892 (#3895)

* Check agains Permissions.RESULTS.GRANTED

* Fix file and image upload as well

* Fix permissions

* Make linter happy

* Use toHaveBeenCalledWith

Co-authored-by: Miguel Alatzar <migbot@users.noreply.github.com>
This commit is contained in:
Mattermost Build 2020-02-06 20:14:44 +01:00 committed by GitHub
parent 51e6b1e1aa
commit 6806337b23
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 186 additions and 85 deletions

View file

@ -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;

View file

@ -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(
<CameraButton {...baseProps}/>,
{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);
}
});
});

View file

@ -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();

View file

@ -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(
<FileUploadButton {...baseProps}/>,
{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);
});
});

View file

@ -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;

View file

@ -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(
<ImageUploadButton {...baseProps}/>,
{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);
}
});
});