OLD | NEW |
(Empty) | |
| 1 // Copyright 2013 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 #include "base/mac/scoped_nsobject.h" |
| 6 #import "ios/chrome/browser/ui/fullscreen_controller.h" |
| 7 #import "ios/web/public/test/test_web_view_content_view.h" |
| 8 #import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h" |
| 9 #import "ios/web/public/web_state/ui/crw_web_view_content_view.h" |
| 10 #import "ios/web/web_state/crw_web_view_proxy_impl.h" |
| 11 #import "ios/web/web_state/ui/crw_web_controller.h" |
| 12 #include "testing/platform_test.h" |
| 13 #import "third_party/ocmock/OCMock/OCMock.h" |
| 14 #include "third_party/ocmock/ocmock_extensions.h" |
| 15 |
| 16 namespace { |
| 17 |
| 18 CGFloat kContentHeight = 5000.0; |
| 19 CGFloat kHeaderHeight = 42.0; |
| 20 } |
| 21 |
| 22 @interface MockFullScreenControllerDelegate |
| 23 : NSObject<FullScreenControllerDelegate> |
| 24 @property(nonatomic, readonly) float currentPosition; |
| 25 @property(nonatomic, assign) BOOL fakeIsTabWithIDCurrentFlag; |
| 26 @end |
| 27 |
| 28 @implementation MockFullScreenControllerDelegate |
| 29 @synthesize currentPosition = currentPosition_; |
| 30 @synthesize fakeIsTabWithIDCurrentFlag = fakeIsTabWithIDCurrentFlag_; |
| 31 |
| 32 - (id)init { |
| 33 if ((self = [super init])) { |
| 34 currentPosition_ = 0.0; |
| 35 fakeIsTabWithIDCurrentFlag_ = YES; |
| 36 } |
| 37 return self; |
| 38 } |
| 39 |
| 40 - (void)fullScreenController:(FullScreenController*)fullscreenController |
| 41 drawHeaderViewFromOffset:(CGFloat)headerOffset |
| 42 animate:(BOOL)animate { |
| 43 currentPosition_ = headerOffset; |
| 44 } |
| 45 |
| 46 - (void)fullScreenController:(FullScreenController*)fullScreenController |
| 47 drawHeaderViewFromOffset:(CGFloat)headerOffset |
| 48 onWebViewProxy:(id<CRWWebViewProxy>)webViewProxy |
| 49 changeTopContentPadding:(BOOL)changeTopContentPadding |
| 50 scrollingToOffset:(CGFloat)contentOffset { |
| 51 currentPosition_ = headerOffset; |
| 52 webViewProxy.scrollViewProxy.contentOffset = CGPointMake(0.0f, contentOffset); |
| 53 } |
| 54 |
| 55 - (BOOL)isTabWithIDCurrent:(NSString*)sessionID { |
| 56 return [self fakeIsTabWithIDCurrentFlag]; |
| 57 } |
| 58 |
| 59 - (CGFloat)currentHeaderOffset { |
| 60 return currentPosition_; |
| 61 } |
| 62 |
| 63 - (CGFloat)headerHeight { |
| 64 return kHeaderHeight; |
| 65 } |
| 66 |
| 67 @end |
| 68 |
| 69 namespace { |
| 70 |
| 71 NSString* const kFakeSessionId = @"fake-session-id"; |
| 72 |
| 73 class FullscreenControllerTest : public PlatformTest { |
| 74 protected: |
| 75 void SetUp() override { |
| 76 CGRect frame = CGRectMake(0.0, 0.0, 300.0, 900.0); |
| 77 PlatformTest::SetUp(); |
| 78 |
| 79 [FullScreenController setHideOmniboxDelaySeconds:0.0]; |
| 80 |
| 81 scrollview_.reset([[UIScrollView alloc] initWithFrame:frame]); |
| 82 scrollview_.get().contentInset = UIEdgeInsetsZero; |
| 83 [GetWindow() addSubview:scrollview_]; |
| 84 |
| 85 CGRect contentSize = CGRectMake(0.0, 0.0, frame.size.width, kContentHeight); |
| 86 scrollview_.get().contentSize = contentSize.size; |
| 87 mockWebController_.reset( |
| 88 [[OCMockObject niceMockForClass:[CRWWebController class]] retain]); |
| 89 mockDelegate_.reset([[MockFullScreenControllerDelegate alloc] init]); |
| 90 mockWebView_.reset([[UIView alloc] init]); |
| 91 mockContentView_.reset([[TestWebViewContentView alloc] |
| 92 initWithMockWebView:mockWebView_ |
| 93 scrollView:scrollview_]); |
| 94 webViewProxy_.reset( |
| 95 [[CRWWebViewProxyImpl alloc] initWithWebController:mockWebController_]); |
| 96 [webViewProxy_ setContentView:mockContentView_]; |
| 97 webViewScrollViewProxy_.reset([[webViewProxy_ scrollViewProxy] retain]); |
| 98 controller_.reset([[FullScreenController alloc] |
| 99 initWithDelegate:mockDelegate_ |
| 100 navigationManager:NULL |
| 101 sessionID:kFakeSessionId]); |
| 102 DCHECK(controller_); |
| 103 [webViewScrollViewProxy_ addObserver:controller_]; |
| 104 // Simulate a CRWWebControllerObserver callback. |
| 105 [controller_ setWebViewProxy:webViewProxy_ controller:mockWebController_]; |
| 106 [controller_ moveHeaderToRestingPosition:YES]; |
| 107 |
| 108 base::scoped_nsobject<UIView> awesome_view( |
| 109 [[UIView alloc] initWithFrame:contentSize]); |
| 110 [scrollview_ addSubview:awesome_view]; |
| 111 |
| 112 EXPECT_TRUE(IsHeaderVisible()); |
| 113 EXPECT_EQ(0.0f, webViewScrollViewProxy_.get().contentOffset.y); |
| 114 } |
| 115 |
| 116 void TearDown() override { |
| 117 [webViewScrollViewProxy_.get() removeObserver:controller_]; |
| 118 [webViewScrollViewProxy_ setScrollView:nil]; |
| 119 [scrollview_ removeFromSuperview]; |
| 120 PlatformTest::TearDown(); |
| 121 } |
| 122 |
| 123 void MoveMiddle() { |
| 124 // Move somewhere in the middle. |
| 125 CGFloat middle_point = kContentHeight / 2.0; |
| 126 webViewScrollViewProxy_.get().contentOffset = |
| 127 CGPointMake(0.0, middle_point); |
| 128 } |
| 129 |
| 130 void MoveTop() { |
| 131 webViewScrollViewProxy_.get().contentOffset = |
| 132 CGPointMake(0.0, -kHeaderHeight); |
| 133 } |
| 134 |
| 135 void MoveMiddleAndHide() { |
| 136 MoveMiddle(); |
| 137 [controller_ moveHeaderToRestingPosition:NO]; |
| 138 EXPECT_TRUE(IsHeaderHidden()); |
| 139 } |
| 140 |
| 141 UIWindow* GetWindow() { |
| 142 UIWindow* window = [[UIApplication sharedApplication] keyWindow]; |
| 143 if (!window) |
| 144 window = [[[UIApplication sharedApplication] windows] lastObject]; |
| 145 EXPECT_TRUE(window != nil); |
| 146 return window; |
| 147 } |
| 148 |
| 149 bool IsHeaderVisible() { return [mockDelegate_ currentPosition] == 0.0; } |
| 150 |
| 151 bool IsHeaderHidden() { |
| 152 return [mockDelegate_ currentPosition] == kHeaderHeight; |
| 153 } |
| 154 |
| 155 // Adds |view| as a sub view to the underlying |scrollview_|. |
| 156 void AddSubViewToScrollView(UIView* view) { [scrollview_ addSubview:view]; } |
| 157 |
| 158 base::scoped_nsobject<FullScreenController> controller_; |
| 159 base::scoped_nsobject<MockFullScreenControllerDelegate> mockDelegate_; |
| 160 base::scoped_nsobject<CRWWebViewScrollViewProxy> webViewScrollViewProxy_; |
| 161 base::scoped_nsobject<id> mockWebView_; |
| 162 base::scoped_nsobject<id> mockWebController_; |
| 163 base::scoped_nsobject<TestWebViewContentView> mockContentView_; |
| 164 base::scoped_nsobject<CRWWebViewProxyImpl> webViewProxy_; |
| 165 |
| 166 private: |
| 167 base::scoped_nsobject<UIScrollView> scrollview_; |
| 168 }; |
| 169 |
| 170 #pragma mark - Programmatic moves |
| 171 |
| 172 TEST_F(FullscreenControllerTest, ForceHidden) { |
| 173 [controller_ moveHeaderToRestingPosition:NO]; |
| 174 EXPECT_TRUE(IsHeaderHidden()); |
| 175 EXPECT_EQ(0.0, webViewScrollViewProxy_.get().contentOffset.y); |
| 176 } |
| 177 |
| 178 #pragma mark - Simulated user moves. |
| 179 |
| 180 TEST_F(FullscreenControllerTest, LargeManualScrollUpHides) { |
| 181 MoveMiddle(); |
| 182 |
| 183 [controller_ webViewScrollViewWillBeginDragging:webViewScrollViewProxy_]; |
| 184 |
| 185 CGFloat middle_point = webViewScrollViewProxy_.get().contentOffset.y; |
| 186 // Move up a bit, multiple times |
| 187 for (float i = 0.0; i < kHeaderHeight * 2.0; i++) { |
| 188 webViewScrollViewProxy_.get().contentOffset = |
| 189 CGPointMake(0.0, middle_point + i); |
| 190 } |
| 191 [controller_ webViewScrollViewDidEndDragging:webViewScrollViewProxy_ |
| 192 willDecelerate:NO]; |
| 193 EXPECT_TRUE(IsHeaderHidden()); |
| 194 } |
| 195 |
| 196 TEST_F(FullscreenControllerTest, PartialManualScrollUpHides) { |
| 197 MoveMiddle(); |
| 198 |
| 199 [controller_ webViewScrollViewWillBeginDragging:webViewScrollViewProxy_]; |
| 200 |
| 201 CGFloat middle_point = webViewScrollViewProxy_.get().contentOffset.y; |
| 202 // Move up a bit, multiple times |
| 203 for (float i = 0.0; i < (kHeaderHeight * (2.0 / 3.0)); i++) { |
| 204 webViewScrollViewProxy_.get().contentOffset = |
| 205 CGPointMake(0.0, middle_point + i); |
| 206 } |
| 207 [controller_ webViewScrollViewDidEndDragging:webViewScrollViewProxy_ |
| 208 willDecelerate:NO]; |
| 209 EXPECT_TRUE(IsHeaderHidden()); |
| 210 } |
| 211 |
| 212 TEST_F(FullscreenControllerTest, SmallPartialManualScrollUpNoEffect) { |
| 213 MoveMiddle(); |
| 214 |
| 215 [controller_ webViewScrollViewWillBeginDragging:webViewScrollViewProxy_]; |
| 216 |
| 217 CGFloat middle_point = webViewScrollViewProxy_.get().contentOffset.y; |
| 218 // Move up a bit, multiple times |
| 219 for (float i = 0.0; i < (kHeaderHeight / 3.0); i++) { |
| 220 webViewScrollViewProxy_.get().contentOffset = |
| 221 CGPointMake(0.0, middle_point + i); |
| 222 } |
| 223 [controller_ webViewScrollViewDidEndDragging:webViewScrollViewProxy_ |
| 224 willDecelerate:NO]; |
| 225 EXPECT_TRUE(IsHeaderVisible()); |
| 226 } |
| 227 |
| 228 TEST_F(FullscreenControllerTest, LargeManualScrollDownShows) { |
| 229 MoveMiddleAndHide(); |
| 230 |
| 231 [controller_ webViewScrollViewWillBeginDragging:webViewScrollViewProxy_]; |
| 232 |
| 233 CGFloat middle_point = webViewScrollViewProxy_.get().contentOffset.y; |
| 234 // Move down a bit, multiple times |
| 235 for (float i = 0.0; i < kHeaderHeight * 2.0; i++) { |
| 236 webViewScrollViewProxy_.get().contentOffset = |
| 237 CGPointMake(0.0, middle_point - i); |
| 238 } |
| 239 [controller_ webViewScrollViewDidEndDragging:webViewScrollViewProxy_ |
| 240 willDecelerate:NO]; |
| 241 EXPECT_TRUE(IsHeaderVisible()); |
| 242 } |
| 243 |
| 244 TEST_F(FullscreenControllerTest, PartialManualScrollDownShows) { |
| 245 MoveMiddleAndHide(); |
| 246 |
| 247 [controller_ webViewScrollViewWillBeginDragging:webViewScrollViewProxy_]; |
| 248 |
| 249 CGFloat middle_point = webViewScrollViewProxy_.get().contentOffset.y; |
| 250 // Move down a bit, multiple times |
| 251 for (float i = 0.0; i < (kHeaderHeight * (2.0 / 3.0)); i++) { |
| 252 webViewScrollViewProxy_.get().contentOffset = |
| 253 CGPointMake(0.0, middle_point - i); |
| 254 } |
| 255 [controller_ webViewScrollViewDidEndDragging:webViewScrollViewProxy_ |
| 256 willDecelerate:NO]; |
| 257 EXPECT_TRUE(IsHeaderVisible()); |
| 258 } |
| 259 |
| 260 TEST_F(FullscreenControllerTest, SmallPartialManualScrollDownNoEffect) { |
| 261 MoveMiddleAndHide(); |
| 262 |
| 263 [controller_ webViewScrollViewWillBeginDragging:webViewScrollViewProxy_]; |
| 264 |
| 265 CGFloat middle_point = webViewScrollViewProxy_.get().contentOffset.y; |
| 266 // Move up a bit, multiple times |
| 267 for (float i = 0.0; i < (kHeaderHeight / 3.0); i++) { |
| 268 webViewScrollViewProxy_.get().contentOffset = |
| 269 CGPointMake(0.0, middle_point - i); |
| 270 } |
| 271 [controller_ webViewScrollViewDidEndDragging:webViewScrollViewProxy_ |
| 272 willDecelerate:NO]; |
| 273 EXPECT_TRUE(IsHeaderHidden()); |
| 274 } |
| 275 |
| 276 #pragma mark - Page load. |
| 277 |
| 278 TEST_F(FullscreenControllerTest, NoHideOnEnable) { |
| 279 [controller_ disableFullScreen]; |
| 280 webViewScrollViewProxy_.get().contentOffset = CGPointMake(0.0, 10.0); |
| 281 EXPECT_TRUE(IsHeaderVisible()); |
| 282 |
| 283 [controller_ enableFullScreen]; |
| 284 |
| 285 EXPECT_TRUE(IsHeaderVisible()); |
| 286 } |
| 287 |
| 288 TEST_F(FullscreenControllerTest, NoHideOnEnableDueToManualScroll) { |
| 289 [controller_ disableFullScreen]; |
| 290 webViewScrollViewProxy_.get().contentOffset = CGPointMake(0.0, 1.0); |
| 291 EXPECT_TRUE(IsHeaderVisible()); |
| 292 |
| 293 [controller_ webViewScrollViewWillBeginDragging:webViewScrollViewProxy_]; |
| 294 webViewScrollViewProxy_.get().contentOffset = CGPointMake(0.0, 10.0); |
| 295 EXPECT_TRUE(IsHeaderVisible()); |
| 296 [controller_ webViewScrollViewDidEndDragging:webViewScrollViewProxy_ |
| 297 willDecelerate:NO]; |
| 298 |
| 299 [controller_ enableFullScreen]; |
| 300 |
| 301 EXPECT_TRUE(IsHeaderVisible()); |
| 302 } |
| 303 |
| 304 #pragma mark - Keyboard. |
| 305 |
| 306 TEST_F(FullscreenControllerTest, KeyboardAppearanceOnNonFullscreenPage) { |
| 307 // Add a textfield. |
| 308 base::scoped_nsobject<UITextField> textField([[UITextField alloc] init]); |
| 309 AddSubViewToScrollView(textField); |
| 310 EXPECT_TRUE(IsHeaderVisible()); |
| 311 |
| 312 // Show the keyboard. |
| 313 [textField becomeFirstResponder]; |
| 314 EXPECT_TRUE(IsHeaderVisible()); |
| 315 |
| 316 // Hide the keyboard. |
| 317 [textField resignFirstResponder]; |
| 318 EXPECT_TRUE(IsHeaderVisible()); |
| 319 } |
| 320 |
| 321 // TODO(lliabraa): Fails on Xcode 6 simulator (crbug.com/392433). |
| 322 #if TARGET_IPHONE_SIMULATOR |
| 323 #define MAYBE_KeyboardAppearanceOnFullscreenPage \ |
| 324 KeyboardAppearanceOnFullscreenPage |
| 325 #else |
| 326 #define MAYBE_KeyboardAppearanceOnFullscreenPage \ |
| 327 KeyboardAppearanceOnFullscreenPage |
| 328 #endif |
| 329 TEST_F(FullscreenControllerTest, MAYBE_KeyboardAppearanceOnFullscreenPage) { |
| 330 // Scroll a bit to hide the toolbar. |
| 331 MoveMiddleAndHide(); |
| 332 |
| 333 // Add a textfield. |
| 334 base::scoped_nsobject<UITextField> textField([[UITextField alloc] init]); |
| 335 AddSubViewToScrollView(textField); |
| 336 EXPECT_TRUE(IsHeaderHidden()); |
| 337 |
| 338 // Show the keyboard. |
| 339 [textField becomeFirstResponder]; |
| 340 EXPECT_TRUE(IsHeaderVisible()); |
| 341 |
| 342 // Hide the keyboard. |
| 343 [textField resignFirstResponder]; |
| 344 |
| 345 // Toolbars are never auto-hidden. |
| 346 EXPECT_FALSE(IsHeaderHidden()); |
| 347 } |
| 348 |
| 349 // TODO(lliabraa): Fails on Xcode 6 simulator (crbug.com/392433). |
| 350 #if TARGET_IPHONE_SIMULATOR |
| 351 #define MAYBE_KeyboardStayOnUserScrollOnNonFullscreenPage \ |
| 352 KeyboardStayOnUserScrollOnNonFullscreenPage |
| 353 #else |
| 354 #define MAYBE_KeyboardStayOnUserScrollOnNonFullscreenPage \ |
| 355 KeyboardStayOnUserScrollOnNonFullscreenPage |
| 356 #endif |
| 357 TEST_F(FullscreenControllerTest, |
| 358 MAYBE_KeyboardStayOnUserScrollOnNonFullscreenPage) { |
| 359 // Add a textfield. |
| 360 base::scoped_nsobject<UITextField> textField([[UITextField alloc] init]); |
| 361 AddSubViewToScrollView(textField); |
| 362 EXPECT_TRUE(IsHeaderVisible()); |
| 363 |
| 364 // Show the keyboard. |
| 365 [textField becomeFirstResponder]; |
| 366 EXPECT_TRUE(IsHeaderVisible()); |
| 367 |
| 368 // Scroll. |
| 369 [controller_ webViewScrollViewWillBeginDragging:webViewScrollViewProxy_]; |
| 370 webViewScrollViewProxy_.get().contentOffset = CGPointMake(0.0, 100.0); |
| 371 [controller_ webViewScrollViewDidEndDragging:webViewScrollViewProxy_ |
| 372 willDecelerate:NO]; |
| 373 EXPECT_TRUE(IsHeaderVisible()); |
| 374 |
| 375 // Hide the keyboard. |
| 376 [textField resignFirstResponder]; |
| 377 EXPECT_TRUE(IsHeaderVisible()); |
| 378 } |
| 379 |
| 380 } // namespace |
OLD | NEW |