Skip to content

Commit 8de310e

Browse files
committed
feat(config): default app permissions (iOS)
1 parent 3f72c24 commit 8de310e

9 files changed

+98
-13
lines changed

detox/index.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ declare global {
178178
bundleId?: string;
179179
build?: string;
180180
launchArgs?: Record<string, any>;
181+
permissions?: DevicePermissions;
181182
}
182183

183184
interface DetoxAndroidAppConfig {
@@ -195,6 +196,7 @@ declare global {
195196
build?: string;
196197
testBinaryPath?: string;
197198
launchArgs?: Record<string, any>;
199+
permissions?: DevicePermissions;
198200
}
199201

200202
type DetoxBuiltInDeviceConfig =

detox/src/configuration/composeAppsConfig.js

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ function composeAppsConfigFromPlain(opts) {
6868
bundleId: localConfig.bundleId,
6969
build: localConfig.build,
7070
launchArgs: localConfig.launchArgs,
71+
permissions: localConfig.permissions,
7172
};
7273
break;
7374
default:

detox/src/configuration/composeAppsConfig.test.js

+16
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ describe('composeAppsConfig', () => {
5656
binaryPath: 'path/to/app',
5757
bundleId: 'com.example.app',
5858
build: 'echo OK',
59+
permissions: {
60+
calendar: 'YES',
61+
},
5962
launchArgs: {
6063
hello: 'world',
6164
}
@@ -65,6 +68,18 @@ describe('composeAppsConfig', () => {
6568
it.each([
6669
['ios.none', 'ios.app'],
6770
['ios.simulator', 'ios.app'],
71+
])('should infer type and app properties for %j', (deviceType, appType) => {
72+
deviceConfig.type = deviceType;
73+
expect(compose()).toEqual({
74+
default: {
75+
...localConfig,
76+
type: appType,
77+
device: undefined,
78+
},
79+
});
80+
});
81+
82+
it.each([
6883
['android.attached', 'android.apk'],
6984
['android.emulator', 'android.apk'],
7085
['android.genycloud', 'android.apk'],
@@ -75,6 +90,7 @@ describe('composeAppsConfig', () => {
7590
...localConfig,
7691
type: appType,
7792
device: undefined,
93+
permissions: undefined,
7894
},
7995
});
8096
});

detox/src/devices/runtime/RuntimeDevice.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
const _ = require('lodash');
2+
13
const DetoxRuntimeError = require('../../errors/DetoxRuntimeError');
24
const debug = require('../../utils/debug'); // debug utils, leave here even if unused
35
const { traceCall } = require('../../utils/trace');
@@ -55,6 +57,7 @@ class RuntimeDevice {
5557
this._emitter = eventEmitter;
5658
this._errorComposer = runtimeErrorComposer;
5759

60+
/** @type {Detox.DetoxAppConfig | null} */
5861
this._currentApp = null;
5962
this._currentAppLaunchArgs = new LaunchArgsEditor();
6063
this._processes = {};
@@ -332,8 +335,13 @@ class RuntimeDevice {
332335
this._createPayloadFileAndUpdatesParamsObject('userActivity', 'detoxUserActivityDataURL', params, baseLaunchArgs);
333336
}
334337

335-
if (params.permissions) {
336-
await this.deviceDriver.setPermissions(bundleId, params.permissions);
338+
const permissions = {
339+
...(this._currentApp ? this._currentApp['permissions'] : null),
340+
...params.permissions,
341+
};
342+
343+
if (!_.isEmpty(permissions)) {
344+
await this.deviceDriver.setPermissions(bundleId, permissions);
337345
}
338346

339347
if (params.disableTouchIndicators) {

detox/src/devices/runtime/RuntimeDevice.test.js

+15-2
Original file line numberDiff line numberDiff line change
@@ -430,10 +430,23 @@ describe('Device', () => {
430430
});
431431

432432
it(`(relaunch) with permissions should send trigger setpermissions before app starts`, async () => {
433-
const device = await aValidDevice();
433+
const device = await aValidDevice({
434+
appsConfig: {
435+
default: {
436+
permissions: {
437+
calendar: 'NO',
438+
camera: 'YES',
439+
},
440+
},
441+
},
442+
});
443+
434444
await device.relaunchApp({ permissions: { calendar: 'YES' } });
435445

436-
expect(driverMock.driver.setPermissions).toHaveBeenCalledWith(bundleId, { calendar: 'YES' });
446+
expect(driverMock.driver.setPermissions).toHaveBeenCalledWith(bundleId, {
447+
calendar: 'YES',
448+
camera: 'YES',
449+
});
437450
});
438451

439452
it('with languageAndLocale should launch app with a specific language/locale', async () => {

detox/test/e2e/detox.config.js

+9
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ const launchArgs = {
1616
micro: 'soft',
1717
};
1818

19+
const defaultPermissions = {
20+
calendar: 'YES',
21+
notifications: 'YES',
22+
camera: 'YES',
23+
photos: 'YES',
24+
};
25+
1926
/** @type {Detox.DetoxConfig} */
2027
const config = {
2128
testRunner: 'nyc jest',
@@ -56,13 +63,15 @@ const config = {
5663
binaryPath: 'ios/build/Build/Products/Debug-iphonesimulator/example.app',
5764
build: 'set -o pipefail && xcodebuild -workspace ios/example.xcworkspace -UseNewBuildSystem=YES -scheme example_ci -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build -quiet',
5865
bundleId: 'com.wix.detox-example',
66+
permissions: defaultPermissions,
5967
},
6068

6169
'ios.release': {
6270
type: 'ios.app',
6371
name: 'example',
6472
binaryPath: 'ios/build/Build/Products/Release-iphonesimulator/example.app',
6573
build: 'set -o pipefail && export CODE_SIGNING_REQUIRED=NO && export RCT_NO_LAUNCH_PACKAGER=true && xcodebuild -workspace ios/example.xcworkspace -UseNewBuildSystem=YES -scheme example_ci -configuration Release -sdk iphonesimulator -derivedDataPath ios/build -quiet',
74+
permissions: defaultPermissions,
6675
},
6776

6877
'android.debug': {

docs/APIRef.Configuration.md

+14-9
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,11 @@ The format of Detox config allows you to define inside it multiple app configs i
202202
"ios.debug": {
203203
"type": "ios.app",
204204
"binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/example.app",
205-
"build": "xcodebuild -project ios/example.xcodeproj -scheme example -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build"
205+
"build": "xcodebuild -project ios/example.xcodeproj -scheme example -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build",
206+
"permissions": {
207+
/** @see {Detox.DevicePermissions} */
208+
notifications: 'YES',
209+
},
206210
},
207211
"android.release": {
208212
"type": "android.apk",
@@ -218,14 +222,15 @@ The format of Detox config allows you to define inside it multiple app configs i
218222

219223
An app config can have the following params:
220224

221-
| Configuration Params | Details |
222-
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
223-
| `type` | Mandatory property to discern app types: `ios.app`, `android.apk`. |
224-
| `name` | Use only when working with multiple apps within the same configuration. See an example below. |
225-
| `binaryPath` | Relative path to the ipa/app/apk due to be tested (make sure you build the app in a project relative path) |
226-
| `build` | **\[optional]** Build command (normally an `xcodebuild` command you use to build your app), which can be called later using Detox CLI tool as a convenience. |
227-
| `testBinaryPath` | (optional, Android only): relative path to the test app (apk) |
228-
| `launchArgs` | **\[optional]** An object specifying arguments (key-values pairs) to pass through into the app, upon launching on the device. For more info, refer to the dedicated [launch-arguments guide](APIRef.LaunchArgs.md). |
225+
| Configuration Params | Details |
226+
|----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
227+
| `type` | Mandatory property to discern app types: `ios.app`, `android.apk`. |
228+
| `name` | Use only when working with multiple apps within the same configuration. See an example below. |
229+
| `build` | **\[optional]** Build command (normally an `xcodebuild` command you use to build your app), which can be called later using Detox CLI tool as a convenience. |
230+
| `binaryPath` | Relative path to the ipa/app/apk due to be tested (make sure you build the app in a project relative path) |
231+
| `testBinaryPath` | **\[optional, Android only]**: relative path to the test app (apk) |
232+
| `launchArgs` | **\[optional]** An object specifying arguments (key-values pairs) to pass through into the app, upon launching on the device. For more info, refer to the dedicated [launch-arguments guide](APIRef.LaunchArgs.md). |
233+
| `permissions` | **\[optional, iOS only]** An object specifying default [runtime permissions](APIRef.DeviceObjectAPI.md#permissions-ios-only) to give before launching the app. |
229234

230235
To work with multiple apps within the same configuration you should be giving each app its name, e.g.:
231236

docs/APIRef.DeviceObjectAPI.md

+31
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ await device.launchApp({permissions: {calendar: 'YES'}});
137137
138138
Detox uses [AppleSimUtils](https://github.com/wix/AppleSimulatorUtils) to implement this functionality for iOS simulators. Read about the different types of permissions and how to set them in AppleSimUtils' documentation and by checking out Detox’s [own test suite](https://github.com/wix/Detox/tree/a9a09246c05733f6b91cfcc0dba05a4714abca92/detox/test/e2e/13.permissions.test.js).
139139
140+
As a reference, you can also use this [table of possible permissions](#permissions-ios-only).
141+
140142
##### 3. `url`—Launching with URL
141143
142144
Launches the app with the specified URL to test your app’s deep link handling mechanism.
@@ -528,3 +530,32 @@ Exposes [`UiAutomator`’s `UiDevice` API](https://developer.android.com/referen
528530
**This is not a part of the official Detox API**, it may break and change whenever an update to `UiDevice` or `UiAutomator` Gradle dependencies (`androidx.test.uiautomator:uiautomator`) is introduced.
529531
530532
[`UiDevice`’s autogenerated code](https://github.com/wix/Detox/tree/a9a09246c05733f6b91cfcc0dba05a4714abca92/detox/src/android/espressoapi/UIDevice.js)
533+
534+
### Permissions (iOS only)
535+
536+
When you are [configuring the apps](APIRef.Configuration.md#apps-configurations) list in your
537+
Detox config file or [launching the app](#2-permissionsset-runtime-permissions-ios-only),
538+
you can give certain permissions beforehand to it to avoid this inconvenient modal:
539+
540+
![iOS permissions modal](img/ios-permissions.png)
541+
542+
So, here is the exhaustive permissions list that Detox currently supports for iOS:
543+
544+
| Permission | Values |
545+
|---------------|---------------------------------------------------------|
546+
| calendar | `'YES' &#124; 'NO' &#124; 'unset'` |
547+
| camera | `'YES' &#124; 'NO' &#124; 'unset'` |
548+
| contacts | `'YES' &#124; 'NO' &#124; 'unset'` |
549+
| faceid | `'YES' &#124; 'NO' &#124; 'unset'` |
550+
| health | `'YES' &#124; 'NO' &#124; 'unset'` |
551+
| homekit | `'YES' &#124; 'NO' &#124; 'unset'` |
552+
| location | `'always' &#124; 'inuse' &#124; 'never' &#124; 'unset'` |
553+
| medialibrary | `'YES' &#124; 'NO' &#124; 'unset'` |
554+
| microphone | `'YES' &#124; 'NO' &#124; 'unset'` |
555+
| motion | `'YES' &#124; 'NO' &#124; 'unset'` |
556+
| notification | `'YES' &#124; 'NO' &#124; 'unset'` |
557+
| photos | `'YES' &#124; 'NO' &#124; 'unset'` |
558+
| reminders | `'YES' &#124; 'NO' &#124; 'unset'` |
559+
| siri | `'YES' &#124; 'NO' &#124; 'unset'` |
560+
| speech | `'YES' &#124; 'NO' &#124; 'unset'` |
561+
| userTracking | `'YES' &#124; 'NO' &#124; 'unset'` |

docs/img/ios-permissions.png

85.7 KB
Loading

0 commit comments

Comments
 (0)