| Index: ios/chrome/browser/ui/stack_view/stack_view_controller_unittest.mm
|
| diff --git a/ios/chrome/browser/ui/stack_view/stack_view_controller_unittest.mm b/ios/chrome/browser/ui/stack_view/stack_view_controller_unittest.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..e7509e5e1152f587166971523f0b296357e0ba10
|
| --- /dev/null
|
| +++ b/ios/chrome/browser/ui/stack_view/stack_view_controller_unittest.mm
|
| @@ -0,0 +1,262 @@
|
| +// Copyright 2012 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#import <QuartzCore/QuartzCore.h>
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/mac/scoped_nsautorelease_pool.h"
|
| +#include "base/mac/scoped_nsobject.h"
|
| +#import "ios/chrome/browser/tabs/tab_model.h"
|
| +#import "ios/chrome/browser/ui/stack_view/card_set.h"
|
| +#import "ios/chrome/browser/ui/stack_view/stack_card.h"
|
| +#import "ios/chrome/browser/ui/stack_view/stack_view_controller.h"
|
| +#import "ios/chrome/browser/ui/stack_view/stack_view_controller_private.h"
|
| +#include "ios/chrome/test/block_cleanup_test.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +#include "testing/gtest_mac.h"
|
| +#include "third_party/ocmock/OCMock/OCMock.h"
|
| +
|
| +namespace {
|
| +
|
| +const CGFloat kViewportDimension = 200;
|
| +
|
| +} // namespace
|
| +
|
| +#pragma mark -
|
| +
|
| +@interface MockCardSet : NSObject {
|
| + @private
|
| + UIView* displayView_;
|
| + CGSize cardSize_;
|
| + CGFloat layoutAxisPosition_;
|
| + BOOL initialConfigurationSet_;
|
| + id observer_;
|
| +}
|
| +
|
| +// CardSet simulation
|
| +@property(nonatomic, retain, readwrite) UIView* displayView;
|
| +@property(nonatomic, assign, readwrite) CGSize cardSize;
|
| +@property(nonatomic, assign, readwrite) id<CardSetObserver> observer;
|
| +@property(nonatomic, assign, readwrite) BOOL keepOnlyVisibleCardViewsAlive;
|
| +
|
| +- (void)configureLayoutParametersWithMargin:(CGFloat)margin;
|
| +- (void)setLayoutAxisPosition:(CGFloat)position
|
| + isVertical:(BOOL)layoutIsVertical;
|
| +- (void)clearGestureRecognizerTargetAndDelegateFromCards:(id)object;
|
| +- (NSArray*)cards;
|
| +- (CGFloat)maximumStackLength;
|
| +- (void)displayViewSizeWasChanged;
|
| +- (TabModel*)tabModel;
|
| +- (void)setTabModel:(TabModel*)tabModel;
|
| +
|
| +// Testing helpers
|
| +- (BOOL)configured;
|
| +@property(nonatomic, assign, readonly) CGFloat layoutAxisPosition;
|
| +@end
|
| +
|
| +@implementation MockCardSet
|
| +
|
| +@synthesize displayView = displayView_;
|
| +@synthesize cardSize = cardSize_;
|
| +@synthesize observer = observer_;
|
| +@synthesize layoutAxisPosition = layoutAxisPosition_;
|
| +@synthesize keepOnlyVisibleCardViewsAlive = keepOnlyVisibleCardViewsAlive_;
|
| +
|
| +- (BOOL)configured {
|
| + return initialConfigurationSet_ && (layoutAxisPosition_ != 0);
|
| +}
|
| +
|
| +- (void)configureLayoutParametersWithMargin:(CGFloat)margin {
|
| + initialConfigurationSet_ = YES;
|
| +}
|
| +
|
| +- (void)setLayoutAxisPosition:(CGFloat)position
|
| + isVertical:(BOOL)layoutIsVertical {
|
| + layoutAxisPosition_ = position;
|
| +}
|
| +
|
| +- (void)clearGestureRecognizerTargetAndDelegateFromCards:(id)object {
|
| +}
|
| +
|
| +- (NSArray*)cards {
|
| + // TODO(stuartmorgan): Return an actual set of cards to allow for more
|
| + // interesting tests. For now this is just to satisfy the toolbar updating
|
| + // code that shows the card count.
|
| + return [NSArray array];
|
| +}
|
| +
|
| +- (CGFloat)maximumStackLength {
|
| + return 2.0 * kViewportDimension;
|
| +}
|
| +
|
| +- (void)displayViewSizeWasChanged {
|
| +}
|
| +
|
| +- (TabModel*)tabModel {
|
| + return nil;
|
| +}
|
| +
|
| +- (void)setTabModel:(TabModel*)tabModel {
|
| +}
|
| +
|
| +@end
|
| +
|
| +#pragma mark -
|
| +
|
| +namespace {
|
| +
|
| +class StackViewControllerTest : public BlockCleanupTest {
|
| + protected:
|
| + void SetUp() override {
|
| + BlockCleanupTest::SetUp();
|
| +
|
| + main_card_set_.reset([[MockCardSet alloc] init]);
|
| + otr_card_set_.reset([[MockCardSet alloc] init]);
|
| +
|
| + view_controller_.reset([[StackViewController alloc]
|
| + initWithMainCardSet:(CardSet*)main_card_set_.get()
|
| + otrCardSet:(CardSet*)otr_card_set_.get()
|
| + activeCardSet:(CardSet*)main_card_set_.get()]);
|
| + // Resize the view and call VC lifecycle events
|
| + [view_controller_ view].frame =
|
| + CGRectMake(0.0, 0.0, kViewportDimension, kViewportDimension);
|
| + // Simulate displaying the view.
|
| + [view_controller_ viewWillAppear:NO];
|
| + }
|
| + void TearDown() override {
|
| + // The view controller uses a delayed selector call, so in the unittests
|
| + // that causes the controller to be retained and outlive the test.
|
| + [NSObject cancelPreviousPerformRequestsWithTarget:view_controller_.get()];
|
| + // And there are likely animations still running.
|
| + for (UIView* view in [[view_controller_ scrollView] subviews]) {
|
| + // Remove any animations on cards themselves.
|
| + for (UIView* subview in [view subviews]) {
|
| + [subview.layer removeAllAnimations];
|
| + }
|
| + [view.layer removeAllAnimations];
|
| + }
|
| + [[[view_controller_ scrollView] layer] removeAllAnimations];
|
| +
|
| + // Manually run teardown.
|
| + [view_controller_ cleanUpViewsAndNotifications];
|
| +
|
| + BlockCleanupTest::TearDown();
|
| + }
|
| +
|
| + // Checks that the display view of |card_set| is correctly set up:
|
| + // - sized to match the size of the scroll view.
|
| + // - origin set to 0 on the non-layout axis, and to the scroll view's content
|
| + // offset on the layout axis.
|
| + // Also checks that the content size of the scroll view is configured
|
| + // appropriately for this card set:
|
| + // - greater than the maximum stack size along the layout axis to give enough
|
| + // space to fully scroll the cards to beginning/end without hitting the
|
| + // scroll view's boundaries.
|
| + // - equal to the display view size along the non-layout axis.
|
| + void ValidateDisplaySetupForCardSet(MockCardSet* card_set) {
|
| + DCHECK(card_set == main_card_set_ || card_set == otr_card_set_);
|
| + EXPECT_FLOAT_EQ([[card_set displayView] bounds].size.width,
|
| + [[view_controller_ scrollView] bounds].size.width);
|
| + EXPECT_FLOAT_EQ([[card_set displayView] bounds].size.height,
|
| + [[view_controller_ scrollView] bounds].size.height);
|
| + CGPoint display_view_origin = [[card_set displayView] frame].origin;
|
| + BOOL is_portrait = UIInterfaceOrientationIsPortrait(
|
| + [UIApplication sharedApplication].statusBarOrientation);
|
| + CGFloat content_offset =
|
| + is_portrait ? [[view_controller_ scrollView] contentOffset].y
|
| + : [[view_controller_ scrollView] contentOffset].x;
|
| + if (is_portrait) {
|
| + EXPECT_FLOAT_EQ(display_view_origin.x, 0);
|
| + EXPECT_FLOAT_EQ(display_view_origin.y, content_offset);
|
| + EXPECT_GT([[view_controller_ scrollView] contentSize].height,
|
| + [card_set maximumStackLength]);
|
| + EXPECT_FLOAT_EQ(card_set.displayView.bounds.size.width,
|
| + [[view_controller_ scrollView] contentSize].width);
|
| + } else {
|
| + EXPECT_FLOAT_EQ(display_view_origin.x, content_offset);
|
| + EXPECT_FLOAT_EQ(display_view_origin.y, 0);
|
| + EXPECT_GT([[view_controller_ scrollView] contentSize].width,
|
| + [card_set maximumStackLength]);
|
| + EXPECT_FLOAT_EQ(card_set.displayView.bounds.size.height,
|
| + [[view_controller_ scrollView] contentSize].height);
|
| + }
|
| + }
|
| +
|
| + base::scoped_nsobject<StackViewController> view_controller_;
|
| + base::scoped_nsobject<MockCardSet> main_card_set_;
|
| + base::scoped_nsobject<MockCardSet> otr_card_set_;
|
| +};
|
| +
|
| +TEST_F(StackViewControllerTest, BasicConfiguration) {
|
| + // Ensure that the CardSet is configured and correctly laid out.
|
| + EXPECT_TRUE([main_card_set_ configured]);
|
| + EXPECT_TRUE([otr_card_set_ configured]);
|
| + ValidateDisplaySetupForCardSet(main_card_set_);
|
| + ValidateDisplaySetupForCardSet(otr_card_set_);
|
| + EXPECT_GT([main_card_set_ cardSize].width, 0U);
|
| + EXPECT_GT([main_card_set_ cardSize].height, 0U);
|
| +
|
| + // Incognito should always be right of (or below in landscape) the main set.
|
| + EXPECT_GT([otr_card_set_ layoutAxisPosition],
|
| + [main_card_set_ layoutAxisPosition]);
|
| +}
|
| +
|
| +TEST_F(StackViewControllerTest, IncognitoHandling) {
|
| + EXPECT_FALSE([view_controller_ isCurrentSetIncognito]);
|
| + EXPECT_EQ((CardSet*)otr_card_set_.get(), [view_controller_ inactiveCardSet]);
|
| + [view_controller_ setActiveCardSet:[view_controller_ inactiveCardSet]];
|
| + EXPECT_TRUE([view_controller_ isCurrentSetIncognito]);
|
| + EXPECT_EQ((CardSet*)main_card_set_.get(), [view_controller_ inactiveCardSet]);
|
| + // Incognito should always be right of (or below in landscape) the main set.
|
| + EXPECT_GT([otr_card_set_ layoutAxisPosition],
|
| + [main_card_set_ layoutAxisPosition]);
|
| +}
|
| +
|
| +TEST_F(StackViewControllerTest, ScrollViewContentOffsetRecentering) {
|
| + BOOL is_portrait = UIInterfaceOrientationIsPortrait(
|
| + [UIApplication sharedApplication].statusBarOrientation);
|
| + CGFloat scroll_view_breadth =
|
| + is_portrait ? [[view_controller_ scrollView] contentSize].width
|
| + : [[view_controller_ scrollView] contentSize].height;
|
| + CGFloat content_size =
|
| + is_portrait ? [[view_controller_ scrollView] contentSize].height
|
| + : [[view_controller_ scrollView] contentSize].width;
|
| +
|
| + // Test that recentering occurs after content offset gets set to lower
|
| + // boundary.
|
| + CGPoint newContentOffset = is_portrait ? CGPointMake(scroll_view_breadth, 0)
|
| + : CGPointMake(0, scroll_view_breadth);
|
| + [[view_controller_ scrollView] setContentOffset:newContentOffset];
|
| + [view_controller_ recenterScrollViewIfNecessary];
|
| + CGFloat content_offset =
|
| + is_portrait ? [[view_controller_ scrollView] contentOffset].y
|
| + : [[view_controller_ scrollView] contentOffset].x;
|
| + EXPECT_GT(content_offset, 0);
|
| + EXPECT_LT(content_offset, content_size);
|
| + ValidateDisplaySetupForCardSet(main_card_set_);
|
| + ValidateDisplaySetupForCardSet(otr_card_set_);
|
| +
|
| + // Test that recentering occurs after content offset gets set to upper
|
| + // boundary.
|
| + newContentOffset = is_portrait
|
| + ? CGPointMake(scroll_view_breadth, content_size)
|
| + : CGPointMake(content_size, scroll_view_breadth);
|
| + [[view_controller_ scrollView] setContentOffset:newContentOffset];
|
| + [view_controller_ recenterScrollViewIfNecessary];
|
| + content_offset = is_portrait
|
| + ? [[view_controller_ scrollView] contentOffset].y
|
| + : [[view_controller_ scrollView] contentOffset].x;
|
| + EXPECT_GT(content_offset, 0);
|
| + EXPECT_LT(content_offset, content_size);
|
| + ValidateDisplaySetupForCardSet(main_card_set_);
|
| + ValidateDisplaySetupForCardSet(otr_card_set_);
|
| +}
|
| +
|
| +TEST_F(StackViewControllerTest, TabModelReset) {
|
| + [view_controller_ setOtrTabModel:nil];
|
| + ValidateDisplaySetupForCardSet(main_card_set_);
|
| + ValidateDisplaySetupForCardSet(otr_card_set_);
|
| +}
|
| +
|
| +} // namespace
|
|
|