// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/testing/system_alert_handler.h"
#import <XCTest/XCTest.h>
#import "base/test/ios/wait_util.h"
using base::test::ios::kWaitForUIElementTimeout;
namespace {
// Returns true if any static text child of `element` (XCUIElement*) contains
// `text` (NSString*).
BOOL ElementStaticTextContainsText(XCUIElement* element, NSString* text) {
NSPredicate* label_contains_text =
[NSPredicate predicateWithFormat:@"%K CONTAINS[c] %@", @"label", text];
return
[element.staticTexts containingPredicate:label_contains_text].count > 0;
}
// Closes the `alert` (XCUIElement*) if it matches a known text/button pair and
// returns whether it succeeded or not in closing it.
BOOL HandleSingleAlert(XCUIElement* alert) {
NSDictionary<NSString*, NSArray<NSString*>*>* text_to_buttons =
TextToButtonsOfKnownSystemAlerts();
for (NSString* text in text_to_buttons) {
if (ElementStaticTextContainsText(alert, text)) {
NSLog(@"Found alert containing text: %@", text);
for (NSString* button in text_to_buttons[text]) {
if (!alert.buttons[button].exists) {
NSLog(@"Button %@ doesn't exist. Skip tapping.", button);
continue;
}
NSLog(@"Tapping alert button: %@", button);
[alert.buttons[button] tap];
return YES;
}
}
}
return NO;
}
} // namespace
NSDictionary<NSString*, NSArray<NSString*>*>* TextToButtonsOfKnownSystemAlerts(
void) {
static NSDictionary<NSString*, NSArray<NSString*>*>* text_to_buttons = nil;
static dispatch_once_t once_token;
dispatch_once(&once_token, ^{
text_to_buttons = @{
@"Software Update" : @[ @"Later", @"Remind Me Later" ],
@"A new iOS update is now available." : @[ @"Close" ],
@"Carrier Settings Update" : @[ @"Not Now" ],
@"would like to find and connect to devices on your local network" :
@[ @"OK", @"Allow" ],
@"Unable to activate Touch ID on this iPhone." : @[ @"OK" ],
@"Like to Access the Microphone" : @[ @"OK" ],
@"Edit Home Screen" : @[ @"Dismiss" ],
@"Apple ID Verification" : @[ @"Not Now" ],
@"iPhone is not Activated" : @[ @"Dismiss" ],
@"Apple Account Verification" : @[ @"Not Now" ],
@"to find devices on local networks" : @[ @"Allow" ],
};
});
return text_to_buttons;
}
BOOL HandleKnownSystemAlertsIfVisible(void) {
XCUIApplication* springboard_app = [[XCUIApplication alloc]
initWithBundleIdentifier:@"com.apple.springboard"];
XCUIElement* alert = springboard_app.alerts.firstMatch;
// Limit attempt times. If attempt limit is exceeded, it means something went
// wrong in tapping the buttons.
int attempt = 0;
while (
attempt < 5 &&
[alert
waitForExistenceWithTimeout:kWaitForUIElementTimeout.InSecondsF()]) {
NSLog(@"Alert on screen: %@", alert.label);
if (!HandleSingleAlert(alert)) {
return NO;
}
attempt++;
}
return attempt < 5;
}