Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Unified Diff: ios/chrome/browser/ui/stack_view/card_set_unittest.mm

Issue 2587023002: Upstream Chrome on iOS source code [8/11]. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ios/chrome/browser/ui/stack_view/card_set_unittest.mm
diff --git a/ios/chrome/browser/ui/stack_view/card_set_unittest.mm b/ios/chrome/browser/ui/stack_view/card_set_unittest.mm
new file mode 100644
index 0000000000000000000000000000000000000000..b347a318d7803ee03f09a00c70174cee665f479a
--- /dev/null
+++ b/ios/chrome/browser/ui/stack_view/card_set_unittest.mm
@@ -0,0 +1,372 @@
+// 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/mac/scoped_nsautorelease_pool.h"
+#include "base/mac/scoped_nsobject.h"
+#include "base/strings/stringprintf.h"
+#import "ios/chrome/browser/tabs/tab.h"
+#import "ios/chrome/browser/tabs/tab_model.h"
+#import "ios/chrome/browser/tabs/tab_model_observer.h"
+#include "ios/chrome/browser/ui/rtl_geometry.h"
+#import "ios/chrome/browser/ui/stack_view/card_set.h"
+#import "ios/chrome/browser/ui/stack_view/card_stack_layout_manager.h"
+#import "ios/chrome/browser/ui/stack_view/stack_card.h"
+#import "ios/testing/ocmock_complex_type_helper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+#import "third_party/ocmock/OCMock/OCMock.h"
+#import "third_party/ocmock/gtest_support.h"
+
+@interface MockTabModel : NSObject<NSFastEnumeration> {
+ @private
+ base::scoped_nsobject<NSMutableArray> tabs_;
+ id<TabModelObserver> observer_; // weak
+}
+
+// Adds a new mock tab with the given properties.
+- (void)addTabWithTitle:(NSString*)title location:(const GURL&)url;
+
+// TabModel mocking.
+- (NSUInteger)count;
+- (BOOL)isOffTheRecord;
+- (Tab*)currentTab;
+- (NSUInteger)indexOfTab:(Tab*)tab;
+- (Tab*)tabAtIndex:(NSUInteger)tabIndex;
+- (void)addObserver:(id<TabModelObserver>)observer;
+- (void)removeObserver:(id<TabModelObserver>)observer;
+- (id<TabModelObserver>)observer;
+@end
+
+@interface CardSetTestTabMock : OCMockComplexTypeHelper
+@end
+@implementation CardSetTestTabMock
+
+typedef const GURL& (^CardSetTestTabMock_url)(void);
+
+- (const GURL&)url {
+ return static_cast<CardSetTestTabMock_url>([self blockForSelector:_cmd])();
+}
+@end
+
+@implementation MockTabModel
+
+- (id)init {
+ if ((self = [super init])) {
+ tabs_.reset([[NSMutableArray alloc] init]);
+ }
+ return self;
+}
+
+- (void)addTabWithTitle:(NSString*)title location:(const GURL&)url {
+ base::scoped_nsobject<id> tab([[CardSetTestTabMock alloc]
+ initWithRepresentedObject:[OCMockObject mockForClass:[Tab class]]]);
+ UIView* dummyView = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
+ static int sCounter = 0;
+ NSString* sessionID = [NSString stringWithFormat:@"%d", sCounter++];
+ BOOL no = NO;
+ [[[tab stub] andReturn:dummyView] view];
+ base::scoped_nsobject<id> block([^{
+ return (const GURL&)url;
+ } copy]);
+ [tab onSelector:@selector(url) callBlockExpectation:block];
+
+ [[tab expect] retrieveSnapshot:[OCMArg any]];
+ [[[tab stub] andReturn:nil] webController];
+ [[[tab stub] andReturn:nil] favicon];
+ [[[tab stub] andReturnValue:OCMOCK_VALUE(no)] canGoBack];
+ [[[tab stub] andReturnValue:OCMOCK_VALUE(no)] canGoForward];
+ [[[tab stub] andReturn:title] title];
+ [[[tab stub] andReturn:sessionID] currentSessionID];
+
+ [tabs_ addObject:tab];
+ [observer_ tabModel:(TabModel*)self
+ didInsertTab:tab
+ atIndex:([tabs_ count] - 1)
+ inForeground:YES];
+}
+
+- (void)removeTabAtIndex:(NSUInteger)index {
+ id tab = [tabs_ objectAtIndex:index];
+ [[tab retain] autorelease];
+ [tabs_ removeObjectAtIndex:index];
+
+ // A tab was removed at the given index.
+ [observer_ tabModel:(TabModel*)self didRemoveTab:tab atIndex:index];
+}
+
+- (NSUInteger)count {
+ return [tabs_ count];
+}
+
+- (BOOL)isOffTheRecord {
+ return NO;
+}
+
+- (Tab*)currentTab {
+ if ([tabs_ count])
+ return [tabs_ objectAtIndex:0];
+ return nil;
+}
+
+- (NSUInteger)indexOfTab:(Tab*)tab {
+ return [tabs_ indexOfObject:tab];
+}
+
+- (Tab*)tabAtIndex:(NSUInteger)tabIndex {
+ return [tabs_ objectAtIndex:tabIndex];
+}
+
+- (void)addObserver:(id<TabModelObserver>)observer {
+ observer_ = observer;
+}
+
+- (void)removeObserver:(id<TabModelObserver>)observer {
+ observer_ = nil;
+}
+
+- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState*)state
+ objects:(id*)stackbuf
+ count:(NSUInteger)len {
+ return [tabs_ countByEnumeratingWithState:state objects:stackbuf count:len];
+}
+
+- (id<TabModelObserver>)observer {
+ return observer_;
+}
+
+@end
+
+#pragma mark -
+
+namespace {
+
+const CGFloat kViewportDimension = 100;
+const CGFloat kCardDimension = 90;
+
+CardStackLayoutManager* CreateMockCardStackLayoutManager() {
+ OCMockObject* stackModelMock =
+ [OCMockObject mockForClass:[CardStackLayoutManager class]];
+ BOOL no = NO;
+ [[[stackModelMock stub] andReturnValue:OCMOCK_VALUE(no)] layoutIsVertical];
+ NSUInteger lastStartStackCardIndex = 0;
+ [[[stackModelMock stub] andReturnValue:OCMOCK_VALUE(lastStartStackCardIndex)]
+ lastStartStackCardIndex];
+ NSArray* cards = @[];
+ [[[stackModelMock stub] andReturn:cards] cards];
+ return (CardStackLayoutManager*)stackModelMock;
+}
+
+class CardSetTest : public PlatformTest {
+ protected:
+ virtual void SetUpWithTabs(int nb_tabs) {
+ tab_model_.reset([[MockTabModel alloc] init]);
+
+ for (int i = 0; i < nb_tabs; ++i) {
+ std::string url = base::StringPrintf("http://%d.example.com", i);
+ [tab_model_ addTabWithTitle:@"NewTab" location:GURL(url)];
+ }
+
+ card_set_.reset(
+ [[CardSet alloc] initWithModel:(TabModel*)tab_model_.get()]);
+
+ display_view_.reset(
+ [[UIView alloc] initWithFrame:CGRectMake(0, 0, kViewportDimension,
+ kViewportDimension)]);
+ // Do some initial configuration of the card set.
+ [card_set_ setDisplayView:display_view_];
+ [card_set_ setCardSize:CGSizeMake(kCardDimension, kCardDimension)];
+ [card_set_ setLayoutAxisPosition:(kViewportDimension / 2.0) isVertical:YES];
+ [card_set_ configureLayoutParametersWithMargin:10];
+ }
+
+ void SetUp() override { SetUpWithTabs(2); }
+
+ base::scoped_nsobject<MockTabModel> tab_model_;
+ base::scoped_nsobject<UIView> display_view_;
+ base::scoped_nsobject<CardSet> card_set_;
+};
+
+TEST_F(CardSetTest, InitialLayoutState) {
+ NSArray* cards = [card_set_ cards];
+ EXPECT_EQ([tab_model_ count], [cards count]);
+
+ // Tabs should be on the trailing side.
+ EXPECT_EQ(CardCloseButtonSide::TRAILING, [card_set_ closeButtonSide]);
+
+ // At least one card should be visible after layout, and cards should have
+ // the right size and center.
+ [card_set_ fanOutCards];
+ BOOL has_visible_card = NO;
+ for (StackCard* card in cards) {
+ if ([card viewIsLive])
+ has_visible_card = YES;
+ EXPECT_FLOAT_EQ(kCardDimension, card.layout.size.width);
+ EXPECT_FLOAT_EQ(kCardDimension, card.layout.size.height);
+ EXPECT_FLOAT_EQ(kViewportDimension / 2.0,
+ CGRectGetMidX(LayoutRectGetRect(card.layout)));
+ }
+ EXPECT_TRUE(has_visible_card);
+}
+
+TEST_F(CardSetTest, HandleRotation) {
+ // Rotate the card set.
+ [card_set_ setLayoutAxisPosition:(kViewportDimension / 3.0) isVertical:NO];
+
+ // Tabs should now be on the leading side.
+ EXPECT_EQ(CardCloseButtonSide::LEADING, [card_set_ closeButtonSide]);
+ // And the centers should be on the new axis.
+ for (StackCard* card in [card_set_ cards]) {
+ EXPECT_FLOAT_EQ(kViewportDimension / 3.0,
+ CGRectGetMidY(LayoutRectGetRect(card.layout)));
+ }
+}
+
+TEST_F(CardSetTest, CurrentCard) {
+ NSUInteger current_tab_index =
+ [tab_model_ indexOfTab:[tab_model_ currentTab]];
+ NSArray* cards = [card_set_ cards];
+ NSUInteger current_card_index = [cards indexOfObject:[card_set_ currentCard]];
+ EXPECT_EQ(current_tab_index, current_card_index);
+}
+
+TEST_F(CardSetTest, ViewClearing) {
+ // Add the views.
+ [card_set_ fanOutCards];
+ ASSERT_GT([[display_view_ subviews] count], 0U);
+ [card_set_ setDisplayView:nil];
+ EXPECT_EQ(0U, [[display_view_ subviews] count]);
+}
+
+TEST_F(CardSetTest, NoticeTabAddition) {
+ NSArray* cards = [card_set_ cards];
+ NSUInteger initial_card_count = [cards count];
+
+ OCMockObject* observer =
+ [OCMockObject mockForProtocol:@protocol(CardSetObserver)];
+ [[observer expect] cardSet:OCMOCK_ANY didAddCard:OCMOCK_ANY];
+ [card_set_ setObserver:(id<CardSetObserver>)observer];
+
+ [tab_model_ addTabWithTitle:@"NewTab"
+ location:GURL("http://www.example.com")];
+ cards = [card_set_ cards];
+ EXPECT_EQ(initial_card_count + 1, [cards count]);
+
+ [card_set_ setObserver:nil];
+ EXPECT_OCMOCK_VERIFY(observer);
+}
+
+TEST_F(CardSetTest, NoticeTabRemoval) {
+ NSArray* cards = [card_set_ cards];
+ NSUInteger initial_card_count = [cards count];
+ StackCard* first_card = [cards objectAtIndex:0];
+
+ OCMockObject* observer =
+ [OCMockObject mockForProtocol:@protocol(CardSetObserver)];
+ [[observer expect] cardSet:OCMOCK_ANY willRemoveCard:OCMOCK_ANY atIndex:0];
+ [[observer expect] cardSet:OCMOCK_ANY didRemoveCard:OCMOCK_ANY atIndex:0];
+
+ [card_set_ setObserver:(id<CardSetObserver>)observer];
+
+ [tab_model_ removeTabAtIndex:0];
+ cards = [card_set_ cards];
+ EXPECT_EQ(initial_card_count - 1, [cards count]);
+ EXPECT_NE(first_card, [cards objectAtIndex:0]);
+
+ [card_set_ setObserver:nil];
+ EXPECT_OCMOCK_VERIFY(observer);
+}
+
+TEST_F(CardSetTest, Preloading) {
+ // Preloading when everything is visible should return NO.
+ [card_set_ fanOutCards];
+ EXPECT_FALSE([card_set_ preloadNextCard]);
+
+ // Add a bunch of cards to ensure stacking.
+ for (int i = 0; i < 20; ++i) {
+ [tab_model_ addTabWithTitle:@"NewTab"
+ location:GURL("http://www.example.com")];
+ }
+ [card_set_ fanOutCards];
+
+ NSUInteger loaded_cards = [[display_view_ subviews] count];
+ // Now preloading should return YES, and should have added one more card to
+ // the view.
+ EXPECT_TRUE([card_set_ preloadNextCard]);
+ EXPECT_EQ(loaded_cards + 1, [[display_view_ subviews] count]);
+}
+
+TEST_F(CardSetTest, stackIsFullyCollapsed) {
+ [card_set_ setStackModelForTesting:CreateMockCardStackLayoutManager()];
+ OCMockObject* stack_model_mock = (OCMockObject*)[card_set_ stackModel];
+ [[stack_model_mock expect] stackIsFullyCollapsed];
+ [card_set_ stackIsFullyCollapsed];
+ EXPECT_OCMOCK_VERIFY(stack_model_mock);
+}
+
+TEST_F(CardSetTest, stackIsFullyFannedOut) {
+ [card_set_ setStackModelForTesting:CreateMockCardStackLayoutManager()];
+ OCMockObject* stack_model_mock = (OCMockObject*)[card_set_ stackModel];
+ [[stack_model_mock expect] stackIsFullyFannedOut];
+ [card_set_ stackIsFullyFannedOut];
+ EXPECT_OCMOCK_VERIFY(stack_model_mock);
+}
+
+TEST_F(CardSetTest, stackIsFullyOverextended) {
+ [card_set_ setStackModelForTesting:CreateMockCardStackLayoutManager()];
+ OCMockObject* stack_model_mock = (OCMockObject*)[card_set_ stackModel];
+ [[stack_model_mock expect] stackIsFullyOverextended];
+ [card_set_ stackIsFullyOverextended];
+ EXPECT_OCMOCK_VERIFY(stack_model_mock);
+}
+
+TEST_F(CardSetTest, isCardInStartStaggerRegion) {
+ [card_set_ fanOutCards];
+ NSArray* cards = [card_set_ cards];
+ // First card should not be collapsed into start stagger region when stack is
+ // fanned out from the first card.
+ StackCard* first_card = [cards objectAtIndex:0];
+ EXPECT_FALSE([card_set_ isCardInStartStaggerRegion:first_card]);
+ // Add a bunch of cards to ensure stacking, and fan them out so that there
+ // is a start stack.
+ for (int i = 0; i < 20; ++i) {
+ [tab_model_ addTabWithTitle:@"NewTab"
+ location:GURL("http://www.example.com")];
+ }
+ [card_set_ fanOutCardsWithStartIndex:10];
+ // First card should now be collapsed into start stagger region.
+ EXPECT_TRUE([card_set_ isCardInStartStaggerRegion:first_card]);
+}
+
+TEST_F(CardSetTest, isCardInEndStaggerRegion) {
+ [card_set_ fanOutCards];
+ NSArray* cards = [card_set_ cards];
+ // Add a bunch of cards to ensure stacking, and fan them out so that there
+ // is an end stack.
+ for (int i = 0; i < 20; ++i) {
+ [tab_model_ addTabWithTitle:@"NewTab"
+ location:GURL("http://www.example.com")];
+ }
+ StackCard* last_card = [cards objectAtIndex:[cards count] - 1];
+ [card_set_ fanOutCards];
+ // Last card should be collapsed into end region.
+ EXPECT_TRUE([card_set_ isCardInEndStaggerRegion:last_card]);
+
+ // Fan out cards from the last card.
+ [card_set_ fanOutCardsWithStartIndex:[cards count] - 1];
+ // Last card should not be collapsed into end region.
+ EXPECT_FALSE([card_set_ isCardInEndStaggerRegion:last_card]);
+}
+
+TEST_F(CardSetTest, setTabModel) {
+ SetUpWithTabs(0);
+ [card_set_ setTabModel:nil];
+ EXPECT_TRUE([tab_model_ observer] == nil);
+ [card_set_ setTabModel:static_cast<id>(tab_model_)];
+ EXPECT_NSEQ(card_set_, static_cast<id>([tab_model_ observer]));
+}
+
+} // namespace
« no previous file with comments | « ios/chrome/browser/ui/stack_view/card_set.mm ('k') | ios/chrome/browser/ui/stack_view/card_stack_layout_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698