Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sync develop with master #1702

Merged
merged 1 commit into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion packages/patrol/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@

This version requires version 2.2.0-dev.1 of `patrol_cli` package.

## 2.2.5

- Fix `grantPermissionOnlyThisTime()` crashing on Android <11 (#1698)

## 2.2.4

- Remove deprecation of `nativeAutomation` and add message about migration to `patrol_finders` (#1670)
- Remove deprecation of `nativeAutomation` and add message about migration to
`patrol_finders` (#1670)

## 2.2.3

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -392,9 +392,9 @@ class Automator private constructor() {

fun allowPermissionWhileUsingApp() {
val identifiers = arrayOf(
"com.android.packageinstaller:id/permission_allow_button",
"com.android.permissioncontroller:id/permission_allow_button",
"com.android.permissioncontroller:id/permission_allow_foreground_only_button"
"com.android.packageinstaller:id/permission_allow_button", // API <= 28
"com.android.permissioncontroller:id/permission_allow_button", // API 29
"com.android.permissioncontroller:id/permission_allow_foreground_only_button" // API >= 30 + API 29 (only for location permission)
)

val uiObject = waitForUiObjectByResourceId(*identifiers, timeout = timeoutMillis)
Expand All @@ -404,10 +404,15 @@ class Automator private constructor() {
}

fun allowPermissionOnce() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
// One-time permissions are available only on API 30 (R) and above.
// See: https://developer.android.com/training/permissions/requesting#one-time
allowPermissionWhileUsingApp()
return
}

val identifiers = arrayOf(
"com.android.packageinstaller:id/permission_allow_button",
"com.android.permissioncontroller:id/permission_allow_button",
"com.android.permissioncontroller:id/permission_allow_one_time_button"
"com.android.permissioncontroller:id/permission_allow_one_time_button" // API >= 30
)

val uiObject = waitForUiObjectByResourceId(*identifiers, timeout = timeoutMillis)
Expand All @@ -418,8 +423,8 @@ class Automator private constructor() {

fun denyPermission() {
val identifiers = arrayOf(
"com.android.packageinstaller:id/permission_deny_button",
"com.android.permissioncontroller:id/permission_deny_button"
"com.android.packageinstaller:id/permission_deny_button", // API <= 28
"com.android.permissioncontroller:id/permission_deny_button" // API >= 29
)

val uiObject = waitForUiObjectByResourceId(*identifiers, timeout = timeoutMillis)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ void main() {
await $.native.selectFineLocation();
await $.native.selectCoarseLocation();
await $.native.selectFineLocation();
await $.native.grantPermissionWhenInUse();
await $.native.grantPermissionOnlyThisTime();
}
await $.pump();

Expand Down
4 changes: 4 additions & 0 deletions packages/patrol/lib/src/native/native_automator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,10 @@ class NativeAutomator {
/// On iOS, this is the same as [grantPermissionWhenInUse] except for the
/// location permission.
///
/// On Android versions older than 11 (R, API level 30), the concept of
/// "one-time permissions" doesn't exist. In this case, this method is the
/// same as [grantPermissionWhenInUse].
///
/// See also:
///
/// * [grantPermissionWhenInUse] and [denyPermission]
Expand Down
4 changes: 4 additions & 0 deletions packages/patrol_cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

This version requires version 2.3.0-dev.1 of `patrol` package.

## 2.1.4

- Uninstall RunnerUITests app on iOS when flavor is present (#1694)

## 2.1.3

- Add migration message due to release of `patrol_finders`
Expand Down
22 changes: 15 additions & 7 deletions packages/patrol_cli/lib/src/commands/develop.dart
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,11 @@ class DevelopCommand extends PatrolCommand {
case TargetPlatform.iOS:
final bundleId = iosOpts.bundleId;
if (bundleId != null) {
action = () => _iosTestBackend.uninstall(bundleId, device);
action = () => _iosTestBackend.uninstall(
appId: bundleId,
flavor: iosOpts.flutter.flavor,
device: device,
);
}
break;
}
Expand All @@ -238,7 +242,7 @@ class DevelopCommand extends PatrolCommand {
Future<void> _execute(
FlutterAppOptions flutterOpts,
AndroidAppOptions android,
IOSAppOptions ios, {
IOSAppOptions iosOpts, {
required bool uninstall,
required Device device,
}) async {
Expand All @@ -257,12 +261,16 @@ class DevelopCommand extends PatrolCommand {
}
break;
case TargetPlatform.iOS:
appId = ios.bundleId;
appId = iosOpts.bundleId;
action = () async =>
_iosTestBackend.execute(ios, device, interruptible: true);
final bundle = ios.bundleId;
if (bundle != null && uninstall) {
finalizer = () => _iosTestBackend.uninstall(bundle, device);
_iosTestBackend.execute(iosOpts, device, interruptible: true);
final bundleId = iosOpts.bundleId;
if (bundleId != null && uninstall) {
finalizer = () => _iosTestBackend.uninstall(
appId: bundleId,
flavor: iosOpts.flutter.flavor,
device: device,
);
}
}

Expand Down
20 changes: 14 additions & 6 deletions packages/patrol_cli/lib/src/commands/test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,11 @@ See https://github.com/leancodepl/patrol/issues/1316 to learn more.
case TargetPlatform.iOS:
final bundleId = iosOpts.bundleId;
if (bundleId != null) {
action = () => _iosTestBackend.uninstall(bundleId, device);
action = () => _iosTestBackend.uninstall(
appId: bundleId,
flavor: iosOpts.flutter.flavor,
device: device,
);
}
break;
}
Expand Down Expand Up @@ -240,7 +244,7 @@ See https://github.com/leancodepl/patrol/issues/1316 to learn more.
Future<bool> _execute(
FlutterAppOptions flutterOpts,
AndroidAppOptions android,
IOSAppOptions ios, {
IOSAppOptions iosOpts, {
required bool uninstall,
required Device device,
}) async {
Expand All @@ -256,10 +260,14 @@ See https://github.com/leancodepl/patrol/issues/1316 to learn more.
}
break;
case TargetPlatform.iOS:
action = () async => _iosTestBackend.execute(ios, device);
final bundle = ios.bundleId;
if (bundle != null && uninstall) {
finalizer = () => _iosTestBackend.uninstall(bundle, device);
action = () async => _iosTestBackend.execute(iosOpts, device);
final bundleId = iosOpts.bundleId;
if (bundleId != null && uninstall) {
finalizer = () => _iosTestBackend.uninstall(
appId: bundleId,
flavor: iosOpts.flutter.flavor,
device: device,
);
}
break;
}
Expand Down
34 changes: 31 additions & 3 deletions packages/patrol_cli/lib/src/ios/ios_test_backend.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'dart:io' show Process;
import 'package:dispose_scope/dispose_scope.dart';
import 'package:file/file.dart';
import 'package:glob/glob.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' show join;
import 'package:patrol_cli/src/base/exceptions.dart';
import 'package:patrol_cli/src/base/logger.dart';
Expand Down Expand Up @@ -189,7 +190,14 @@ class IOSTestBackend {
});
}

Future<void> uninstall(String appId, Device device) async {
/// Uninstalls the app under test and the test runner from [device].
///
/// [flavor] is required to infer the test runner bundle ID.
Future<void> uninstall({
required String appId,
required String? flavor,
required Device device,
}) async {
if (device.real) {
// uninstall from iOS device
await _processManager.run(
Expand All @@ -208,8 +216,10 @@ class IOSTestBackend {
);
}

// TODO: Not being removed https://github.com/leancodepl/patrol/issues/1094
final testApp = '$appId.RunnerUITests.xctrunner';
// See rationale: https://github.com/leancodepl/patrol/issues/1094
final appIdWithoutFlavor = stripFlavorFromAppId(appId, flavor);
final testApp = '$appIdWithoutFlavor.RunnerUITests.xctrunner';

if (device.real) {
// uninstall from iOS device
await _processManager.run(
Expand All @@ -229,6 +239,24 @@ class IOSTestBackend {
}
}

/// Removes [flavor] from the end of [appId].
///
/// Assumes that [appId] and [flavor] are separated by a dot.
@visibleForTesting
String stripFlavorFromAppId(String appId, String? flavor) {
if (flavor == null) {
return appId;
}

final idx = appId.indexOf('.$flavor');

if (idx == -1) {
return appId;
}

return appId.substring(0, idx);
}

Future<String> xcTestRunPath({
required bool real,
required String scheme,
Expand Down
32 changes: 32 additions & 0 deletions packages/patrol_cli/test/ios/ios_test_backend_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,38 @@ void main() {
testPlan: 'SomeTestPlan',
);
});

group('stripFlavorFromAppId', () {
test('simply returns appId when flavor is null', () {
const appId = 'com.company.app';
const String? flavor = null;

expect(
iosTestBackend.stripFlavorFromAppId(appId, flavor),
'com.company.app',
);
});

test('works when appId contains flavor', () {
const appId = 'com.company.app.dev';
const flavor = 'dev';

expect(
iosTestBackend.stripFlavorFromAppId(appId, flavor),
'com.company.app',
);
});

test('ignores when appId contains flavor not preceded by a dot', () {
const appId = 'com.company.app_dev';
const flavor = 'dev';

expect(
iosTestBackend.stripFlavorFromAppId(appId, flavor),
'com.company.app_dev',
);
});
});
});
}

Expand Down
Loading