OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #import "ios/chrome/test/earl_grey/chrome_test_case.h" |
| 6 |
| 7 #import <objc/runtime.h> |
| 8 |
| 9 #import <EarlGrey/EarlGrey.h> |
| 10 |
| 11 #include "base/mac/scoped_block.h" |
| 12 #include "base/strings/sys_string_conversions.h" |
| 13 #import "ios/chrome/test/app/chrome_test_util.h" |
| 14 #import "ios/chrome/test/app/settings_test_util.h" |
| 15 #include "ios/chrome/test/app/signin_test_util.h" |
| 16 #import "ios/chrome/test/app/sync_test_util.h" |
| 17 #import "ios/chrome/test/app/tab_test_util.h" |
| 18 #import "ios/web/public/test/http_server.h" |
| 19 |
| 20 namespace { |
| 21 |
| 22 // Contains a list of test names that run in multitasking test suite. |
| 23 NSArray* whiteListedMultitaskingTests = @[ |
| 24 // Integration tests |
| 25 @"testContextMenuOpenInNewTab", // ContextMenuTestCase |
| 26 @"testSwitchToMain", // CookiesTestCase |
| 27 @"testSwitchToIncognito", // CookiesTestCase |
| 28 @"testFindDefaultFormAssistControls", // FormInputTestCase |
| 29 @"testTabDeletion", // TabUsageRecorderTestCase |
| 30 @"testAutoTranslate", // TranslateTestCase |
| 31 |
| 32 // Settings tests |
| 33 @"testSignInPopUpAccountOnSyncSettings", // AccountCollectionsTestCase |
| 34 @"testAutofillProfileEditing", // AutofillSettingsTestCase |
| 35 @"testAccessibilityOfBlockPopupSettings", // BlockPopupsTestCase |
| 36 @"testClearCookies", // SettingsTestCase |
| 37 @"testAccessibilityOfTranslateSettings", // TranslateUITestCase |
| 38 |
| 39 // UI tests |
| 40 @"testActivityServiceControllerPrintAfterRedirectionToUnprintablePage", |
| 41 // ActivityServiceControllerTestCase |
| 42 @"testDismissOnDestroy", // AlertCoordinatorTestCase |
| 43 @"testAddRemoveBookmark", // BookmarksTestCase |
| 44 @"testJavaScriptInOmnibox", // BrowserViewControllerTestCase |
| 45 @"testChooseCastReceiverChooser", // CastReceiverTestCase |
| 46 @"testErrorPage", // ErrorPageTestCase |
| 47 @"testFindInPage", // FindInPageTestCase |
| 48 @"testDismissFirstRun", // FirstRunTestCase |
| 49 @"testLongPDFScroll", // FullscreenTestCase |
| 50 @"testDeleteHistory", // HistoryUITestCase |
| 51 @"testInfobarsDismissOnNavigate", // InfobarTestCase |
| 52 @"testShowJavaScriptAlert", // JavaScriptDialogTestCase |
| 53 @"testKeyboardCommands_RecentTabsPresented", // KeyboardCommandsTestCase |
| 54 @"testAccessibilityOnMostVisited", // NewTabPageTestCase |
| 55 @"testPrintNormalPage", // PrintControllerTestCase |
| 56 @"testQRScannerUIIsShown", // QRScannerViewControllerTestCase |
| 57 @"testMarkMixedEntriesRead", // ReadingListTestCase |
| 58 @"testClosedTabAppearsInRecentTabsPanel", |
| 59 // RecentTabsPanelControllerTestCase |
| 60 @"testSafeModeSendingCrashReport", // SafeModeTestCase |
| 61 @"testSignInOneUser", // SigninInteractionControllerTestCase |
| 62 @"testSwitchTabs", // StackViewTestCase |
| 63 @"testTabStripSwitchTabs", // TabStripTestCase |
| 64 @"testTabHistoryMenu", // TabHistoryPopupControllerTestCase |
| 65 @"testEnteringTabSwitcher", // TabSwitcherControllerTestCase |
| 66 @"testEnterURL", // ToolbarTestCase |
| 67 @"testOpenAndCloseToolsMenu", // ToolsPopupMenuTestCase |
| 68 @"testUserFeedbackPageOpenPrivacyPolicy", // UserFeedbackTestCase |
| 69 @"testVersion", // WebUITestCase |
| 70 ]; |
| 71 } // namespace |
| 72 |
| 73 @interface ChromeTestCase () { |
| 74 // Block to be executed during object tearDown. |
| 75 base::mac::ScopedBlock<ProceduralBlock> _tearDownHandler; |
| 76 |
| 77 BOOL _isHTTPServerStopped; |
| 78 BOOL _isMockAuthenticationDisabled; |
| 79 } |
| 80 |
| 81 // Cleans up mock authentication. |
| 82 + (void)disableMockAuthentication; |
| 83 |
| 84 // Sets up mock authentication. |
| 85 + (void)enableMockAuthentication; |
| 86 |
| 87 // Stops the HTTP server. Should only be called when the server is running. |
| 88 + (void)stopHTTPServer; |
| 89 |
| 90 // Starts the HTTP server. Should only be called when the server is stopped. |
| 91 + (void)startHTTPServer; |
| 92 |
| 93 // Returns a NSArray of test names in this class that contain the prefix |
| 94 // "FLAKY_". |
| 95 + (NSArray*)flakyTestNames; |
| 96 |
| 97 // Returns a NSArray of test names in this class for multitasking test suite. |
| 98 + (NSArray*)multitaskingTestNames; |
| 99 @end |
| 100 |
| 101 @implementation ChromeTestCase |
| 102 |
| 103 // Overrides testInvocations so the set of tests run can be modified, as |
| 104 // necessary. |
| 105 + (NSArray*)testInvocations { |
| 106 NSError* error = nil; |
| 107 [[EarlGrey selectElementWithMatcher:grey_systemAlertViewShown()] |
| 108 assertWithMatcher:grey_nil() |
| 109 error:&error]; |
| 110 if (error != nil) { |
| 111 NSLog(@"System alert view is present, so skipping all tests!"); |
| 112 return @[]; |
| 113 } |
| 114 |
| 115 // Return specific list of tests based on the target. |
| 116 NSString* targetName = [NSBundle mainBundle].infoDictionary[@"CFBundleName"]; |
| 117 if ([targetName isEqualToString:@"ios_chrome_flaky_egtests"]) { |
| 118 // Only run FLAKY_ tests for the flaky test suite. |
| 119 return [self flakyTestNames]; |
| 120 } else if ([targetName isEqualToString:@"ios_chrome_multitasking_egtests"]) { |
| 121 // Only run white listed tests for the multitasking test suite. |
| 122 return [self multitaskingTestNames]; |
| 123 } else { |
| 124 return [super testInvocations]; |
| 125 } |
| 126 } |
| 127 |
| 128 // Set up called once for the class, to dismiss anything displayed on startup |
| 129 // and revert browser settings to default. It also starts the HTTP server and |
| 130 // enables mock authentication. |
| 131 + (void)setUp { |
| 132 [super setUp]; |
| 133 [[self class] startHTTPServer]; |
| 134 [[self class] enableMockAuthentication]; |
| 135 |
| 136 // Sometimes on start up there can be infobars (e.g. restore session), so |
| 137 // ensure the UI is in a clean state. |
| 138 [self removeAnyOpenMenusAndInfoBars]; |
| 139 [self closeAllTabs]; |
| 140 chrome_test_util::SetContentSettingsBlockPopups(CONTENT_SETTING_DEFAULT); |
| 141 } |
| 142 |
| 143 // Tear down called once for the class, to shutdown mock authentication and |
| 144 // the HTTP server. |
| 145 + (void)tearDown { |
| 146 [[self class] disableMockAuthentication]; |
| 147 [[self class] stopHTTPServer]; |
| 148 [super tearDown]; |
| 149 } |
| 150 |
| 151 // Set up called once per test, to open a new tab. |
| 152 - (void)setUp { |
| 153 [super setUp]; |
| 154 _isHTTPServerStopped = NO; |
| 155 _isMockAuthenticationDisabled = NO; |
| 156 _tearDownHandler.reset(); |
| 157 |
| 158 chrome_test_util::OpenNewTab(); |
| 159 [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; |
| 160 } |
| 161 |
| 162 // Tear down called once per test, to close all tabs and menus, and clear the |
| 163 // tracked tests accounts. It also makes sure mock authentication and the HTTP |
| 164 // server are running. |
| 165 - (void)tearDown { |
| 166 if (_tearDownHandler) { |
| 167 _tearDownHandler.get()(); |
| 168 } |
| 169 |
| 170 // Clear any remaining test accounts and signed in users. |
| 171 chrome_test_util::SignOutAndClearAccounts(); |
| 172 |
| 173 // Re-start anything that was disabled this test, so it is running when the |
| 174 // next test starts. |
| 175 if (_isHTTPServerStopped) { |
| 176 [[self class] startHTTPServer]; |
| 177 _isHTTPServerStopped = NO; |
| 178 } |
| 179 if (_isMockAuthenticationDisabled) { |
| 180 [[self class] enableMockAuthentication]; |
| 181 _isMockAuthenticationDisabled = NO; |
| 182 } |
| 183 |
| 184 // Clean up any UI that may remain open so the next test starts in a clean |
| 185 // state. |
| 186 [[self class] removeAnyOpenMenusAndInfoBars]; |
| 187 [[self class] closeAllTabs]; |
| 188 [super tearDown]; |
| 189 } |
| 190 |
| 191 #pragma mark - Public methods |
| 192 |
| 193 - (void)setTearDownHandler:(ProceduralBlock)tearDownHandler { |
| 194 // Enforce that only one |_tearDownHandler| is set per test. |
| 195 DCHECK(!_tearDownHandler); |
| 196 _tearDownHandler.reset([tearDownHandler copy]); |
| 197 } |
| 198 |
| 199 + (void)removeAnyOpenMenusAndInfoBars { |
| 200 chrome_test_util::RemoveAllInfoBars(); |
| 201 chrome_test_util::ClearPresentedState(); |
| 202 // After programatically removing UI elements, allow Earl Grey's |
| 203 // UI synchronization to become idle, so subsequent steps won't start before |
| 204 // the UI is in a good state. |
| 205 [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; |
| 206 } |
| 207 |
| 208 + (void)closeAllTabs { |
| 209 chrome_test_util::CloseAllTabs(); |
| 210 [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; |
| 211 } |
| 212 |
| 213 - (void)disableMockAuthentication { |
| 214 // Enforce that disableMockAuthentication can only be called once. |
| 215 DCHECK(!_isMockAuthenticationDisabled); |
| 216 [[self class] disableMockAuthentication]; |
| 217 _isMockAuthenticationDisabled = YES; |
| 218 } |
| 219 |
| 220 - (void)stopHTTPServer { |
| 221 // Enforce that the HTTP server can only be stopped once per test. It should |
| 222 // not be stopped if it is not running. |
| 223 DCHECK(!_isHTTPServerStopped); |
| 224 [[self class] stopHTTPServer]; |
| 225 _isHTTPServerStopped = YES; |
| 226 } |
| 227 |
| 228 #pragma mark - Private methods |
| 229 |
| 230 + (void)disableMockAuthentication { |
| 231 // Make sure local data is cleared, before disabling mock authentication, |
| 232 // where data may be sent to real servers. |
| 233 chrome_test_util::SignOutAndClearAccounts(); |
| 234 chrome_test_util::TearDownFakeSyncServer(); |
| 235 chrome_test_util::TearDownMockAccountReconcilor(); |
| 236 chrome_test_util::TearDownMockAuthentication(); |
| 237 } |
| 238 |
| 239 + (void)enableMockAuthentication { |
| 240 chrome_test_util::SetUpMockAuthentication(); |
| 241 chrome_test_util::SetUpMockAccountReconcilor(); |
| 242 chrome_test_util::SetUpFakeSyncServer(); |
| 243 } |
| 244 |
| 245 + (void)stopHTTPServer { |
| 246 web::test::HttpServer& server = web::test::HttpServer::GetSharedInstance(); |
| 247 DCHECK(server.IsRunning()); |
| 248 server.Stop(); |
| 249 } |
| 250 |
| 251 + (void)startHTTPServer { |
| 252 web::test::HttpServer& server = web::test::HttpServer::GetSharedInstance(); |
| 253 DCHECK(!server.IsRunning()); |
| 254 server.StartOrDie(); |
| 255 } |
| 256 |
| 257 + (NSArray*)flakyTestNames { |
| 258 const char kFlakyTestPrefix[] = "FLAKY"; |
| 259 unsigned int count = 0; |
| 260 Method* methods = class_copyMethodList(self, &count); |
| 261 NSMutableArray* flakyTestNames = [NSMutableArray array]; |
| 262 for (unsigned int i = 0; i < count; i++) { |
| 263 SEL selector = method_getName(methods[i]); |
| 264 if (std::string(sel_getName(selector)).find(kFlakyTestPrefix) == 0) { |
| 265 NSMethodSignature* methodSignature = |
| 266 [self instanceMethodSignatureForSelector:selector]; |
| 267 NSInvocation* invocation = |
| 268 [NSInvocation invocationWithMethodSignature:methodSignature]; |
| 269 invocation.selector = selector; |
| 270 [flakyTestNames addObject:invocation]; |
| 271 } |
| 272 } |
| 273 free(methods); |
| 274 return flakyTestNames; |
| 275 } |
| 276 |
| 277 + (NSArray*)multitaskingTestNames { |
| 278 unsigned int count = 0; |
| 279 Method* methods = class_copyMethodList(self, &count); |
| 280 NSMutableArray* multitaskingTestNames = [NSMutableArray array]; |
| 281 for (unsigned int i = 0; i < count; i++) { |
| 282 SEL selector = method_getName(methods[i]); |
| 283 if ([whiteListedMultitaskingTests |
| 284 containsObject:base::SysUTF8ToNSString(sel_getName(selector))]) { |
| 285 NSMethodSignature* methodSignature = |
| 286 [self instanceMethodSignatureForSelector:selector]; |
| 287 NSInvocation* invocation = |
| 288 [NSInvocation invocationWithMethodSignature:methodSignature]; |
| 289 invocation.selector = selector; |
| 290 [multitaskingTestNames addObject:invocation]; |
| 291 } |
| 292 } |
| 293 free(methods); |
| 294 return multitaskingTestNames; |
| 295 } |
| 296 |
| 297 @end |
OLD | NEW |