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 <EarlGrey/EarlGrey.h> |
| 6 #import <XCTest/XCTest.h> |
| 7 |
| 8 #include "base/mac/bind_objc_block.h" |
| 9 #include "base/memory/ptr_util.h" |
| 10 #include "base/strings/stringprintf.h" |
| 11 #include "base/strings/sys_string_conversions.h" |
| 12 #include "base/strings/utf_string_conversions.h" |
| 13 #import "base/test/ios/wait_util.h" |
| 14 #include "components/strings/grit/components_strings.h" |
| 15 #include "ios/chrome/browser/experimental_flags.h" |
| 16 #import "ios/chrome/browser/metrics/tab_usage_recorder.h" |
| 17 #import "ios/chrome/browser/ui/settings/privacy_collection_view_controller.h" |
| 18 #import "ios/chrome/browser/ui/settings/settings_collection_view_controller.h" |
| 19 #import "ios/chrome/browser/ui/toolbar/toolbar_controller.h" |
| 20 #import "ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.h" |
| 21 #include "ios/chrome/browser/ui/ui_util.h" |
| 22 #import "ios/chrome/browser/ui/uikit_ui_util.h" |
| 23 #include "ios/chrome/grit/ios_strings.h" |
| 24 #import "ios/chrome/test/app/chrome_test_util.h" |
| 25 #import "ios/chrome/test/app/histogram_test_util.h" |
| 26 #include "ios/chrome/test/app/navigation_test_util.h" |
| 27 #import "ios/chrome/test/app/tab_test_util.h" |
| 28 #include "ios/chrome/test/app/web_view_interaction_test_util.h" |
| 29 #import "ios/chrome/test/earl_grey/chrome_assertions.h" |
| 30 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" |
| 31 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h" |
| 32 #import "ios/chrome/test/earl_grey/chrome_matchers.h" |
| 33 #import "ios/chrome/test/earl_grey/chrome_test_case.h" |
| 34 #import "ios/testing/wait_util.h" |
| 35 #import "ios/web/public/test/http_server.h" |
| 36 #import "ios/web/public/test/http_server_util.h" |
| 37 #include "ios/web/public/test/response_providers/delayed_response_provider.h" |
| 38 #include "ios/web/public/test/response_providers/html_response_provider.h" |
| 39 #include "ui/base/l10n/l10n_util.h" |
| 40 #include "ui/base/l10n/l10n_util_mac.h" |
| 41 |
| 42 namespace { |
| 43 |
| 44 const char kTestUrl1[] = |
| 45 "http://ios/testing/data/http_server_files/memory_usage.html"; |
| 46 const char kURL1FirstWord[] = "Page"; |
| 47 const char kTestUrl2[] = |
| 48 "http://ios/testing/data/http_server_files/fullscreen.html"; |
| 49 const char kURL2FirstWord[] = "Rugby"; |
| 50 const char kClearPageScript[] = "document.body.innerHTML='';"; |
| 51 |
| 52 // The delay to use to serve slow URLs. |
| 53 const CGFloat kSlowURLDelay = 3; |
| 54 |
| 55 // The delay to wait for an element to appear before tapping on it. |
| 56 const CGFloat kWaitElementTimeout = 3; |
| 57 |
| 58 void ResetTabUsageRecorder() { |
| 59 GREYAssertTrue(chrome_test_util::ResetTabUsageRecorder(), |
| 60 @"Fail to reset the TabUsageRecorder"); |
| 61 } |
| 62 |
| 63 // Wait until |matcher| is accessible (not nil). |
| 64 void Wait(id<GREYMatcher> matcher, NSString* name) { |
| 65 ConditionBlock condition = ^{ |
| 66 NSError* error = nil; |
| 67 [[EarlGrey selectElementWithMatcher:matcher] assertWithMatcher:grey_notNil() |
| 68 error:&error]; |
| 69 return error == nil; |
| 70 }; |
| 71 GREYAssert( |
| 72 testing::WaitUntilConditionOrTimeout(kWaitElementTimeout, condition), |
| 73 [NSString stringWithFormat:@"Waiting for matcher %@ failed.", name]); |
| 74 } |
| 75 |
| 76 // Wait until |matcher| is accessible (not nil) and tap on it. |
| 77 void WaitAndTap(id<GREYMatcher> matcher, NSString* name) { |
| 78 Wait(matcher, name); |
| 79 [[EarlGrey selectElementWithMatcher:matcher] performAction:grey_tap()]; |
| 80 } |
| 81 |
| 82 // Creates a new main tab and load |url|. Wait until |word| is visible on the |
| 83 // page. |
| 84 void NewMainTabWithURL(const GURL& url, const std::string& word) { |
| 85 int number_of_tabs = chrome_test_util::GetMainTabCount(); |
| 86 chrome_test_util::OpenNewTab(); |
| 87 [ChromeEarlGrey loadURL:url]; |
| 88 [[EarlGrey |
| 89 selectElementWithMatcher:chrome_test_util::webViewContainingText(word)] |
| 90 assertWithMatcher:grey_notNil()]; |
| 91 chrome_test_util::AssertMainTabCount(number_of_tabs + 1); |
| 92 } |
| 93 |
| 94 // Opens 2 new tabs with different URLs. |
| 95 void OpenTwoTabs() { |
| 96 chrome_test_util::CloseAllTabsInCurrentMode(); |
| 97 |
| 98 const GURL url1 = web::test::HttpServer::MakeUrl(kTestUrl1); |
| 99 const GURL url2 = web::test::HttpServer::MakeUrl(kTestUrl2); |
| 100 NewMainTabWithURL(url1, kURL1FirstWord); |
| 101 NewMainTabWithURL(url2, kURL2FirstWord); |
| 102 } |
| 103 |
| 104 // Opens a new main tab using the UI. This method is using ad-hoc |
| 105 // synchronization. |
| 106 void OpenNewMainTabUsingUIUnsynced() { |
| 107 int nb_main_tab = chrome_test_util::GetMainTabCount(); |
| 108 id<GREYMatcher> tool_menu_matcher = |
| 109 grey_accessibilityID(kToolbarToolsMenuButtonIdentifier); |
| 110 WaitAndTap(tool_menu_matcher, @"Tool menu"); |
| 111 id<GREYMatcher> new_main_tab_button_matcher = |
| 112 grey_accessibilityID(kToolsMenuNewTabId); |
| 113 WaitAndTap(new_main_tab_button_matcher, @"New tab button"); |
| 114 |
| 115 chrome_test_util::AssertMainTabCount(nb_main_tab + 1); |
| 116 } |
| 117 |
| 118 // Opens a new incognito tab using the UI and evicts any main tab model tabs. |
| 119 void OpenNewIncognitoTabUsingUIAndEvictMainTabs() { |
| 120 int nb_incognito_tab = chrome_test_util::GetIncognitoTabCount(); |
| 121 [ChromeEarlGreyUI openToolsMenu]; |
| 122 id<GREYMatcher> new_incognito_tab_button_matcher = |
| 123 grey_accessibilityID(kToolsMenuNewIncognitoTabId); |
| 124 [[EarlGrey selectElementWithMatcher:new_incognito_tab_button_matcher] |
| 125 performAction:grey_tap()]; |
| 126 chrome_test_util::AssertIncognitoTabCount(nb_incognito_tab + 1); |
| 127 |
| 128 chrome_test_util::EvictOtherTabModelTabs(); |
| 129 } |
| 130 |
| 131 // Closes a tab in the current tab model. Synchronize on tab number afterwards. |
| 132 void CloseTabAtIndexAndSync(NSUInteger i) { |
| 133 NSUInteger nb_main_tab = chrome_test_util::GetMainTabCount(); |
| 134 chrome_test_util::CloseTabAtIndex(i); |
| 135 ConditionBlock condition = ^{ |
| 136 return chrome_test_util::GetMainTabCount() == (nb_main_tab - 1); |
| 137 }; |
| 138 GREYAssert( |
| 139 testing::WaitUntilConditionOrTimeout(kWaitElementTimeout, condition), |
| 140 @"Waiting for tab to close"); |
| 141 } |
| 142 |
| 143 // Closes the tabs switcher. |
| 144 void CloseTabSwitcher() { |
| 145 id<GREYMatcher> matcher = chrome_test_util::buttonWithAccessibilityLabelId( |
| 146 IDS_IOS_TAB_STRIP_LEAVE_TAB_SWITCHER); |
| 147 [[EarlGrey selectElementWithMatcher:matcher] performAction:grey_tap()]; |
| 148 } |
| 149 |
| 150 // Swithches to normal mode using swith button (iPad) or stack view (iPhone). |
| 151 // Assumes current mode is Incognito. |
| 152 void SwitchToNormalMode() { |
| 153 GREYAssertTrue(chrome_test_util::IsIncognitoMode(), |
| 154 @"Switching to normal mode is only allowed from Incognito."); |
| 155 if (IsIPadIdiom()) { |
| 156 if (experimental_flags::IsTabSwitcherEnabled()) { |
| 157 // Enter the tab switcher. |
| 158 id<GREYMatcher> tabSwitcherEnterButton = |
| 159 grey_accessibilityLabel(l10n_util::GetNSStringWithFixup( |
| 160 IDS_IOS_TAB_STRIP_ENTER_TAB_SWITCHER)); |
| 161 [[EarlGrey selectElementWithMatcher:tabSwitcherEnterButton] |
| 162 performAction:grey_tap()]; |
| 163 |
| 164 // Select the non incognito panel. |
| 165 id<GREYMatcher> tabSwitcherHeaderPanelButton = |
| 166 grey_accessibilityLabel(l10n_util::GetNSStringWithFixup( |
| 167 IDS_IOS_TAB_SWITCHER_HEADER_NON_INCOGNITO_TABS)); |
| 168 [[EarlGrey selectElementWithMatcher:tabSwitcherHeaderPanelButton] |
| 169 performAction:grey_tap()]; |
| 170 |
| 171 // Leave the tab switcher. |
| 172 CloseTabSwitcher(); |
| 173 } else { |
| 174 [[EarlGrey selectElementWithMatcher: |
| 175 chrome_test_util::buttonWithAccessibilityLabelId( |
| 176 IDS_IOS_SWITCH_BROWSER_MODE_LEAVE_INCOGNITO)] |
| 177 performAction:grey_tap()]; |
| 178 } |
| 179 } else { |
| 180 [[EarlGrey selectElementWithMatcher: |
| 181 chrome_test_util::buttonWithAccessibilityLabelId( |
| 182 IDS_IOS_TOOLBAR_SHOW_TABS)] performAction:grey_tap()]; |
| 183 [[EarlGrey selectElementWithMatcher: |
| 184 chrome_test_util::buttonWithAccessibilityLabelId( |
| 185 IDS_IOS_TOOLS_MENU_NEW_INCOGNITO_TAB)] |
| 186 performAction:grey_swipeFastInDirection(kGREYDirectionRight)]; |
| 187 [[EarlGrey selectElementWithMatcher: |
| 188 chrome_test_util::buttonWithAccessibilityLabelId( |
| 189 IDS_IOS_TOOLBAR_SHOW_TABS)] performAction:grey_tap()]; |
| 190 } |
| 191 GREYAssertFalse(chrome_test_util::IsIncognitoMode(), |
| 192 @"Switching to normal mode failed."); |
| 193 } |
| 194 |
| 195 // Check that the error page is visible. |
| 196 void CheckErrorPageIsVisible() { |
| 197 // The DNS error page is static HTML content, so it isn't part of the webview |
| 198 // owned by the webstate. |
| 199 [[EarlGrey selectElementWithMatcher:chrome_test_util:: |
| 200 webViewBelongingToWebController()] |
| 201 assertWithMatcher:grey_nil()]; |
| 202 NSString* const kError = |
| 203 l10n_util::GetNSString(IDS_ERRORPAGES_HEADING_NOT_AVAILABLE); |
| 204 [[EarlGrey |
| 205 selectElementWithMatcher:chrome_test_util::staticHtmlViewContainingText( |
| 206 kError)] assertWithMatcher:grey_notNil()]; |
| 207 } |
| 208 |
| 209 // Open the settings submenu. Assumes that settings menu is visible. |
| 210 void OpenSettingsSubMenuUnsynced(int submenu) { |
| 211 id<GREYMatcher> settings_button_matcher = |
| 212 grey_text(l10n_util::GetNSString(submenu)); |
| 213 [[[EarlGrey selectElementWithMatcher:settings_button_matcher] |
| 214 usingSearchAction:grey_swipeSlowInDirection(kGREYDirectionUp) |
| 215 onElementWithMatcher:grey_accessibilityID(kSettingsCollectionViewId)] |
| 216 performAction:grey_tap()]; |
| 217 } |
| 218 |
| 219 // Open the settings menu. Wait for the settings menu to appear. |
| 220 void OpenSettingsMenuUnsynced() { |
| 221 id<GREYMatcher> tool_menu_matcher = |
| 222 grey_accessibilityID(kToolbarToolsMenuButtonIdentifier); |
| 223 WaitAndTap(tool_menu_matcher, @"Tool menu"); |
| 224 |
| 225 id<GREYMatcher> settings_button_matcher = |
| 226 grey_accessibilityID(kToolsMenuSettingsId); |
| 227 |
| 228 WaitAndTap(settings_button_matcher, @"Settings menu"); |
| 229 Wait(grey_accessibilityID(kSettingsCollectionViewId), @"Setting view"); |
| 230 } |
| 231 |
| 232 // Select the tab with title |title| using UI (tab strip on iPad, stack view on |
| 233 // iPhone). |
| 234 void SelectTabUsingUI(NSString* title) { |
| 235 if (IsCompact()) { |
| 236 WaitAndTap(chrome_test_util::buttonWithAccessibilityLabelId( |
| 237 IDS_IOS_TOOLBAR_SHOW_TABS), |
| 238 @"Tab switcher"); |
| 239 } |
| 240 WaitAndTap(grey_text(title), |
| 241 [NSString stringWithFormat:@"tab with title %@", title]); |
| 242 } |
| 243 } // namespace |
| 244 |
| 245 // Test for the TabUsageRecorder class. |
| 246 @interface TabUsageRecorderTestCase : ChromeTestCase |
| 247 @end |
| 248 |
| 249 @implementation TabUsageRecorderTestCase |
| 250 |
| 251 - (void)tearDown { |
| 252 [[GREYConfiguration sharedInstance] |
| 253 setValue:@(YES) |
| 254 forConfigKey:kGREYConfigKeySynchronizationEnabled]; |
| 255 [super tearDown]; |
| 256 } |
| 257 |
| 258 // Tests that the recorder actual recorde tab state. |
| 259 - (void)testTabSwitchRecorder { |
| 260 web::test::SetUpFileBasedHttpServer(); |
| 261 chrome_test_util::HistogramTester histogramTester; |
| 262 ResetTabUsageRecorder(); |
| 263 FailureBlock failureBlock = ^(NSString* error) { |
| 264 GREYFail(error); |
| 265 }; |
| 266 |
| 267 // Open two tabs with urls. |
| 268 OpenTwoTabs(); |
| 269 chrome_test_util::AssertMainTabCount(2); |
| 270 // Switch between the two tabs. Both are currently in memory. |
| 271 chrome_test_util::SelectTabAtIndexInCurrentMode(0); |
| 272 |
| 273 // Verify that one in-memory tab switch has been recorded. |
| 274 // histogramTester.ExpectTotalCount(kSelectedTabHistogramName, 1, |
| 275 // failureBlock); |
| 276 histogramTester.ExpectUniqueSample( |
| 277 kSelectedTabHistogramName, TabUsageRecorder::IN_MEMORY, 1, failureBlock); |
| 278 |
| 279 // Evict the tab. |
| 280 OpenNewIncognitoTabUsingUIAndEvictMainTabs(); |
| 281 GREYAssertTrue(chrome_test_util::IsIncognitoMode(), |
| 282 @"Failed to switch to incognito mode"); |
| 283 |
| 284 // Switch back to the normal tabs. Should be on tab one. |
| 285 SwitchToNormalMode(); |
| 286 [[EarlGrey selectElementWithMatcher:chrome_test_util::webViewContainingText( |
| 287 kURL1FirstWord)] |
| 288 assertWithMatcher:grey_notNil()]; |
| 289 |
| 290 histogramTester.ExpectTotalCount(kSelectedTabHistogramName, 2, failureBlock); |
| 291 histogramTester.ExpectBucketCount(kSelectedTabHistogramName, |
| 292 TabUsageRecorder::EVICTED, 1, failureBlock); |
| 293 } |
| 294 |
| 295 // Verifies the UMA metric for page loads before a tab eviction by loading |
| 296 // some tabs, forcing a tab eviction, then checking the histogram. |
| 297 - (void)testPageLoadCountBeforeEvictedTab { |
| 298 web::test::SetUpFileBasedHttpServer(); |
| 299 chrome_test_util::HistogramTester histogramTester; |
| 300 ResetTabUsageRecorder(); |
| 301 const GURL url1 = web::test::HttpServer::MakeUrl(kTestUrl1); |
| 302 FailureBlock failureBlock = ^(NSString* error) { |
| 303 GREYFail(error); |
| 304 }; |
| 305 |
| 306 // This test opens three tabs. |
| 307 const int numberOfTabs = 3; |
| 308 chrome_test_util::CloseAllTabsInCurrentMode(); |
| 309 // Open three tabs with http:// urls. |
| 310 for (NSUInteger i = 0; i < numberOfTabs; i++) { |
| 311 chrome_test_util::OpenNewTab(); |
| 312 [ChromeEarlGrey loadURL:url1]; |
| 313 [[EarlGrey selectElementWithMatcher:chrome_test_util::webViewContainingText( |
| 314 kURL1FirstWord)] |
| 315 assertWithMatcher:grey_notNil()]; |
| 316 } |
| 317 chrome_test_util::AssertMainTabCount(numberOfTabs); |
| 318 |
| 319 // Switch between the tabs. They are currently in memory. |
| 320 chrome_test_util::SelectTabAtIndexInCurrentMode(0); |
| 321 |
| 322 // Verify that no page-load count has been recorded. |
| 323 histogramTester.ExpectTotalCount(kPageLoadsBeforeEvictedTabSelected, 0, |
| 324 failureBlock); |
| 325 |
| 326 // Reload each tab. |
| 327 for (NSUInteger i = 0; i < numberOfTabs; i++) { |
| 328 chrome_test_util::SelectTabAtIndexInCurrentMode(i); |
| 329 // Clear the page so that we can check when pade reload is complete. |
| 330 __block bool finished = false; |
| 331 chrome_test_util::GetCurrentWebState()->ExecuteJavaScript( |
| 332 base::UTF8ToUTF16(kClearPageScript), |
| 333 base::BindBlock(^(const base::Value*) { |
| 334 finished = true; |
| 335 })); |
| 336 |
| 337 GREYAssert(testing::WaitUntilConditionOrTimeout(1.0, |
| 338 ^{ |
| 339 return finished; |
| 340 }), |
| 341 @"JavaScript to reload each tab did not finish"); |
| 342 [ChromeEarlGreyUI reload]; |
| 343 [[EarlGrey selectElementWithMatcher:chrome_test_util::webViewContainingText( |
| 344 kURL1FirstWord)] |
| 345 assertWithMatcher:grey_notNil()]; |
| 346 } |
| 347 |
| 348 // Evict the tab. Create a dummy tab so that switching back to normal mode |
| 349 // does not trigger a reload immediatly. |
| 350 chrome_test_util::OpenNewTab(); |
| 351 OpenNewIncognitoTabUsingUIAndEvictMainTabs(); |
| 352 chrome_test_util::AssertIncognitoTabCount(1); |
| 353 |
| 354 // Switch back to the normal tabs. Should be on tab one. |
| 355 SwitchToNormalMode(); |
| 356 chrome_test_util::SelectTabAtIndexInCurrentMode(0); |
| 357 [[EarlGrey selectElementWithMatcher:chrome_test_util::webViewContainingText( |
| 358 kURL1FirstWord)] |
| 359 assertWithMatcher:grey_notNil()]; |
| 360 |
| 361 // Verify that one page-load count has been recorded. It should contain two |
| 362 // page loads for each tab created. |
| 363 histogramTester.ExpectTotalCount(kPageLoadsBeforeEvictedTabSelected, 1, |
| 364 failureBlock); |
| 365 |
| 366 std::unique_ptr<base::HistogramSamples> samples = |
| 367 histogramTester.GetHistogramSamplesSinceCreation( |
| 368 kPageLoadsBeforeEvictedTabSelected); |
| 369 int sampleSum = samples ? samples->sum() : 0; |
| 370 GREYAssertEqual( |
| 371 sampleSum, numberOfTabs * 2, |
| 372 [NSString stringWithFormat:@"Expected page loads is %d, actual %d.", |
| 373 numberOfTabs * 2, sampleSum]); |
| 374 } |
| 375 |
| 376 // Tests that tabs reloaded on cold start are reported as |
| 377 // EVICTED_DUE_TO_COLD_START. |
| 378 - (void)testColdLaunchReloadCount { |
| 379 web::test::SetUpFileBasedHttpServer(); |
| 380 chrome_test_util::HistogramTester histogramTester; |
| 381 ResetTabUsageRecorder(); |
| 382 |
| 383 // Open two tabs with urls. |
| 384 OpenTwoTabs(); |
| 385 chrome_test_util::AssertMainTabCount(2); |
| 386 // Set the normal tabs as 'cold start' tabs. |
| 387 GREYAssertTrue(chrome_test_util::SetCurrentTabsToBeColdStartTabs(), |
| 388 @"Fail to state tabs as cold start tabs"); |
| 389 |
| 390 // Open two incognito tabs with urls, clearing normal tabs from memory. |
| 391 OpenNewIncognitoTabUsingUIAndEvictMainTabs(); |
| 392 OpenNewIncognitoTabUsingUIAndEvictMainTabs(); |
| 393 chrome_test_util::AssertIncognitoTabCount(2); |
| 394 |
| 395 // Switch back to the normal tabs. |
| 396 SwitchToNormalMode(); |
| 397 [[EarlGrey selectElementWithMatcher:chrome_test_util::webViewContainingText( |
| 398 kURL2FirstWord)] |
| 399 assertWithMatcher:grey_notNil()]; |
| 400 |
| 401 // Select the other one so it also reloads. |
| 402 chrome_test_util::SelectTabAtIndexInCurrentMode(0); |
| 403 [[EarlGrey selectElementWithMatcher:chrome_test_util::webViewContainingText( |
| 404 kURL1FirstWord)] |
| 405 assertWithMatcher:grey_notNil()]; |
| 406 |
| 407 FailureBlock failureBlock = ^(NSString* error) { |
| 408 GREYFail(error); |
| 409 }; |
| 410 // Make sure that one of the 2 tab loads (excluding the selected tab) is |
| 411 // counted as a cold start eviction. |
| 412 histogramTester.ExpectBucketCount(kSelectedTabHistogramName, |
| 413 TabUsageRecorder::EVICTED_DUE_TO_COLD_START, |
| 414 1, failureBlock); |
| 415 |
| 416 histogramTester.ExpectBucketCount( |
| 417 kSelectedTabHistogramName, TabUsageRecorder::IN_MEMORY, 0, failureBlock); |
| 418 // Re-select the same tab and make sure it is not counted again as evicted. |
| 419 chrome_test_util::SelectTabAtIndexInCurrentMode(1); |
| 420 chrome_test_util::SelectTabAtIndexInCurrentMode(0); |
| 421 |
| 422 [[EarlGrey selectElementWithMatcher:chrome_test_util::webViewContainingText( |
| 423 kURL1FirstWord)] |
| 424 assertWithMatcher:grey_notNil()]; |
| 425 histogramTester.ExpectBucketCount(kSelectedTabHistogramName, |
| 426 TabUsageRecorder::EVICTED_DUE_TO_COLD_START, |
| 427 1, failureBlock); |
| 428 |
| 429 histogramTester.ExpectBucketCount( |
| 430 kSelectedTabHistogramName, TabUsageRecorder::IN_MEMORY, 2, failureBlock); |
| 431 } |
| 432 |
| 433 // Tests that tabs reloads after backgrounding and eviction. |
| 434 - (void)testBackgroundingReloadCount { |
| 435 web::test::SetUpFileBasedHttpServer(); |
| 436 chrome_test_util::HistogramTester histogramTester; |
| 437 ResetTabUsageRecorder(); |
| 438 FailureBlock failureBlock = ^(NSString* error) { |
| 439 GREYFail(error); |
| 440 }; |
| 441 |
| 442 // Open two tabs with urls. |
| 443 OpenTwoTabs(); |
| 444 chrome_test_util::AssertMainTabCount(2); |
| 445 |
| 446 // Simulate going into the background. |
| 447 GREYAssertTrue(chrome_test_util::SimulateTabsBackgrounding(), |
| 448 @"Fail to simulate tab backgrounding."); |
| 449 |
| 450 // Open incognito and clear normal tabs from memory. |
| 451 OpenNewIncognitoTabUsingUIAndEvictMainTabs(); |
| 452 GREYAssertTrue(chrome_test_util::IsIncognitoMode(), |
| 453 @"Failed to switch to incognito mode"); |
| 454 histogramTester.ExpectTotalCount(kEvictedTabReloadTime, 0, failureBlock); |
| 455 |
| 456 // Switch back to the normal tabs. |
| 457 SwitchToNormalMode(); |
| 458 [[EarlGrey selectElementWithMatcher:chrome_test_util::webViewContainingText( |
| 459 kURL2FirstWord)] |
| 460 assertWithMatcher:grey_notNil()]; |
| 461 |
| 462 const GURL url1 = web::test::HttpServer::MakeUrl(kTestUrl1); |
| 463 const GURL url2 = web::test::HttpServer::MakeUrl(kTestUrl2); |
| 464 [[EarlGrey |
| 465 selectElementWithMatcher:chrome_test_util::omniboxText(url2.GetContent())] |
| 466 assertWithMatcher:grey_notNil()]; |
| 467 histogramTester.ExpectTotalCount(kEvictedTabReloadTime, 1, failureBlock); |
| 468 |
| 469 chrome_test_util::SelectTabAtIndexInCurrentMode(0); |
| 470 [[EarlGrey selectElementWithMatcher:chrome_test_util::webViewContainingText( |
| 471 kURL1FirstWord)] |
| 472 assertWithMatcher:grey_notNil()]; |
| 473 [[EarlGrey |
| 474 selectElementWithMatcher:chrome_test_util::omniboxText(url1.GetContent())] |
| 475 assertWithMatcher:grey_notNil()]; |
| 476 histogramTester.ExpectTotalCount(kEvictedTabReloadTime, 2, failureBlock); |
| 477 } |
| 478 |
| 479 // Verify correct recording of metrics when the reloading of an evicted tab |
| 480 // succeeds. |
| 481 - (void)testEvictedTabReloadSuccess { |
| 482 web::test::SetUpFileBasedHttpServer(); |
| 483 chrome_test_util::HistogramTester histogramTester; |
| 484 FailureBlock failureBlock = ^(NSString* error) { |
| 485 GREYFail(error); |
| 486 }; |
| 487 |
| 488 GURL URL = web::test::HttpServer::MakeUrl(kTestUrl1); |
| 489 NewMainTabWithURL(URL, kURL1FirstWord); |
| 490 OpenNewIncognitoTabUsingUIAndEvictMainTabs(); |
| 491 SwitchToNormalMode(); |
| 492 [[EarlGrey selectElementWithMatcher:chrome_test_util::webViewContainingText( |
| 493 kURL1FirstWord)] |
| 494 assertWithMatcher:grey_notNil()]; |
| 495 |
| 496 histogramTester.ExpectUniqueSample(kEvictedTabReloadSuccessRate, |
| 497 TabUsageRecorder::LOAD_SUCCESS, 1, |
| 498 failureBlock); |
| 499 histogramTester.ExpectUniqueSample(kDidUserWaitForEvictedTabReload, |
| 500 TabUsageRecorder::USER_WAITED, 1, |
| 501 failureBlock); |
| 502 histogramTester.ExpectTotalCount(kEvictedTabReloadTime, 1, failureBlock); |
| 503 } |
| 504 |
| 505 // Verify correct recording of metrics when the reloading of an evicted tab |
| 506 // fails. |
| 507 - (void)testEvictedTabReloadFailure { |
| 508 web::test::SetUpFileBasedHttpServer(); |
| 509 chrome_test_util::HistogramTester histogramTester; |
| 510 FailureBlock failureBlock = ^(NSString* error) { |
| 511 GREYFail(error); |
| 512 }; |
| 513 |
| 514 // This URL is purposely invalid so it triggers a navigation error. |
| 515 GURL invalidURL(kTestUrl1); |
| 516 |
| 517 chrome_test_util::OpenNewTab(); |
| 518 [ChromeEarlGrey loadURL:invalidURL]; |
| 519 CheckErrorPageIsVisible(); |
| 520 OpenNewIncognitoTabUsingUIAndEvictMainTabs(); |
| 521 |
| 522 SwitchToNormalMode(); |
| 523 CheckErrorPageIsVisible(); |
| 524 |
| 525 histogramTester.ExpectUniqueSample(kEvictedTabReloadSuccessRate, |
| 526 TabUsageRecorder::LOAD_FAILURE, 1, |
| 527 failureBlock); |
| 528 histogramTester.ExpectUniqueSample(kDidUserWaitForEvictedTabReload, |
| 529 TabUsageRecorder::USER_WAITED, 1, |
| 530 failureBlock); |
| 531 histogramTester.ExpectTotalCount(kEvictedTabReloadTime, 0, failureBlock); |
| 532 } |
| 533 |
| 534 // Test that USER_DID_NOT_WAIT is reported if the user does not wait for the |
| 535 // reload to be complete after eviction. |
| 536 - (void)testEvictedTabSlowReload { |
| 537 std::map<GURL, std::string> responses; |
| 538 const GURL slowURL = web::test::HttpServer::MakeUrl("http://slow"); |
| 539 responses[slowURL] = "Slow Page"; |
| 540 |
| 541 web::test::SetUpHttpServer(base::MakeUnique<web::DelayedResponseProvider>( |
| 542 base::MakeUnique<HtmlResponseProvider>(responses), kSlowURLDelay)); |
| 543 |
| 544 chrome_test_util::HistogramTester histogramTester; |
| 545 FailureBlock failureBlock = ^(NSString* error) { |
| 546 GREYFail(error); |
| 547 }; |
| 548 |
| 549 // A blank tab needed to switch to it after reloading. |
| 550 chrome_test_util::OpenNewTab(); |
| 551 chrome_test_util::OpenNewTab(); |
| 552 chrome_test_util::LoadUrl(slowURL); |
| 553 OpenNewIncognitoTabUsingUIAndEvictMainTabs(); |
| 554 |
| 555 web::test::SetUpHttpServer(base::MakeUnique<web::DelayedResponseProvider>( |
| 556 base::MakeUnique<HtmlResponseProvider>(responses), kSlowURLDelay)); |
| 557 |
| 558 SwitchToNormalMode(); |
| 559 |
| 560 GREYAssert( |
| 561 [[GREYCondition conditionWithName:@"Wait for tab to restart loading." |
| 562 block:^BOOL() { |
| 563 return chrome_test_util::IsLoading(); |
| 564 }] waitWithTimeout:kWaitElementTimeout], |
| 565 @"Tab did not start loading."); |
| 566 |
| 567 // This method is not synced on EarlGrey. |
| 568 chrome_test_util::SelectTabAtIndexInCurrentMode(0); |
| 569 |
| 570 // Do not test the kEvictedTabReloadSuccessRate, as the timing of the two |
| 571 // page loads cannot be guaranteed. The test would be flaky. |
| 572 histogramTester.ExpectBucketCount(kDidUserWaitForEvictedTabReload, |
| 573 TabUsageRecorder::USER_DID_NOT_WAIT, 1, |
| 574 failureBlock); |
| 575 } |
| 576 |
| 577 // Test that the USER_DID_NOT_WAIT metric is logged when the user opens an NTP |
| 578 // while the evicted tab is still reloading. |
| 579 - (void)testEvictedTabReloadSwitchToNTP { |
| 580 std::map<GURL, std::string> responses; |
| 581 const GURL slowURL = web::test::HttpServer::MakeUrl("http://slow"); |
| 582 responses[slowURL] = "Slow Page"; |
| 583 |
| 584 web::test::SetUpHttpServer(base::MakeUnique<HtmlResponseProvider>(responses)); |
| 585 |
| 586 chrome_test_util::HistogramTester histogramTester; |
| 587 FailureBlock failureBlock = ^(NSString* error) { |
| 588 GREYFail(error); |
| 589 }; |
| 590 |
| 591 NewMainTabWithURL(slowURL, "Slow"); |
| 592 |
| 593 OpenNewIncognitoTabUsingUIAndEvictMainTabs(); |
| 594 web::test::SetUpHttpServer(base::MakeUnique<web::DelayedResponseProvider>( |
| 595 base::MakeUnique<HtmlResponseProvider>(responses), kSlowURLDelay)); |
| 596 |
| 597 SwitchToNormalMode(); |
| 598 |
| 599 // TODO(crbug.com/640977): EarlGrey synchronize on some animations when a |
| 600 // page is loading. Need to handle synchronization manually for this test. |
| 601 [[GREYConfiguration sharedInstance] |
| 602 setValue:@(NO) |
| 603 forConfigKey:kGREYConfigKeySynchronizationEnabled]; |
| 604 OpenNewMainTabUsingUIUnsynced(); |
| 605 [[GREYConfiguration sharedInstance] |
| 606 setValue:@(YES) |
| 607 forConfigKey:kGREYConfigKeySynchronizationEnabled]; |
| 608 histogramTester.ExpectBucketCount(kDidUserWaitForEvictedTabReload, |
| 609 TabUsageRecorder::USER_DID_NOT_WAIT, 1, |
| 610 failureBlock); |
| 611 } |
| 612 |
| 613 // Test that the USER_DID_NOT_WAIT metric is not logged when the user opens |
| 614 // and closes the settings UI while the evicted tab is still reloading. |
| 615 - (void)testEvictedTabReloadSettingsAndBack { |
| 616 std::map<GURL, std::string> responses; |
| 617 const GURL slowURL = web::test::HttpServer::MakeUrl("http://slow"); |
| 618 responses[slowURL] = "Slow Page"; |
| 619 |
| 620 web::test::SetUpHttpServer(base::MakeUnique<web::DelayedResponseProvider>( |
| 621 base::MakeUnique<HtmlResponseProvider>(responses), kSlowURLDelay)); |
| 622 |
| 623 chrome_test_util::HistogramTester histogramTester; |
| 624 FailureBlock failureBlock = ^(NSString* error) { |
| 625 GREYFail(error); |
| 626 }; |
| 627 |
| 628 NewMainTabWithURL(slowURL, responses[slowURL]); |
| 629 |
| 630 OpenNewIncognitoTabUsingUIAndEvictMainTabs(); |
| 631 |
| 632 SwitchToNormalMode(); |
| 633 // TODO(crbug.com/640977): EarlGrey synchronize on some animations when a |
| 634 // page is loading. Need to handle synchronization manually for this test. |
| 635 [[GREYConfiguration sharedInstance] |
| 636 setValue:@(NO) |
| 637 forConfigKey:kGREYConfigKeySynchronizationEnabled]; |
| 638 OpenSettingsMenuUnsynced(); |
| 639 OpenSettingsSubMenuUnsynced(IDS_OPTIONS_ADVANCED_SECTION_TITLE_PRIVACY); |
| 640 Wait(grey_accessibilityID(kPrivacyCollectionViewId), |
| 641 @"Privacy settings view."); |
| 642 |
| 643 WaitAndTap(grey_accessibilityLabel( |
| 644 l10n_util::GetNSString(IDS_IOS_NAVIGATION_BAR_DONE_BUTTON)), |
| 645 @"Close settings"); |
| 646 [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; |
| 647 [[EarlGrey selectElementWithMatcher:chrome_test_util::webViewContainingText( |
| 648 responses[slowURL])] |
| 649 assertWithMatcher:grey_notNil()]; |
| 650 |
| 651 [[GREYConfiguration sharedInstance] |
| 652 setValue:@(YES) |
| 653 forConfigKey:kGREYConfigKeySynchronizationEnabled]; |
| 654 |
| 655 histogramTester.ExpectBucketCount(kDidUserWaitForEvictedTabReload, |
| 656 TabUsageRecorder::USER_DID_NOT_WAIT, 0, |
| 657 failureBlock); |
| 658 histogramTester.ExpectBucketCount(kDidUserWaitForEvictedTabReload, |
| 659 TabUsageRecorder::USER_WAITED, 1, |
| 660 failureBlock); |
| 661 } |
| 662 |
| 663 // Tests that leaving Chrome while an evicted tab is reloading triggers the |
| 664 // recording of the USER_LEFT_CHROME metric. |
| 665 - (void)testEvictedTabReloadBackgrounded { |
| 666 std::map<GURL, std::string> responses; |
| 667 const GURL slowURL = web::test::HttpServer::MakeUrl("http://slow"); |
| 668 responses[slowURL] = "Slow Page"; |
| 669 |
| 670 web::test::SetUpHttpServer(base::MakeUnique<HtmlResponseProvider>(responses)); |
| 671 |
| 672 chrome_test_util::HistogramTester histogramTester; |
| 673 chrome_test_util::OpenNewTab(); |
| 674 chrome_test_util::LoadUrl(slowURL); |
| 675 |
| 676 OpenNewIncognitoTabUsingUIAndEvictMainTabs(); |
| 677 |
| 678 web::test::SetUpHttpServer(base::MakeUnique<web::DelayedResponseProvider>( |
| 679 base::MakeUnique<HtmlResponseProvider>(responses), kSlowURLDelay)); |
| 680 SwitchToNormalMode(); |
| 681 |
| 682 // TODO(crbug.com/640977): EarlGrey synchronize on some animations when a |
| 683 // page is loading. Need to handle synchronization manually for this test. |
| 684 [[GREYConfiguration sharedInstance] |
| 685 setValue:@(NO) |
| 686 forConfigKey:kGREYConfigKeySynchronizationEnabled]; |
| 687 id<GREYMatcher> toolMenuMatcher = |
| 688 grey_accessibilityID(kToolbarToolsMenuButtonIdentifier); |
| 689 Wait(toolMenuMatcher, @"Tool Menu"); |
| 690 |
| 691 GREYAssertTrue(chrome_test_util::SimulateTabsBackgrounding(), |
| 692 @"Failed to simulate tab backgrounding."); |
| 693 [[GREYConfiguration sharedInstance] |
| 694 setValue:@(YES) |
| 695 forConfigKey:kGREYConfigKeySynchronizationEnabled]; |
| 696 |
| 697 FailureBlock failureBlock = ^(NSString* error) { |
| 698 GREYFail(error); |
| 699 }; |
| 700 histogramTester.ExpectBucketCount(kDidUserWaitForEvictedTabReload, |
| 701 TabUsageRecorder::USER_LEFT_CHROME, 1, |
| 702 failureBlock); |
| 703 } |
| 704 |
| 705 // Tests that backgrounding a tab that was not evicted while it is loading does |
| 706 // not record the USER_LEFT_CHROME metric. |
| 707 - (void)testLiveTabReloadBackgrounded { |
| 708 std::map<GURL, std::string> responses; |
| 709 const GURL slowURL = web::test::HttpServer::MakeUrl("http://slow"); |
| 710 responses[slowURL] = "Slow Page"; |
| 711 |
| 712 web::test::SetUpHttpServer(base::MakeUnique<web::DelayedResponseProvider>( |
| 713 base::MakeUnique<HtmlResponseProvider>(responses), kSlowURLDelay)); |
| 714 |
| 715 chrome_test_util::HistogramTester histogramTester; |
| 716 |
| 717 // We need two tabs to be able to switch. |
| 718 chrome_test_util::OpenNewTab(); |
| 719 [[GREYConfiguration sharedInstance] |
| 720 setValue:@(NO) |
| 721 forConfigKey:kGREYConfigKeySynchronizationEnabled]; |
| 722 chrome_test_util::LoadUrl(slowURL); |
| 723 |
| 724 // Ensure loading starts but is not finished. |
| 725 base::test::ios::SpinRunLoopWithMaxDelay(base::TimeDelta::FromSeconds(1)); |
| 726 chrome_test_util::SelectTabAtIndexInCurrentMode(0); |
| 727 [[GREYConfiguration sharedInstance] |
| 728 setValue:@(YES) |
| 729 forConfigKey:kGREYConfigKeySynchronizationEnabled]; |
| 730 |
| 731 FailureBlock failureBlock = ^(NSString* error) { |
| 732 GREYFail(error); |
| 733 }; |
| 734 histogramTester.ExpectBucketCount(kDidUserWaitForEvictedTabReload, |
| 735 TabUsageRecorder::USER_LEFT_CHROME, 0, |
| 736 failureBlock); |
| 737 } |
| 738 |
| 739 // Tests that redirecting pages are not reloaded after eviction. |
| 740 - (void)testPageRedirect { |
| 741 GURL redirectURL = web::test::HttpServer::MakeUrl( |
| 742 "http://ios/testing/data/http_server_files/redirect_refresh.html"); |
| 743 GURL destinationURL = web::test::HttpServer::MakeUrl( |
| 744 "http://ios/testing/data/http_server_files/destination.html"); |
| 745 web::test::SetUpFileBasedHttpServer(); |
| 746 chrome_test_util::HistogramTester histogramTester; |
| 747 ResetTabUsageRecorder(); |
| 748 |
| 749 NewMainTabWithURL(redirectURL, "arrived"); |
| 750 |
| 751 [[EarlGrey selectElementWithMatcher:chrome_test_util::omniboxText( |
| 752 destinationURL.GetContent())] |
| 753 assertWithMatcher:grey_notNil()]; |
| 754 |
| 755 NSUInteger tabIndex = chrome_test_util::GetMainTabCount() - 1; |
| 756 chrome_test_util::OpenNewTab(); |
| 757 OpenNewIncognitoTabUsingUIAndEvictMainTabs(); |
| 758 SwitchToNormalMode(); |
| 759 chrome_test_util::SelectTabAtIndexInCurrentMode(tabIndex); |
| 760 [[EarlGrey selectElementWithMatcher:chrome_test_util::webViewContainingText( |
| 761 "arrived")] |
| 762 assertWithMatcher:grey_notNil()]; |
| 763 |
| 764 FailureBlock failureBlock = ^(NSString* error) { |
| 765 GREYFail(error); |
| 766 }; |
| 767 // Verify that one page-load count has been recorded. It should contain a |
| 768 // sum of 1 - one sample with 1 page load. |
| 769 histogramTester.ExpectTotalCount(kPageLoadsBeforeEvictedTabSelected, 1, |
| 770 failureBlock); |
| 771 |
| 772 std::unique_ptr<base::HistogramSamples> samples = |
| 773 histogramTester.GetHistogramSamplesSinceCreation( |
| 774 kPageLoadsBeforeEvictedTabSelected); |
| 775 int sampleSum = samples->sum(); |
| 776 GREYAssertEqual( |
| 777 sampleSum, 1, |
| 778 [NSString stringWithFormat:@"Expected page loads is %d, actual is %d.", 1, |
| 779 sampleSum]); |
| 780 } |
| 781 |
| 782 // Tests that navigations are correctly reported in |
| 783 // Tab.PageLoadsSinceLastSwitchToEvictedTab histogram. |
| 784 - (void)testLinkClickNavigation { |
| 785 // Create map of canned responses and set up the test HTML server. |
| 786 std::map<GURL, std::string> responses; |
| 787 const GURL initialURL = |
| 788 web::test::HttpServer::MakeUrl("http://scenarioTestLinkClickNavigation"); |
| 789 const GURL destinationURL = |
| 790 web::test::HttpServer::MakeUrl("http://destination"); |
| 791 responses[initialURL] = base::StringPrintf( |
| 792 "<body><a style='margin-left:50px' href='%s' id='link'>link</a></body>", |
| 793 destinationURL.spec().c_str()); |
| 794 responses[destinationURL] = "Whee!"; |
| 795 web::test::SetUpHttpServer(base::MakeUnique<HtmlResponseProvider>(responses)); |
| 796 chrome_test_util::HistogramTester histogramTester; |
| 797 ResetTabUsageRecorder(); |
| 798 |
| 799 // Open a tab with a link to click. |
| 800 NewMainTabWithURL(initialURL, "link"); |
| 801 // Click the link. |
| 802 chrome_test_util::TapWebViewElementWithId("link"); |
| 803 |
| 804 [[EarlGrey |
| 805 selectElementWithMatcher:chrome_test_util::webViewContainingText("Whee")] |
| 806 assertWithMatcher:grey_notNil()]; |
| 807 |
| 808 NSUInteger tabIndex = chrome_test_util::GetMainTabCount() - 1; |
| 809 chrome_test_util::OpenNewTab(); |
| 810 OpenNewIncognitoTabUsingUIAndEvictMainTabs(); |
| 811 SwitchToNormalMode(); |
| 812 chrome_test_util::SelectTabAtIndexInCurrentMode(tabIndex); |
| 813 [[EarlGrey |
| 814 selectElementWithMatcher:chrome_test_util::webViewContainingText("Whee")] |
| 815 assertWithMatcher:grey_notNil()]; |
| 816 |
| 817 // Verify that the page-load count has been recorded. It should contain a |
| 818 // sum of 2 - one sample with 2 page loads. |
| 819 std::unique_ptr<base::HistogramSamples> samples = |
| 820 histogramTester.GetHistogramSamplesSinceCreation( |
| 821 kPageLoadsBeforeEvictedTabSelected); |
| 822 int sampleSum = samples->sum(); |
| 823 GREYAssertEqual( |
| 824 sampleSum, 2, |
| 825 [NSString stringWithFormat:@"Expected page loads is %d, actual %d.", 2, |
| 826 sampleSum]); |
| 827 |
| 828 FailureBlock failureBlock = ^(NSString* error) { |
| 829 GREYFail(error); |
| 830 }; |
| 831 // Verify that only one evicted tab was selected. This is to make sure the |
| 832 // link click did not generate an evicted-tab-reload count. |
| 833 histogramTester.ExpectBucketCount(kSelectedTabHistogramName, |
| 834 TabUsageRecorder::EVICTED, 1, failureBlock); |
| 835 } |
| 836 |
| 837 // Tests that opening links in a new tab will not evict the source tab. |
| 838 - (void)testOpenLinkInNewTab { |
| 839 // Create map of canned responses and set up the test HTML server. |
| 840 std::map<GURL, std::string> responses; |
| 841 const GURL initialURL = |
| 842 web::test::HttpServer::MakeUrl("http://scenarioTestOpenLinkInNewTab"); |
| 843 const GURL destinationURL = |
| 844 web::test::HttpServer::MakeUrl("http://destination"); |
| 845 // Make the link that cover the whole page so that long pressing the web view |
| 846 // will trigger the link context menu. |
| 847 responses[initialURL] = base::StringPrintf( |
| 848 "<body style='width:auto; height:auto;'><a href='%s' " |
| 849 "id='link'><div style='width:100%%; " |
| 850 "height:100%%;'>link</div></a></body>", |
| 851 destinationURL.spec().c_str()); |
| 852 responses[destinationURL] = "Whee!"; |
| 853 web::test::SetUpHttpServer(base::MakeUnique<HtmlResponseProvider>(responses)); |
| 854 chrome_test_util::HistogramTester histogramTester; |
| 855 ResetTabUsageRecorder(); |
| 856 |
| 857 // Open a tab with a link to click. |
| 858 NewMainTabWithURL(initialURL, "link"); |
| 859 |
| 860 int numberOfTabs = chrome_test_util::GetMainTabCount(); |
| 861 [[EarlGrey |
| 862 selectElementWithMatcher:chrome_test_util::webViewContainingText("link")] |
| 863 performAction:grey_longPress()]; |
| 864 |
| 865 [[EarlGrey |
| 866 selectElementWithMatcher:grey_text(l10n_util::GetNSString( |
| 867 IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB))] |
| 868 performAction:grey_tap()]; |
| 869 chrome_test_util::AssertMainTabCount(numberOfTabs + 1); |
| 870 |
| 871 SelectTabUsingUI(base::SysUTF8ToNSString(destinationURL.GetContent())); |
| 872 |
| 873 [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; |
| 874 [[EarlGrey |
| 875 selectElementWithMatcher:chrome_test_util::webViewContainingText("Whee")] |
| 876 assertWithMatcher:grey_notNil()]; |
| 877 |
| 878 FailureBlock failureBlock = ^(NSString* error) { |
| 879 GREYFail(error); |
| 880 }; |
| 881 histogramTester.ExpectTotalCount(kSelectedTabHistogramName, 1, failureBlock); |
| 882 histogramTester.ExpectBucketCount( |
| 883 kSelectedTabHistogramName, TabUsageRecorder::IN_MEMORY, 1, failureBlock); |
| 884 } |
| 885 |
| 886 // Tests that opening tabs from external app will not cause tab eviction. |
| 887 - (void)testOpenFromApp { |
| 888 web::test::SetUpFileBasedHttpServer(); |
| 889 chrome_test_util::HistogramTester histogramTester; |
| 890 ResetTabUsageRecorder(); |
| 891 |
| 892 chrome_test_util::OpenNewTab(); |
| 893 GURL url(kTestUrl1); |
| 894 |
| 895 chrome_test_util::OpenChromeFromExternalApp(url); |
| 896 |
| 897 // Add a delay to ensure the tab has fully opened. Because the check below |
| 898 // is for zero metrics recorded, it adds no flakiness. However, this pause |
| 899 // makes the step more likely to fail in failure cases. I.e. without it, this |
| 900 // test would sometimes pass even when it should fail. |
| 901 base::test::ios::SpinRunLoopWithMaxDelay( |
| 902 base::TimeDelta::FromMilliseconds(500)); |
| 903 |
| 904 FailureBlock failureBlock = ^(NSString* error) { |
| 905 GREYFail(error); |
| 906 }; |
| 907 // Verify that zero Tab.StatusWhenSwitchedBackToForeground metrics were |
| 908 // recorded. Tabs created at the time the user switches to them should not |
| 909 // be counted in this metric. |
| 910 histogramTester.ExpectTotalCount(kSelectedTabHistogramName, 0, failureBlock); |
| 911 } |
| 912 |
| 913 // Verify that evicted tabs that are deleted are removed from the evicted tabs |
| 914 // map. |
| 915 - (void)testTabDeletion { |
| 916 web::test::SetUpFileBasedHttpServer(); |
| 917 chrome_test_util::HistogramTester histogramTester; |
| 918 ResetTabUsageRecorder(); |
| 919 // Add an autorelease pool to delete the closed tabs before the end of the |
| 920 // test. |
| 921 @autoreleasepool { |
| 922 // Open two tabs with urls. |
| 923 OpenTwoTabs(); |
| 924 // Set the normal tabs as 'cold start' tabs. |
| 925 chrome_test_util::SetCurrentTabsToBeColdStartTabs(); |
| 926 // One more tab. |
| 927 const GURL url1 = web::test::HttpServer::MakeUrl(kTestUrl1); |
| 928 NewMainTabWithURL(url1, kURL1FirstWord); |
| 929 |
| 930 GREYAssertEqual(chrome_test_util::GetMainTabCount(), 3, |
| 931 @"Check number of normal tabs"); |
| 932 // The cold start tab which was not active will still be evicted. |
| 933 GREYAssertEqual(chrome_test_util::GetEvictedMainTabCount(), 1, |
| 934 @"Check number of evicted tabs"); |
| 935 |
| 936 // Close two of the three open tabs without selecting them first. |
| 937 // This should delete the tab objects, even though they're still being |
| 938 // tracked |
| 939 // by the tab usage recorder in its |evicted_tabs_| map. |
| 940 CloseTabAtIndexAndSync(1); |
| 941 |
| 942 GREYAssertEqual(chrome_test_util::GetMainTabCount(), 2, |
| 943 @"Check number of normal tabs"); |
| 944 CloseTabAtIndexAndSync(0); |
| 945 GREYAssertEqual(chrome_test_util::GetMainTabCount(), 1, |
| 946 @"Check number of normal tabs"); |
| 947 [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; |
| 948 } |
| 949 // The deleted tabs are purged during foregrounding and backgrounding. |
| 950 chrome_test_util::SimulateTabsBackgrounding(); |
| 951 // Make sure |evicted_tabs_| purged the deleted tabs. |
| 952 int evicted = chrome_test_util::GetEvictedMainTabCount(); |
| 953 GREYAssertEqual(evicted, 0, @"Check number of evicted tabs"); |
| 954 } |
| 955 |
| 956 @end |
OLD | NEW |