OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import <XCTest/XCTest.h> | 5 #import <XCTest/XCTest.h> |
6 | 6 |
7 #include "base/ios/block_types.h" | 7 #include "base/ios/block_types.h" |
8 #include "base/mac/foundation_util.h" | 8 #include "base/mac/foundation_util.h" |
9 #include "base/strings/sys_string_conversions.h" | 9 #include "base/strings/sys_string_conversions.h" |
10 #import "base/test/ios/wait_util.h" | 10 #import "base/test/ios/wait_util.h" |
11 #include "ios/chrome/browser/browser_state/chrome_browser_state.h" | 11 #include "ios/chrome/browser/browser_state/chrome_browser_state.h" |
12 #include "ios/chrome/browser/pref_names.h" | 12 #include "ios/chrome/browser/pref_names.h" |
13 #import "ios/chrome/browser/tabs/tab.h" | 13 #import "ios/chrome/browser/tabs/tab.h" |
14 #import "ios/chrome/browser/tabs/tab_model.h" | 14 #import "ios/chrome/browser/tabs/tab_model.h" |
15 #import "ios/chrome/browser/ui/browser_view_controller.h" | 15 #import "ios/chrome/browser/ui/browser_view_controller.h" |
16 #import "ios/chrome/browser/ui/stack_view/card_view.h" | 16 #import "ios/chrome/browser/ui/stack_view/card_view.h" |
17 #import "ios/chrome/browser/ui/stack_view/stack_view_controller.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" | 18 #import "ios/chrome/browser/ui/stack_view/stack_view_controller_private.h" |
19 #import "ios/chrome/browser/ui/toolbar/toolbar_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" | 20 #import "ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.h" |
21 #import "ios/chrome/test/app/stack_view_test_util.h" | 21 #import "ios/chrome/test/app/stack_view_test_util.h" |
22 #import "ios/chrome/test/app/tab_test_util.h" | 22 #import "ios/chrome/test/app/tab_test_util.h" |
23 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" | 23 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" |
24 #import "ios/chrome/test/earl_grey/chrome_matchers.h" | 24 #import "ios/chrome/test/earl_grey/chrome_matchers.h" |
25 #import "ios/chrome/test/earl_grey/chrome_test_case.h" | 25 #import "ios/chrome/test/earl_grey/chrome_test_case.h" |
26 #include "ios/testing/earl_grey/disabled_test_macros.h" | 26 #include "ios/testing/earl_grey/disabled_test_macros.h" |
| 27 #import "ios/testing/wait_util.h" |
27 | 28 |
28 #if !defined(__has_feature) || !__has_feature(objc_arc) | 29 #if !defined(__has_feature) || !__has_feature(objc_arc) |
29 #error "This file requires ARC support." | 30 #error "This file requires ARC support." |
30 #endif | 31 #endif |
31 | 32 |
32 namespace { | 33 namespace { |
33 // Returns a GREYMatcher that matches |view|. | 34 // Returns a GREYMatcher that matches |view|. |
34 // TODO(crbug.com/642619): Evaluate whether this should be shared code. | 35 // TODO(crbug.com/642619): Evaluate whether this should be shared code. |
35 id<GREYMatcher> ViewMatchingView(UIView* view) { | 36 id<GREYMatcher> ViewMatchingView(UIView* view) { |
36 MatchesBlock matches = ^BOOL(UIView* viewToMatch) { | 37 MatchesBlock matches = ^BOOL(UIView* viewToMatch) { |
37 return viewToMatch == view; | 38 return viewToMatch == view; |
38 }; | 39 }; |
39 DescribeToBlock describe = ^void(id<GREYDescription> description) { | 40 DescribeToBlock describe = ^void(id<GREYDescription> description) { |
40 NSString* matcherDescription = | 41 NSString* matcherDescription = |
41 [NSString stringWithFormat:@"View matching %@", view]; | 42 [NSString stringWithFormat:@"View matching %@", view]; |
42 [description appendText:matcherDescription]; | 43 [description appendText:matcherDescription]; |
43 }; | 44 }; |
44 return [[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches | 45 return [[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches |
45 descriptionBlock:describe]; | 46 descriptionBlock:describe]; |
46 } | 47 } |
47 | 48 |
48 // Returns a matcher for the StackViewController's view. | 49 // Returns a matcher for the StackViewController's view. |
49 id<GREYMatcher> StackView() { | 50 id<GREYMatcher> StackView() { |
50 return ViewMatchingView([chrome_test_util::GetStackViewController() view]); | 51 return ViewMatchingView([chrome_test_util::GetStackViewController() view]); |
51 } | 52 } |
52 | 53 |
53 // Waits for the Stack View to be visible/hidden. | 54 // Waits for the Stack View to be active/inactive. |
| 55 void WaitForStackViewActive(bool active) { |
| 56 NSString* activeStatusString = active ? @"active" : @"inactive"; |
| 57 NSString* activeTabSwitcherDescription = |
| 58 [NSString stringWithFormat:@"Waiting for tab switcher to be %@.", |
| 59 activeStatusString]; |
| 60 BOOL (^activeTabSwitcherBlock) |
| 61 () = ^BOOL { |
| 62 BOOL isActive = chrome_test_util::GetStackViewController() && |
| 63 chrome_test_util::IsTabSwitcherActive(); |
| 64 return active ? isActive : !isActive; |
| 65 }; |
| 66 GREYCondition* activeTabSwitcherCondition = |
| 67 [GREYCondition conditionWithName:activeTabSwitcherDescription |
| 68 block:activeTabSwitcherBlock]; |
| 69 NSString* assertDescription = [NSString |
| 70 stringWithFormat:@"Tab switcher did not become %@.", activeStatusString]; |
| 71 |
| 72 GREYAssert([activeTabSwitcherCondition |
| 73 waitWithTimeout:testing::kWaitForUIElementTimeout], |
| 74 assertDescription); |
| 75 } |
| 76 |
| 77 // Verify the visibility of the stack view. |
54 void CheckForStackViewVisibility(bool visible) { | 78 void CheckForStackViewVisibility(bool visible) { |
55 id<GREYMatcher> visibilityMatcher = | 79 id<GREYMatcher> visibilityMatcher = |
56 grey_allOf(visible ? grey_sufficientlyVisible() : grey_notVisible(), | 80 grey_allOf(visible ? grey_sufficientlyVisible() : grey_notVisible(), |
57 visible ? grey_notNil() : grey_nil(), nil); | 81 visible ? grey_notNil() : grey_nil(), nil); |
58 [[EarlGrey selectElementWithMatcher:StackView()] | 82 [[EarlGrey selectElementWithMatcher:StackView()] |
59 assertWithMatcher:visibilityMatcher]; | 83 assertWithMatcher:visibilityMatcher]; |
60 } | 84 } |
61 | 85 |
62 // Opens the StackViewController. | 86 // Opens the StackViewController. |
63 void OpenStackView() { | 87 void OpenStackView() { |
64 if (chrome_test_util::IsTabSwitcherActive()) | 88 if (chrome_test_util::IsTabSwitcherActive()) |
65 return; | 89 return; |
66 // Tap on the toolbar's tab switcher button. | 90 // Tap on the toolbar's tab switcher button. |
67 id<GREYMatcher> stackButtonMatcher = | 91 id<GREYMatcher> stackButtonMatcher = |
68 grey_allOf(grey_accessibilityID(kToolbarStackButtonIdentifier), | 92 grey_allOf(grey_accessibilityID(kToolbarStackButtonIdentifier), |
69 grey_sufficientlyVisible(), nil); | 93 grey_sufficientlyVisible(), nil); |
70 [[EarlGrey selectElementWithMatcher:stackButtonMatcher] | 94 [[EarlGrey selectElementWithMatcher:stackButtonMatcher] |
71 performAction:grey_tap()]; | 95 performAction:grey_tap()]; |
72 // Verify that a StackViewController was presented. | 96 // Verify that a StackViewController was presented. |
| 97 WaitForStackViewActive(true); |
73 CheckForStackViewVisibility(true); | 98 CheckForStackViewVisibility(true); |
74 } | 99 } |
75 | 100 |
76 // Shows either the normal or incognito deck. | 101 // Shows either the normal or incognito deck. |
77 enum class DeckType : bool { NORMAL, INCOGNITO }; | 102 enum class DeckType : bool { NORMAL, INCOGNITO }; |
78 void ShowDeckWithType(DeckType type) { | 103 void ShowDeckWithType(DeckType type) { |
79 OpenStackView(); | 104 OpenStackView(); |
80 StackViewController* stackViewController = | 105 StackViewController* stackViewController = |
81 chrome_test_util::GetStackViewController(); | 106 chrome_test_util::GetStackViewController(); |
82 UIView* activeDisplayView = stackViewController.activeCardSet.displayView; | 107 UIView* activeDisplayView = stackViewController.activeCardSet.displayView; |
(...skipping 15 matching lines...) Expand all Loading... |
98 } | 123 } |
99 } | 124 } |
100 | 125 |
101 // Opens a new tab using the stack view button. | 126 // Opens a new tab using the stack view button. |
102 void OpenNewTabUsingStackView() { | 127 void OpenNewTabUsingStackView() { |
103 // Open the stack view, tap the New Tab button, and wait for the animation to | 128 // Open the stack view, tap the New Tab button, and wait for the animation to |
104 // finish. | 129 // finish. |
105 ShowDeckWithType(DeckType::NORMAL); | 130 ShowDeckWithType(DeckType::NORMAL); |
106 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"New Tab")] | 131 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"New Tab")] |
107 performAction:grey_tap()]; | 132 performAction:grey_tap()]; |
| 133 WaitForStackViewActive(false); |
108 CheckForStackViewVisibility(false); | 134 CheckForStackViewVisibility(false); |
109 } | 135 } |
110 | 136 |
111 // Opens the tools menu from the stack view. | 137 // Opens the tools menu from the stack view. |
112 void OpenToolsMenu() { | 138 void OpenToolsMenu() { |
113 OpenStackView(); | 139 OpenStackView(); |
114 [[EarlGrey selectElementWithMatcher:chrome_test_util::ToolsMenuButton()] | 140 [[EarlGrey selectElementWithMatcher:chrome_test_util::ToolsMenuButton()] |
115 performAction:grey_tap()]; | 141 performAction:grey_tap()]; |
116 } | 142 } |
117 | 143 |
118 // Opens a new Incognito Tab using the stack view button. | 144 // Opens a new Incognito Tab using the stack view button. |
119 void OpenNewIncognitoTabUsingStackView() { | 145 void OpenNewIncognitoTabUsingStackView() { |
120 OpenToolsMenu(); | 146 OpenToolsMenu(); |
121 NSString* newIncognitoTabID = kToolsMenuNewIncognitoTabId; | 147 NSString* newIncognitoTabID = kToolsMenuNewIncognitoTabId; |
122 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(newIncognitoTabID)] | 148 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(newIncognitoTabID)] |
123 performAction:grey_tap()]; | 149 performAction:grey_tap()]; |
| 150 WaitForStackViewActive(false); |
124 CheckForStackViewVisibility(false); | 151 CheckForStackViewVisibility(false); |
125 } | 152 } |
126 | 153 |
127 // Taps the CardView associated with |tab|. | 154 // Taps the CardView associated with |tab|. |
128 void SelectTabUsingStackView(Tab* tab) { | 155 void SelectTabUsingStackView(Tab* tab) { |
129 DCHECK(tab); | 156 DCHECK(tab); |
130 // Present the StackViewController. | 157 // Present the StackViewController. |
131 OpenStackView(); | 158 OpenStackView(); |
132 // Get the StackCard associated with |tab|. | 159 // Get the StackCard associated with |tab|. |
133 StackViewController* stackViewController = | 160 StackViewController* stackViewController = |
134 chrome_test_util::GetStackViewController(); | 161 chrome_test_util::GetStackViewController(); |
135 StackCard* nextCard = [[stackViewController activeCardSet] cardForTab:tab]; | 162 StackCard* nextCard = [[stackViewController activeCardSet] cardForTab:tab]; |
136 UIView* card_title_label = static_cast<UIView*>([[nextCard view] titleLabel]); | 163 UIView* card_title_label = static_cast<UIView*>([[nextCard view] titleLabel]); |
137 [[EarlGrey selectElementWithMatcher:ViewMatchingView(card_title_label)] | 164 [[EarlGrey selectElementWithMatcher:ViewMatchingView(card_title_label)] |
138 performAction:grey_tap()]; | 165 performAction:grey_tap()]; |
139 // Wait for the StackViewController to be dismissed. | 166 // Wait for the StackViewController to be dismissed. |
| 167 WaitForStackViewActive(false); |
140 CheckForStackViewVisibility(false); | 168 CheckForStackViewVisibility(false); |
141 // Checks that the next Tab has been selected. | 169 // Checks that the next Tab has been selected. |
142 GREYAssertEqual(tab, chrome_test_util::GetCurrentTab(), | 170 GREYAssertEqual(tab, chrome_test_util::GetCurrentTab(), |
143 @"The next Tab was not selected"); | 171 @"The next Tab was not selected"); |
144 } | 172 } |
145 } | 173 } |
146 | 174 |
147 // Tests for interacting with the StackViewController. | 175 // Tests for interacting with the StackViewController. |
148 @interface StackViewTestCase : ChromeTestCase | 176 @interface StackViewTestCase : ChromeTestCase |
149 @end | 177 @end |
(...skipping 30 matching lines...) Expand all Loading... |
180 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(identifier)] | 208 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(identifier)] |
181 performAction:grey_tap()]; | 209 performAction:grey_tap()]; |
182 // Verify that the CardView and its associated Tab were removed. | 210 // Verify that the CardView and its associated Tab were removed. |
183 [[EarlGrey selectElementWithMatcher:ViewMatchingView(cardView)] | 211 [[EarlGrey selectElementWithMatcher:ViewMatchingView(cardView)] |
184 assertWithMatcher:grey_notVisible()]; | 212 assertWithMatcher:grey_notVisible()]; |
185 GREYAssertEqual(chrome_test_util::GetMainTabCount(), 0, | 213 GREYAssertEqual(chrome_test_util::GetMainTabCount(), 0, |
186 @"All Tabs should be closed."); | 214 @"All Tabs should be closed."); |
187 } | 215 } |
188 | 216 |
189 // Tests closing all Tabs in the stack view. | 217 // Tests closing all Tabs in the stack view. |
190 // TODO(crbug.com/693517): Re-enable this test on simulator. | 218 - (void)testCloseAllTabs { |
191 #if TARGET_IPHONE_SIMULATOR | |
192 #define MAYBE_testCloseAllTabs FLAKY_testCloseAllTabs | |
193 #else | |
194 #define MAYBE_testCloseAllTabs testCloseAllTabs | |
195 #endif | |
196 - (void)MAYBE_testCloseAllTabs { | |
197 // The StackViewController is only used on iPhones. | 219 // The StackViewController is only used on iPhones. |
198 if (IsIPadIdiom()) | 220 if (IsIPadIdiom()) |
199 EARL_GREY_TEST_SKIPPED(@"Stack view is not used on iPads."); | 221 EARL_GREY_TEST_SKIPPED(@"Stack view is not used on iPads."); |
200 // Open an incognito Tab. | 222 // Open an incognito Tab. |
201 OpenNewIncognitoTabUsingStackView(); | 223 OpenNewIncognitoTabUsingStackView(); |
202 GREYAssertEqual(chrome_test_util::GetIncognitoTabCount(), 1, | 224 GREYAssertEqual(chrome_test_util::GetIncognitoTabCount(), 1, |
203 @"Incognito Tab was not opened."); | 225 @"Incognito Tab was not opened."); |
204 // Open two additional Tabs. | 226 // Open two additional Tabs. |
205 const NSUInteger kAdditionalTabCount = 2; | 227 const NSUInteger kAdditionalTabCount = 2; |
206 for (NSUInteger i = 0; i < kAdditionalTabCount; ++i) | 228 for (NSUInteger i = 0; i < kAdditionalTabCount; ++i) |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 chrome_test_util::GetStackViewController(); | 272 chrome_test_util::GetStackViewController(); |
251 GREYAssert([stackViewController isCurrentSetIncognito], | 273 GREYAssert([stackViewController isCurrentSetIncognito], |
252 @"Incognito deck not selected."); | 274 @"Incognito deck not selected."); |
253 // Switch back to the main CardSet and verify that is selected. | 275 // Switch back to the main CardSet and verify that is selected. |
254 ShowDeckWithType(DeckType::NORMAL); | 276 ShowDeckWithType(DeckType::NORMAL); |
255 GREYAssert(![stackViewController isCurrentSetIncognito], | 277 GREYAssert(![stackViewController isCurrentSetIncognito], |
256 @"Normal deck not selected."); | 278 @"Normal deck not selected."); |
257 } | 279 } |
258 | 280 |
259 @end | 281 @end |
OLD | NEW |