| Index: ios/chrome/test/earl_grey/chrome_test_case.mm
|
| diff --git a/ios/chrome/test/earl_grey/chrome_test_case.mm b/ios/chrome/test/earl_grey/chrome_test_case.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1dfa8560aaaa7934270e6cf2c8fc5d96ec5b883f
|
| --- /dev/null
|
| +++ b/ios/chrome/test/earl_grey/chrome_test_case.mm
|
| @@ -0,0 +1,297 @@
|
| +// Copyright 2016 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/chrome/test/earl_grey/chrome_test_case.h"
|
| +
|
| +#import <objc/runtime.h>
|
| +
|
| +#import <EarlGrey/EarlGrey.h>
|
| +
|
| +#include "base/mac/scoped_block.h"
|
| +#include "base/strings/sys_string_conversions.h"
|
| +#import "ios/chrome/test/app/chrome_test_util.h"
|
| +#import "ios/chrome/test/app/settings_test_util.h"
|
| +#include "ios/chrome/test/app/signin_test_util.h"
|
| +#import "ios/chrome/test/app/sync_test_util.h"
|
| +#import "ios/chrome/test/app/tab_test_util.h"
|
| +#import "ios/web/public/test/http_server.h"
|
| +
|
| +namespace {
|
| +
|
| +// Contains a list of test names that run in multitasking test suite.
|
| +NSArray* whiteListedMultitaskingTests = @[
|
| + // Integration tests
|
| + @"testContextMenuOpenInNewTab", // ContextMenuTestCase
|
| + @"testSwitchToMain", // CookiesTestCase
|
| + @"testSwitchToIncognito", // CookiesTestCase
|
| + @"testFindDefaultFormAssistControls", // FormInputTestCase
|
| + @"testTabDeletion", // TabUsageRecorderTestCase
|
| + @"testAutoTranslate", // TranslateTestCase
|
| +
|
| + // Settings tests
|
| + @"testSignInPopUpAccountOnSyncSettings", // AccountCollectionsTestCase
|
| + @"testAutofillProfileEditing", // AutofillSettingsTestCase
|
| + @"testAccessibilityOfBlockPopupSettings", // BlockPopupsTestCase
|
| + @"testClearCookies", // SettingsTestCase
|
| + @"testAccessibilityOfTranslateSettings", // TranslateUITestCase
|
| +
|
| + // UI tests
|
| + @"testActivityServiceControllerPrintAfterRedirectionToUnprintablePage",
|
| + // ActivityServiceControllerTestCase
|
| + @"testDismissOnDestroy", // AlertCoordinatorTestCase
|
| + @"testAddRemoveBookmark", // BookmarksTestCase
|
| + @"testJavaScriptInOmnibox", // BrowserViewControllerTestCase
|
| + @"testChooseCastReceiverChooser", // CastReceiverTestCase
|
| + @"testErrorPage", // ErrorPageTestCase
|
| + @"testFindInPage", // FindInPageTestCase
|
| + @"testDismissFirstRun", // FirstRunTestCase
|
| + @"testLongPDFScroll", // FullscreenTestCase
|
| + @"testDeleteHistory", // HistoryUITestCase
|
| + @"testInfobarsDismissOnNavigate", // InfobarTestCase
|
| + @"testShowJavaScriptAlert", // JavaScriptDialogTestCase
|
| + @"testKeyboardCommands_RecentTabsPresented", // KeyboardCommandsTestCase
|
| + @"testAccessibilityOnMostVisited", // NewTabPageTestCase
|
| + @"testPrintNormalPage", // PrintControllerTestCase
|
| + @"testQRScannerUIIsShown", // QRScannerViewControllerTestCase
|
| + @"testMarkMixedEntriesRead", // ReadingListTestCase
|
| + @"testClosedTabAppearsInRecentTabsPanel",
|
| + // RecentTabsPanelControllerTestCase
|
| + @"testSafeModeSendingCrashReport", // SafeModeTestCase
|
| + @"testSignInOneUser", // SigninInteractionControllerTestCase
|
| + @"testSwitchTabs", // StackViewTestCase
|
| + @"testTabStripSwitchTabs", // TabStripTestCase
|
| + @"testTabHistoryMenu", // TabHistoryPopupControllerTestCase
|
| + @"testEnteringTabSwitcher", // TabSwitcherControllerTestCase
|
| + @"testEnterURL", // ToolbarTestCase
|
| + @"testOpenAndCloseToolsMenu", // ToolsPopupMenuTestCase
|
| + @"testUserFeedbackPageOpenPrivacyPolicy", // UserFeedbackTestCase
|
| + @"testVersion", // WebUITestCase
|
| +];
|
| +} // namespace
|
| +
|
| +@interface ChromeTestCase () {
|
| + // Block to be executed during object tearDown.
|
| + base::mac::ScopedBlock<ProceduralBlock> _tearDownHandler;
|
| +
|
| + BOOL _isHTTPServerStopped;
|
| + BOOL _isMockAuthenticationDisabled;
|
| +}
|
| +
|
| +// Cleans up mock authentication.
|
| ++ (void)disableMockAuthentication;
|
| +
|
| +// Sets up mock authentication.
|
| ++ (void)enableMockAuthentication;
|
| +
|
| +// Stops the HTTP server. Should only be called when the server is running.
|
| ++ (void)stopHTTPServer;
|
| +
|
| +// Starts the HTTP server. Should only be called when the server is stopped.
|
| ++ (void)startHTTPServer;
|
| +
|
| +// Returns a NSArray of test names in this class that contain the prefix
|
| +// "FLAKY_".
|
| ++ (NSArray*)flakyTestNames;
|
| +
|
| +// Returns a NSArray of test names in this class for multitasking test suite.
|
| ++ (NSArray*)multitaskingTestNames;
|
| +@end
|
| +
|
| +@implementation ChromeTestCase
|
| +
|
| +// Overrides testInvocations so the set of tests run can be modified, as
|
| +// necessary.
|
| ++ (NSArray*)testInvocations {
|
| + NSError* error = nil;
|
| + [[EarlGrey selectElementWithMatcher:grey_systemAlertViewShown()]
|
| + assertWithMatcher:grey_nil()
|
| + error:&error];
|
| + if (error != nil) {
|
| + NSLog(@"System alert view is present, so skipping all tests!");
|
| + return @[];
|
| + }
|
| +
|
| + // Return specific list of tests based on the target.
|
| + NSString* targetName = [NSBundle mainBundle].infoDictionary[@"CFBundleName"];
|
| + if ([targetName isEqualToString:@"ios_chrome_flaky_egtests"]) {
|
| + // Only run FLAKY_ tests for the flaky test suite.
|
| + return [self flakyTestNames];
|
| + } else if ([targetName isEqualToString:@"ios_chrome_multitasking_egtests"]) {
|
| + // Only run white listed tests for the multitasking test suite.
|
| + return [self multitaskingTestNames];
|
| + } else {
|
| + return [super testInvocations];
|
| + }
|
| +}
|
| +
|
| +// Set up called once for the class, to dismiss anything displayed on startup
|
| +// and revert browser settings to default. It also starts the HTTP server and
|
| +// enables mock authentication.
|
| ++ (void)setUp {
|
| + [super setUp];
|
| + [[self class] startHTTPServer];
|
| + [[self class] enableMockAuthentication];
|
| +
|
| + // Sometimes on start up there can be infobars (e.g. restore session), so
|
| + // ensure the UI is in a clean state.
|
| + [self removeAnyOpenMenusAndInfoBars];
|
| + [self closeAllTabs];
|
| + chrome_test_util::SetContentSettingsBlockPopups(CONTENT_SETTING_DEFAULT);
|
| +}
|
| +
|
| +// Tear down called once for the class, to shutdown mock authentication and
|
| +// the HTTP server.
|
| ++ (void)tearDown {
|
| + [[self class] disableMockAuthentication];
|
| + [[self class] stopHTTPServer];
|
| + [super tearDown];
|
| +}
|
| +
|
| +// Set up called once per test, to open a new tab.
|
| +- (void)setUp {
|
| + [super setUp];
|
| + _isHTTPServerStopped = NO;
|
| + _isMockAuthenticationDisabled = NO;
|
| + _tearDownHandler.reset();
|
| +
|
| + chrome_test_util::OpenNewTab();
|
| + [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
|
| +}
|
| +
|
| +// Tear down called once per test, to close all tabs and menus, and clear the
|
| +// tracked tests accounts. It also makes sure mock authentication and the HTTP
|
| +// server are running.
|
| +- (void)tearDown {
|
| + if (_tearDownHandler) {
|
| + _tearDownHandler.get()();
|
| + }
|
| +
|
| + // Clear any remaining test accounts and signed in users.
|
| + chrome_test_util::SignOutAndClearAccounts();
|
| +
|
| + // Re-start anything that was disabled this test, so it is running when the
|
| + // next test starts.
|
| + if (_isHTTPServerStopped) {
|
| + [[self class] startHTTPServer];
|
| + _isHTTPServerStopped = NO;
|
| + }
|
| + if (_isMockAuthenticationDisabled) {
|
| + [[self class] enableMockAuthentication];
|
| + _isMockAuthenticationDisabled = NO;
|
| + }
|
| +
|
| + // Clean up any UI that may remain open so the next test starts in a clean
|
| + // state.
|
| + [[self class] removeAnyOpenMenusAndInfoBars];
|
| + [[self class] closeAllTabs];
|
| + [super tearDown];
|
| +}
|
| +
|
| +#pragma mark - Public methods
|
| +
|
| +- (void)setTearDownHandler:(ProceduralBlock)tearDownHandler {
|
| + // Enforce that only one |_tearDownHandler| is set per test.
|
| + DCHECK(!_tearDownHandler);
|
| + _tearDownHandler.reset([tearDownHandler copy]);
|
| +}
|
| +
|
| ++ (void)removeAnyOpenMenusAndInfoBars {
|
| + chrome_test_util::RemoveAllInfoBars();
|
| + chrome_test_util::ClearPresentedState();
|
| + // After programatically removing UI elements, allow Earl Grey's
|
| + // UI synchronization to become idle, so subsequent steps won't start before
|
| + // the UI is in a good state.
|
| + [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
|
| +}
|
| +
|
| ++ (void)closeAllTabs {
|
| + chrome_test_util::CloseAllTabs();
|
| + [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
|
| +}
|
| +
|
| +- (void)disableMockAuthentication {
|
| + // Enforce that disableMockAuthentication can only be called once.
|
| + DCHECK(!_isMockAuthenticationDisabled);
|
| + [[self class] disableMockAuthentication];
|
| + _isMockAuthenticationDisabled = YES;
|
| +}
|
| +
|
| +- (void)stopHTTPServer {
|
| + // Enforce that the HTTP server can only be stopped once per test. It should
|
| + // not be stopped if it is not running.
|
| + DCHECK(!_isHTTPServerStopped);
|
| + [[self class] stopHTTPServer];
|
| + _isHTTPServerStopped = YES;
|
| +}
|
| +
|
| +#pragma mark - Private methods
|
| +
|
| ++ (void)disableMockAuthentication {
|
| + // Make sure local data is cleared, before disabling mock authentication,
|
| + // where data may be sent to real servers.
|
| + chrome_test_util::SignOutAndClearAccounts();
|
| + chrome_test_util::TearDownFakeSyncServer();
|
| + chrome_test_util::TearDownMockAccountReconcilor();
|
| + chrome_test_util::TearDownMockAuthentication();
|
| +}
|
| +
|
| ++ (void)enableMockAuthentication {
|
| + chrome_test_util::SetUpMockAuthentication();
|
| + chrome_test_util::SetUpMockAccountReconcilor();
|
| + chrome_test_util::SetUpFakeSyncServer();
|
| +}
|
| +
|
| ++ (void)stopHTTPServer {
|
| + web::test::HttpServer& server = web::test::HttpServer::GetSharedInstance();
|
| + DCHECK(server.IsRunning());
|
| + server.Stop();
|
| +}
|
| +
|
| ++ (void)startHTTPServer {
|
| + web::test::HttpServer& server = web::test::HttpServer::GetSharedInstance();
|
| + DCHECK(!server.IsRunning());
|
| + server.StartOrDie();
|
| +}
|
| +
|
| ++ (NSArray*)flakyTestNames {
|
| + const char kFlakyTestPrefix[] = "FLAKY";
|
| + unsigned int count = 0;
|
| + Method* methods = class_copyMethodList(self, &count);
|
| + NSMutableArray* flakyTestNames = [NSMutableArray array];
|
| + for (unsigned int i = 0; i < count; i++) {
|
| + SEL selector = method_getName(methods[i]);
|
| + if (std::string(sel_getName(selector)).find(kFlakyTestPrefix) == 0) {
|
| + NSMethodSignature* methodSignature =
|
| + [self instanceMethodSignatureForSelector:selector];
|
| + NSInvocation* invocation =
|
| + [NSInvocation invocationWithMethodSignature:methodSignature];
|
| + invocation.selector = selector;
|
| + [flakyTestNames addObject:invocation];
|
| + }
|
| + }
|
| + free(methods);
|
| + return flakyTestNames;
|
| +}
|
| +
|
| ++ (NSArray*)multitaskingTestNames {
|
| + unsigned int count = 0;
|
| + Method* methods = class_copyMethodList(self, &count);
|
| + NSMutableArray* multitaskingTestNames = [NSMutableArray array];
|
| + for (unsigned int i = 0; i < count; i++) {
|
| + SEL selector = method_getName(methods[i]);
|
| + if ([whiteListedMultitaskingTests
|
| + containsObject:base::SysUTF8ToNSString(sel_getName(selector))]) {
|
| + NSMethodSignature* methodSignature =
|
| + [self instanceMethodSignatureForSelector:selector];
|
| + NSInvocation* invocation =
|
| + [NSInvocation invocationWithMethodSignature:methodSignature];
|
| + invocation.selector = selector;
|
| + [multitaskingTestNames addObject:invocation];
|
| + }
|
| + }
|
| + free(methods);
|
| + return multitaskingTestNames;
|
| +}
|
| +
|
| +@end
|
|
|