Skip to content

[image_picker_ios] Update UITests for Xcode 15/iOS 17 #5176

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

Merged
merged 2 commits into from
Oct 19, 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
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,30 @@ @interface ImagePickerFromGalleryUITests : XCTestCase

@property(nonatomic, strong) XCUIApplication *app;

@property(nonatomic, assign) BOOL interceptedPermissionInterruption;

@end

@implementation ImagePickerFromGalleryUITests

- (void)setUp {
[super setUp];
// Delete the app if already exists, to test permission popups

self.continueAfterFailure = NO;
self.app = [[XCUIApplication alloc] init];
if (@available(iOS 13.4, *)) {
// Reset the authorization status for Photos to test permission popups
[self.app resetAuthorizationStatusForResource:XCUIProtectedResourcePhotos];
}
[self.app launch];
self.interceptedPermissionInterruption = NO;
__weak typeof(self) weakSelf = self;
[self addUIInterruptionMonitorWithDescription:@"Permission popups"
handler:^BOOL(XCUIElement *_Nonnull interruptingElement) {
if (@available(iOS 14, *)) {
XCUIElement *allPhotoPermission =
interruptingElement
.buttons[@"Allow Access to All Photos"];
.buttons[weakSelf.allowAccessPermissionText];
if (![allPhotoPermission waitForExistenceWithTimeout:
kElementWaitingTime]) {
os_log_error(OS_LOG_DEFAULT, "%@",
Expand All @@ -50,6 +56,7 @@ - (void)setUp {
}
[ok tap];
}
weakSelf.interceptedPermissionInterruption = YES;
return YES;
}];
}
Expand All @@ -59,6 +66,46 @@ - (void)tearDown {
[self.app terminate];
}

- (NSString *)allowAccessPermissionText {
NSString *fullAccessButtonText = @"Allow Access to All Photos";
if (@available(iOS 17, *)) {
fullAccessButtonText = @"Allow Full Access";
}
return fullAccessButtonText;
}

- (void)handlePermissionInterruption {
// addUIInterruptionMonitorWithDescription is only invoked when trying to interact with an element
// (the app in this case) the alert is blocking. We expect a permission popup here so do a swipe
// up action (which should be harmless).
[self.app swipeUp];

if (@available(iOS 17, *)) {
// addUIInterruptionMonitorWithDescription does not work consistently on Xcode 15 simulators, so
// use a backup method of accepting permissions popup.

if (self.interceptedPermissionInterruption == YES) {
return;
}

// If cancel button exists, permission has already been given.
XCUIElement *cancelButton = self.app.buttons[@"Cancel"].firstMatch;
if ([cancelButton waitForExistenceWithTimeout:kElementWaitingTime]) {
return;
}

XCUIApplication *springboardApp =
[[XCUIApplication alloc] initWithBundleIdentifier:@"com.apple.springboard"];
XCUIElement *allowButton = springboardApp.buttons[self.allowAccessPermissionText];
if (![allowButton waitForExistenceWithTimeout:kElementWaitingTime]) {
os_log_error(OS_LOG_DEFAULT, "%@", self.app.debugDescription);
XCTFail(@"Failed due to not able to find Allow Access button with %@ seconds",
@(kElementWaitingTime));
}
[allowButton tap];
}
}

- (void)testCancel {
// Find and tap on the pick from gallery button.
XCUIElement *imageFromGalleryButton =
Expand All @@ -80,9 +127,7 @@ - (void)testCancel {

[pickButton tap];

// There is a known bug where the permission popups interruption won't get fired until a tap
// happened in the app. We expect a permission popup so we do a tap here.
[self.app tap];
[self handlePermissionInterruption];

// Find and tap on the `Cancel` button.
XCUIElement *cancelButton = self.app.buttons[@"Cancel"].firstMatch;
Expand Down Expand Up @@ -151,9 +196,7 @@ - (void)launchPickerAndPickWithMaxWidth:(NSNumber *)maxWidth
}
[pickButton tap];

// There is a known bug where the permission popups interruption won't get fired until a tap
// happened in the app. We expect a permission popup so we do a tap here.
[self.app tap];
[self handlePermissionInterruption];

// Find an image and tap on it. (IOS 14 UI, images are showing directly)
XCUIElement *aImage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,21 @@ @interface ImagePickerFromLimitedGalleryUITests : XCTestCase

@property(nonatomic, strong) XCUIApplication *app;

@property(nonatomic, assign) BOOL interceptedPermissionInterruption;

@end

@implementation ImagePickerFromLimitedGalleryUITests

- (void)setUp {
[super setUp];
// Delete the app if already exists, to test permission popups

self.continueAfterFailure = NO;
self.app = [[XCUIApplication alloc] init];
if (@available(iOS 13.4, *)) {
// Reset the authorization status for Photos to test permission popups
[self.app resetAuthorizationStatusForResource:XCUIProtectedResourcePhotos];
}
[self.app launch];
__weak typeof(self) weakSelf = self;
[self addUIInterruptionMonitorWithDescription:@"Permission popups"
Expand All @@ -37,6 +42,7 @@ - (void)setUp {
@(kLimitedElementWaitingTime));
}
[limitedPhotoPermission tap];
weakSelf.interceptedPermissionInterruption = YES;
return YES;
}];
}
Expand All @@ -46,6 +52,38 @@ - (void)tearDown {
[self.app terminate];
}

- (void)handlePermissionInterruption {
// addUIInterruptionMonitorWithDescription is only invoked when trying to interact with an element
// (the app in this case) the alert is blocking. We expect a permission popup here so do a swipe
// up action (which should be harmless).
[self.app swipeUp];

if (@available(iOS 17, *)) {
// addUIInterruptionMonitorWithDescription does not work consistently on Xcode 15 simulators, so
// use a backup method of accepting permissions popup.

if (self.interceptedPermissionInterruption == YES) {
return;
}

// If cancel button exists, permission has already been given.
XCUIElement *cancelButton = self.app.buttons[@"Cancel"].firstMatch;
if ([cancelButton waitForExistenceWithTimeout:kLimitedElementWaitingTime]) {
return;
}

XCUIApplication *springboardApp =
[[XCUIApplication alloc] initWithBundleIdentifier:@"com.apple.springboard"];
XCUIElement *allowButton = springboardApp.buttons[@"Limit Access…"];
if (![allowButton waitForExistenceWithTimeout:kLimitedElementWaitingTime]) {
os_log_error(OS_LOG_DEFAULT, "%@", self.app.debugDescription);
XCTFail(@"Failed due to not able to find Limit Access button with %@ seconds",
@(kLimitedElementWaitingTime));
}
[allowButton tap];
}
}

// Test the `Select Photos` button which is available after iOS 14.
- (void)testSelectingFromGallery API_AVAILABLE(ios(14)) {
// Find and tap on the pick from gallery button.
Expand All @@ -66,9 +104,7 @@ - (void)testSelectingFromGallery API_AVAILABLE(ios(14)) {
}
[pickButton tap];

// There is a known bug where the permission popups interruption won't get fired until a tap
// happened in the app. We expect a permission popup so we do a tap here.
[self.app tap];
[self handlePermissionInterruption];

// Find an image and tap on it.
XCUIElement *aImage = [self.app.scrollViews.firstMatch.images elementBoundByIndex:1];
Expand Down