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 <XCTest/XCTest.h> |
| 6 |
| 7 #include "base/ios/block_types.h" |
| 8 #include "base/mac/foundation_util.h" |
| 9 #include "base/strings/sys_string_conversions.h" |
| 10 #import "base/test/ios/wait_util.h" |
| 11 #include "ios/chrome/browser/browser_state/chrome_browser_state.h" |
| 12 #include "ios/chrome/browser/pref_names.h" |
| 13 #import "ios/chrome/browser/tabs/tab.h" |
| 14 #import "ios/chrome/browser/tabs/tab_model.h" |
| 15 #import "ios/chrome/browser/ui/browser_view_controller.h" |
| 16 #import "ios/chrome/browser/ui/stack_view/card_view.h" |
| 17 #import "ios/chrome/browser/ui/stack_view/stack_view_controller.h" |
| 18 #import "ios/chrome/browser/ui/stack_view/stack_view_controller_private.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 #import "ios/chrome/test/app/stack_view_test_util.h" |
| 22 #import "ios/chrome/test/app/tab_test_util.h" |
| 23 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" |
| 24 #import "ios/chrome/test/earl_grey/chrome_matchers.h" |
| 25 #import "ios/chrome/test/earl_grey/chrome_test_case.h" |
| 26 #include "ios/testing/earl_grey/disabled_test_macros.h" |
| 27 |
| 28 namespace { |
| 29 // Returns a GREYMatcher that matches |view|. |
| 30 // TODO(crbug.com/642619): Evaluate whether this should be shared code. |
| 31 id<GREYMatcher> viewMatchingView(UIView* view) { |
| 32 MatchesBlock matches = ^BOOL(UIView* viewToMatch) { |
| 33 return viewToMatch == view; |
| 34 }; |
| 35 DescribeToBlock describe = ^void(id<GREYDescription> description) { |
| 36 NSString* matcherDescription = |
| 37 [NSString stringWithFormat:@"View matching %@", view]; |
| 38 [description appendText:matcherDescription]; |
| 39 }; |
| 40 return [[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches |
| 41 descriptionBlock:describe]; |
| 42 } |
| 43 |
| 44 // Returns a matcher for the StackViewController's view. |
| 45 id<GREYMatcher> stackView() { |
| 46 return viewMatchingView([chrome_test_util::GetStackViewController() view]); |
| 47 } |
| 48 |
| 49 // Waits for the Stack View to be visible/hidden. |
| 50 void CheckForStackViewVisibility(bool visible) { |
| 51 id<GREYMatcher> visibilityMatcher = |
| 52 grey_allOf(visible ? grey_sufficientlyVisible() : grey_notVisible(), |
| 53 visible ? grey_notNil() : grey_nil(), nil); |
| 54 [[EarlGrey selectElementWithMatcher:stackView()] |
| 55 assertWithMatcher:visibilityMatcher]; |
| 56 } |
| 57 |
| 58 // Opens the StackViewController. |
| 59 void OpenStackView() { |
| 60 if (chrome_test_util::IsTabSwitcherActive()) |
| 61 return; |
| 62 // Tap on the toolbar's tab switcher button. |
| 63 id<GREYMatcher> stackButtonMatcher = |
| 64 grey_allOf(grey_accessibilityID(kToolbarStackButtonIdentifier), |
| 65 grey_sufficientlyVisible(), nil); |
| 66 [[EarlGrey selectElementWithMatcher:stackButtonMatcher] |
| 67 performAction:grey_tap()]; |
| 68 // Verify that a StackViewController was presented. |
| 69 CheckForStackViewVisibility(true); |
| 70 } |
| 71 |
| 72 // Shows either the normal or incognito deck. |
| 73 enum class DeckType : bool { NORMAL, INCOGNITO }; |
| 74 void ShowDeckWithType(DeckType type) { |
| 75 OpenStackView(); |
| 76 StackViewController* stackViewController = |
| 77 chrome_test_util::GetStackViewController(); |
| 78 UIView* activeDisplayView = stackViewController.activeCardSet.displayView; |
| 79 // The inactive deck region is in scroll view coordinates, but the tap |
| 80 // recognizer is installed on the active card set's display view. |
| 81 CGRect inactiveDeckRegion = |
| 82 [activeDisplayView convertRect:[stackViewController inactiveDeckRegion] |
| 83 fromView:stackViewController.scrollView]; |
| 84 bool showIncognito = type == DeckType::INCOGNITO; |
| 85 if (showIncognito) { |
| 86 GREYAssert(!CGRectIsEmpty(inactiveDeckRegion), |
| 87 @"Cannot show Incognito deck if no Incognito tabs are open"); |
| 88 } |
| 89 if (showIncognito != [stackViewController isCurrentSetIncognito]) { |
| 90 CGPoint tapPoint = CGPointMake(CGRectGetMidX(inactiveDeckRegion), |
| 91 CGRectGetMidY(inactiveDeckRegion)); |
| 92 [[EarlGrey selectElementWithMatcher:viewMatchingView(activeDisplayView)] |
| 93 performAction:grey_tapAtPoint(tapPoint)]; |
| 94 } |
| 95 } |
| 96 |
| 97 // Opens a new tab using the stack view button. |
| 98 void OpenNewTabUsingStackView() { |
| 99 // Open the stack view, tap the New Tab button, and wait for the animation to |
| 100 // finish. |
| 101 ShowDeckWithType(DeckType::NORMAL); |
| 102 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"New Tab")] |
| 103 performAction:grey_tap()]; |
| 104 CheckForStackViewVisibility(false); |
| 105 } |
| 106 |
| 107 // Opens the tools menu from the stack view. |
| 108 void OpenToolsMenu() { |
| 109 OpenStackView(); |
| 110 [[EarlGrey selectElementWithMatcher:chrome_test_util::toolsMenuButton()] |
| 111 performAction:grey_tap()]; |
| 112 } |
| 113 |
| 114 // Opens a new Incognito Tab using the stack view button. |
| 115 void OpenNewIncognitoTabUsingStackView() { |
| 116 OpenToolsMenu(); |
| 117 NSString* newIncognitoTabID = kToolsMenuNewIncognitoTabId; |
| 118 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(newIncognitoTabID)] |
| 119 performAction:grey_tap()]; |
| 120 CheckForStackViewVisibility(false); |
| 121 } |
| 122 |
| 123 // Taps the CardView associated with |tab|. |
| 124 void SelectTabUsingStackView(Tab* tab) { |
| 125 DCHECK(tab); |
| 126 // Present the StackViewController. |
| 127 OpenStackView(); |
| 128 // Get the StackCard associated with |tab|. |
| 129 StackViewController* stackViewController = |
| 130 chrome_test_util::GetStackViewController(); |
| 131 StackCard* nextCard = [[stackViewController activeCardSet] cardForTab:tab]; |
| 132 UIView* card_title_label = static_cast<UIView*>([[nextCard view] titleLabel]); |
| 133 [[EarlGrey selectElementWithMatcher:viewMatchingView(card_title_label)] |
| 134 performAction:grey_tap()]; |
| 135 // Wait for the StackViewController to be dismissed. |
| 136 CheckForStackViewVisibility(false); |
| 137 // Checks that the next Tab has been selected. |
| 138 GREYAssertEqual(tab, chrome_test_util::GetCurrentTab(), |
| 139 @"The next Tab was not selected"); |
| 140 } |
| 141 } |
| 142 |
| 143 // Tests for interacting with the StackViewController. |
| 144 @interface StackViewTestCase : ChromeTestCase |
| 145 @end |
| 146 |
| 147 @implementation StackViewTestCase |
| 148 |
| 149 // Switches between three Tabs via the stack view. |
| 150 - (void)testSwitchTabs { |
| 151 // The StackViewController is only used on iPhones. |
| 152 if (IsIPadIdiom()) |
| 153 EARL_GREY_TEST_SKIPPED(@"Stack view is not used on iPads."); |
| 154 // Open two additional Tabs. |
| 155 const NSUInteger kAdditionalTabCount = 2; |
| 156 for (NSUInteger i = 0; i < kAdditionalTabCount; ++i) |
| 157 OpenNewTabUsingStackView(); |
| 158 // Select each additional Tab using the stack view UI. |
| 159 for (NSUInteger i = 0; i < kAdditionalTabCount + 1; ++i) |
| 160 SelectTabUsingStackView(chrome_test_util::GetNextTab()); |
| 161 } |
| 162 |
| 163 // Tests closing a tab in the stack view. |
| 164 - (void)testCloseTab { |
| 165 // The StackViewController is only used on iPhones. |
| 166 if (IsIPadIdiom()) |
| 167 EARL_GREY_TEST_SKIPPED(@"Stack view is not used on iPads."); |
| 168 // Open the stack view and tap the close button on the current CardView. |
| 169 OpenStackView(); |
| 170 StackViewController* stackViewController = |
| 171 chrome_test_util::GetStackViewController(); |
| 172 Tab* currentTab = chrome_test_util::GetCurrentTab(); |
| 173 StackCard* card = [[stackViewController activeCardSet] cardForTab:currentTab]; |
| 174 CardView* cardView = card.view; |
| 175 NSString* identifier = card.view.closeButtonId; |
| 176 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(identifier)] |
| 177 performAction:grey_tap()]; |
| 178 // Verify that the CardView and its associated Tab were removed. |
| 179 [[EarlGrey selectElementWithMatcher:viewMatchingView(cardView)] |
| 180 assertWithMatcher:grey_notVisible()]; |
| 181 GREYAssertEqual(chrome_test_util::GetMainTabCount(), 0, |
| 182 @"All Tabs should be closed."); |
| 183 } |
| 184 |
| 185 // Tests closing all Tabs in the stack view. |
| 186 - (void)testCloseAllTabs { |
| 187 // The StackViewController is only used on iPhones. |
| 188 if (IsIPadIdiom()) |
| 189 EARL_GREY_TEST_SKIPPED(@"Stack view is not used on iPads."); |
| 190 // Open an incognito Tab. |
| 191 OpenNewIncognitoTabUsingStackView(); |
| 192 GREYAssertEqual(chrome_test_util::GetIncognitoTabCount(), 1, |
| 193 @"Incognito Tab was not opened."); |
| 194 // Open two additional Tabs. |
| 195 const NSUInteger kAdditionalTabCount = 2; |
| 196 for (NSUInteger i = 0; i < kAdditionalTabCount; ++i) |
| 197 OpenNewTabUsingStackView(); |
| 198 GREYAssertEqual(chrome_test_util::GetMainTabCount(), kAdditionalTabCount + 1, |
| 199 @"Additional Tabs were not opened."); |
| 200 // Record all created CardViews. |
| 201 OpenStackView(); |
| 202 StackViewController* stackViewController = |
| 203 chrome_test_util::GetStackViewController(); |
| 204 NSMutableArray* cardViews = [NSMutableArray array]; |
| 205 for (StackCard* card in [stackViewController activeCardSet].cards) { |
| 206 if (card.viewIsLive) |
| 207 [cardViews addObject:card.view]; |
| 208 } |
| 209 for (StackCard* card in [stackViewController inactiveCardSet].cards) { |
| 210 if (card.viewIsLive) |
| 211 [cardViews addObject:card.view]; |
| 212 } |
| 213 // Open the tools menu and select "Close all tabs". |
| 214 OpenToolsMenu(); |
| 215 NSString* closeAllTabsID = kToolsMenuCloseAllTabsId; |
| 216 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(closeAllTabsID)] |
| 217 performAction:grey_tap()]; |
| 218 // Wait for CardViews to be dismissed. |
| 219 for (CardView* cardView in cardViews) { |
| 220 [[EarlGrey selectElementWithMatcher:viewMatchingView(cardView)] |
| 221 assertWithMatcher:grey_notVisible()]; |
| 222 } |
| 223 // Check that all Tabs were closed. |
| 224 GREYAssertEqual(chrome_test_util::GetMainTabCount(), 0, |
| 225 @"Tabs were not closed."); |
| 226 GREYAssertEqual(chrome_test_util::GetIncognitoTabCount(), 0, |
| 227 @"Incognito Tab was not closed."); |
| 228 } |
| 229 |
| 230 // Tests that tapping on the inactive deck region switches modes. |
| 231 - (void)testSwitchingModes { |
| 232 // The StackViewController is only used on iPhones. |
| 233 if (IsIPadIdiom()) |
| 234 EARL_GREY_TEST_SKIPPED(@"Stack view is not used on iPads."); |
| 235 // Open an Incognito Tab then switch decks. |
| 236 OpenNewIncognitoTabUsingStackView(); |
| 237 ShowDeckWithType(DeckType::INCOGNITO); |
| 238 // Verify that the current CardSet is the incognito set. |
| 239 StackViewController* stackViewController = |
| 240 chrome_test_util::GetStackViewController(); |
| 241 GREYAssert([stackViewController isCurrentSetIncognito], |
| 242 @"Incognito deck not selected."); |
| 243 // Switch back to the main CardSet and verify that is selected. |
| 244 ShowDeckWithType(DeckType::NORMAL); |
| 245 GREYAssert(![stackViewController isCurrentSetIncognito], |
| 246 @"Normal deck not selected."); |
| 247 } |
| 248 |
| 249 @end |
OLD | NEW |