blob: 2a4e8565401eb324602ba5e690872a92d0645a0c [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/testing/earl_grey/base_earl_grey_test_case.h"
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/strings/sys_string_conversions.h"
#import "ios/testing/earl_grey/app_launch_manager.h"
#import "ios/testing/earl_grey/base_earl_grey_test_case_app_interface.h"
#import "ios/testing/earl_grey/coverage_utils.h"
#import "ios/testing/earl_grey/earl_grey_test.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
#if defined(CHROME_EARL_GREY_2)
GREY_STUB_CLASS_IN_APP_MAIN_QUEUE(BaseEarlGreyTestCaseAppInterface)
#endif // defined(CHROME_EARL_GREY_2)
namespace {
// If true, +setUpForTestCase will be called from -setUp. This flag is used to
// ensure that +setUpForTestCase is called exactly once per unique XCTestCase
// and is reset in +tearDown.
bool g_needs_set_up_for_test_case = true;
} // namespace
@implementation BaseEarlGreyTestCase
+ (void)setUpForTestCase {
}
// Invoked upon starting each test method in a test case.
// Launches the app under test if necessary.
- (void)setUp {
[super setUp];
#if defined(CHROME_EARL_GREY_2)
[self launchAppForTestMethod];
[self handleSystemAlertIfVisible];
NSString* logFormat = @"*********************************\nStarting test: %@";
[BaseEarlGreyTestCaseAppInterface
logMessage:[NSString stringWithFormat:logFormat, self.name]];
// Calling XCTFail before the application is launched does not assert
// properly, so failing upon detection of overriding +setUp is delayed until
// here. See +setUp below for details on why overriding +setUp causes a
// failure.
[self failIfSetUpIsOverridden];
#endif
if (g_needs_set_up_for_test_case) {
g_needs_set_up_for_test_case = false;
[CoverageUtils configureCoverageReportPath];
[[self class] setUpForTestCase];
}
}
+ (void)tearDown {
g_needs_set_up_for_test_case = true;
[super tearDown];
}
// Handles system alerts if any are present, closing them to unblock the UI.
- (void)handleSystemAlertIfVisible {
#if defined(CHROME_EARL_GREY_2)
NSError* systemAlertFoundError = nil;
[[EarlGrey selectElementWithMatcher:grey_systemAlertViewShown()]
assertWithMatcher:grey_nil()
error:&systemAlertFoundError];
if (systemAlertFoundError) {
NSError* alertGetTextError = nil;
NSString* alertText =
[self grey_systemAlertTextWithError:&alertGetTextError];
GREYAssertNil(alertGetTextError, @"Error getting alert text.\n%@",
alertGetTextError);
// If the system alert is of a known type, accept it.
// Otherwise, reject it, as unknown types include alerts which are not
// desirable to accept, including OS upgrades.
if ([self grey_systemAlertType] != GREYSystemAlertTypeUnknown) {
DLOG(WARNING) << "Accepting iOS system alert: "
<< base::SysNSStringToUTF8(alertText);
NSError* acceptAlertError = nil;
[self grey_acceptSystemDialogWithError:&acceptAlertError];
GREYAssertNil(acceptAlertError, @"Error accepting system alert.\n%@",
acceptAlertError);
} else {
DLOG(WARNING) << "Denying iOS system alert of unknown type: "
<< base::SysNSStringToUTF8(alertText);
NSError* denyAlertError = nil;
[self grey_denySystemDialogWithError:&denyAlertError];
GREYAssertNil(denyAlertError, @"Error denying system alert.\n%@",
denyAlertError);
}
}
#endif // CHROME_EARL_GREY_2
}
- (void)launchAppForTestMethod {
[[AppLaunchManager sharedManager] ensureAppLaunchedWithFeaturesEnabled:{}
disabled:{}
forceRestart:NO];
}
// Prevents tests inheriting from this class from putting logic in +setUp.
// +setUp will be called before the application is launched,
// and thus is not suitable for most test case setup. Inheriting tests should
// migrate their +setUp logic to use the equivalent -setUpForTestCase.
- (void)failIfSetUpIsOverridden {
if ([[BaseEarlGreyTestCase class] methodForSelector:@selector(setUp)] !=
[[self class] methodForSelector:@selector(setUp)]) {
XCTFail(@"EG2 test class %@ inheriting from BaseEarlGreyTestCase "
@"should not override +setUp, as it is called before the "
@"test application is launched. Please convert your "
@"+setUp method to +setUpForTestCase.",
NSStringFromClass([self class]));
}
}
@end