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

Unified Diff: ios/chrome/browser/tabs/tab_model_unittest.mm

Issue 2585233003: Upstream Chrome on iOS source code [2/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/tabs/tab_model_unittest.mm
diff --git a/ios/chrome/browser/tabs/tab_model_unittest.mm b/ios/chrome/browser/tabs/tab_model_unittest.mm
new file mode 100644
index 0000000000000000000000000000000000000000..367fbb9b9e22c4498f9ddc5dfe8c614d83ef2db6
--- /dev/null
+++ b/ios/chrome/browser/tabs/tab_model_unittest.mm
@@ -0,0 +1,900 @@
+// 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 <objc/runtime.h>
+
+#include "base/mac/scoped_nsautorelease_pool.h"
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "base/strings/sys_string_conversions.h"
+#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
+#include "ios/chrome/browser/chrome_url_constants.h"
+#include "ios/chrome/browser/infobars/infobar_manager_impl.h"
+#import "ios/chrome/browser/sessions/session_window.h"
+#import "ios/chrome/browser/sessions/test_session_service.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"
+#import "ios/chrome/browser/tabs/tab_private.h"
+#import "ios/chrome/browser/web/chrome_web_client.h"
+#import "ios/web/navigation/crw_session_controller.h"
+#import "ios/web/navigation/navigation_manager_impl.h"
+#import "ios/web/public/navigation_manager.h"
+#include "ios/web/public/referrer.h"
+#include "ios/web/public/test/scoped_testing_web_client.h"
+#include "ios/web/public/test/test_web_thread_bundle.h"
+#include "ios/web/public/web_thread.h"
+#import "ios/web/web_state/ui/crw_web_controller.h"
+#import "ios/web/web_state/web_state_impl.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"
+#include "third_party/ocmock/gtest_support.h"
+
+using web::WebStateImpl;
+
+// For some of the unit tests, we need to make sure the session is saved
+// immediately so we can read it back in to verify various attributes. This
+// is not a situation we normally expect to be in because we never
+// want the session being saved on the main thread in the production app.
+// We could expose this as part of the service's public API, but again that
+// might encourage use where we don't want it. As a result, just use the
+// known private-for-testing method directly.
+@interface SessionServiceIOS (Testing)
+- (void)performSaveWindow:(SessionWindowIOS*)window
+ toDirectory:(NSString*)directory;
+@end
+
+// Trivial objective C class whose unique aim is to be a wrapper of C++
+// classes.
+@interface ClassesWrapper : NSObject {
+ @public
+ std::unique_ptr<WebStateImpl> _webStateImpl;
+}
+@end
+
+@implementation ClassesWrapper
+@end
+
+@interface TabTest : Tab
+
+- (instancetype)initWithWindowName:(NSString*)windowName
+ lastVisitedTimestamp:(double)lastVisitedTimestamp
+ browserState:(ios::ChromeBrowserState*)browserState
+ tabModel:(TabModel*)tabModel;
+@end
+
+@implementation TabTest
+
+- (instancetype)initWithWindowName:(NSString*)windowName
+ lastVisitedTimestamp:(double)lastVisitedTimestamp
+ browserState:(ios::ChromeBrowserState*)browserState
+ tabModel:(TabModel*)tabModel {
+ self = [super initWithWindowName:windowName
+ opener:nil
+ openedByDOM:NO
+ model:tabModel
+ browserState:browserState];
+ if (self) {
+ id webControllerMock =
+ [OCMockObject niceMockForClass:[CRWWebController class]];
+
+ std::unique_ptr<WebStateImpl> webStateImpl(new WebStateImpl(browserState));
+ webStateImpl->SetWebController(webControllerMock);
+ webStateImpl->GetNavigationManagerImpl().InitializeSession(
+ windowName, @"opener", NO, -1);
+ [webStateImpl->GetNavigationManagerImpl().GetSessionController()
+ setLastVisitedTimestamp:lastVisitedTimestamp];
+
+ WebStateImpl* webStateImplPtr = webStateImpl.get();
+ [[[webControllerMock stub] andReturnValue:OCMOCK_VALUE(webStateImplPtr)]
+ webStateImpl];
+ BOOL yes = YES;
+ [[[webControllerMock stub] andReturnValue:OCMOCK_VALUE(yes)] isViewAlive];
+
+ [self replaceWebStateImpl:std::move(webStateImpl)];
+ }
+ return self;
+}
+
+@end
+
+@interface TabModel (VisibleForTesting)
+- (SessionWindowIOS*)windowForSavingSession;
+@end
+
+// Defines a TabModelObserver for use in unittests. This class can be used to
+// test if an observer method was called or not.
+@interface TabModelObserverPong : NSObject<TabModelObserver> {
+ // TODO(crbug.com/661989): Add tests for the other observer methods.
+ BOOL tabMovedWasCalled_;
+}
+@property(nonatomic, assign) BOOL tabMovedWasCalled;
+@end
+
+@implementation TabModelObserverPong
+@synthesize tabMovedWasCalled = tabMovedWasCalled_;
+
+- (void)tabModel:(TabModel*)model
+ didMoveTab:(Tab*)tab
+ fromIndex:(NSUInteger)fromIndex
+ toIndex:(NSUInteger)toIndex {
+ tabMovedWasCalled_ = YES;
+}
+
+@end
+
+namespace {
+
+const GURL kURL("https://www.some.url.com");
+const web::Referrer kEmptyReferrer;
+const web::Referrer kReferrer(GURL("https//www.some.referer.com"),
+ web::ReferrerPolicyDefault);
+const web::Referrer kReferrer2(GURL("https//www.some.referer2.com"),
+ web::ReferrerPolicyDefault);
+
+class TabModelTest : public PlatformTest {
+ public:
+ TabModelTest() : web_client_(base::MakeUnique<ChromeWebClient>()) {}
+
+ protected:
+ void SetUp() override {
+ DCHECK_CURRENTLY_ON(web::WebThread::UI);
+ PlatformTest::SetUp();
+
+ TestChromeBrowserState::Builder test_cbs_builder;
+ chrome_browser_state_ = test_cbs_builder.Build();
+
+ sessionWindow_.reset([[SessionWindowIOS new] retain]);
+ // Create tab model with just a dummy session service so the async state
+ // saving doesn't trigger unless actually wanted.
+ base::scoped_nsobject<TestSessionService> test_service(
+ [[TestSessionService alloc] init]);
+ tabModel_.reset([[TabModel alloc]
+ initWithSessionWindow:sessionWindow_.get()
+ sessionService:test_service
+ browserState:chrome_browser_state_.get()]);
+ [tabModel_ setWebUsageEnabled:YES];
+ [tabModel_ setPrimary:YES];
+ tabModelObserver_.reset([[TabModelObserverPong alloc] init]);
+ [tabModel_ addObserver:tabModelObserver_];
+ }
+
+ void TearDown() override {
+ [tabModel_ removeObserver:tabModelObserver_];
+ [tabModel_ browserStateDestroyed];
+ PlatformTest::TearDown();
+ }
+
+ Tab* CreateTab(NSString* windowName,
+ double lastVisitedTimestamp) NS_RETURNS_RETAINED {
+ return [[TabTest alloc] initWithWindowName:windowName
+ lastVisitedTimestamp:lastVisitedTimestamp
+ browserState:chrome_browser_state_.get()
+ tabModel:tabModel_.get()];
+ }
+
+ std::unique_ptr<WebStateImpl> CreateWebState(NSString* windowName,
+ NSString* opener,
+ NSInteger index) {
+ std::unique_ptr<WebStateImpl> webState(
+ new WebStateImpl(chrome_browser_state_.get()));
+ webState->GetNavigationManagerImpl().InitializeSession(windowName, opener,
+ NO, index);
+ return webState;
+ }
+
+ std::unique_ptr<WebStateImpl> CreateWebState(NSString* windowName) {
+ return CreateWebState(windowName, @"", -1);
+ }
+
+ std::unique_ptr<WebStateImpl> CreateChildWebState(Tab* parent) {
+ return CreateWebState([parent windowName], [parent currentSessionID], -1);
+ }
+
+ void RestoreSession(SessionWindowIOS* window) {
+ [tabModel_ restoreSessionWindow:window];
+ }
+
+ // Creates a session window with |entries| entries and a |selectedIndex| of 1.
+ SessionWindowIOS* CreateSessionWindow(int entries) {
+ SessionWindowIOS* window = [[SessionWindowIOS alloc] init];
+ for (int i = 0; i < entries; i++) {
+ NSString* windowName = [NSString stringWithFormat:@"window %d", i + 1];
+ [window addSession:CreateWebState(windowName)];
+ }
+ if (entries)
+ [window setSelectedIndex:1];
+ return window;
+ }
+
+ web::TestWebThreadBundle thread_bundle_;
+ web::ScopedTestingWebClient web_client_;
+ base::scoped_nsobject<SessionWindowIOS> sessionWindow_;
+ std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
+ base::scoped_nsobject<TabModel> tabModel_;
+ base::scoped_nsobject<TabModelObserverPong> tabModelObserver_;
+ base::mac::ScopedNSAutoreleasePool pool_;
+};
+
+TEST_F(TabModelTest, IsStoredAsUserData) {
+ EXPECT_EQ(tabModel_,
+ [TabModel tabModelForBrowserState:chrome_browser_state_.get()]);
+ [tabModel_ browserStateDestroyed];
+ EXPECT_EQ(nil,
+ [TabModel tabModelForBrowserState:chrome_browser_state_.get()]);
+ // Verify that a null browser state doesn't break +tabModelForBrowserState.
+ EXPECT_EQ(nil, [TabModel tabModelForBrowserState:nullptr]);
+}
+
+TEST_F(TabModelTest, IsEmpty) {
+ EXPECT_EQ([tabModel_ count], 0U);
+ EXPECT_TRUE([tabModel_ isEmpty]);
+ [tabModel_ insertTabWithURL:kURL
+ referrer:kReferrer
+ windowName:@"window 1"
+ opener:nil
+ atIndex:0];
+ ASSERT_EQ(1U, [tabModel_ count]);
+ EXPECT_FALSE([tabModel_ isEmpty]);
+}
+
+TEST_F(TabModelTest, InsertUrlSingle) {
+ [tabModel_ insertTabWithURL:kURL
+ referrer:kReferrer
+ windowName:@"window 1"
+ opener:nil
+ atIndex:0];
+ ASSERT_EQ(1U, [tabModel_ count]);
+ EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:0] windowName]);
+}
+
+TEST_F(TabModelTest, InsertUrlMultiple) {
+ [tabModel_ insertTabWithURL:kURL
+ referrer:kReferrer
+ windowName:@"window 1"
+ opener:nil
+ atIndex:0];
+ [tabModel_ insertTabWithURL:kURL
+ referrer:kReferrer
+ windowName:@"window 2"
+ opener:nil
+ atIndex:0];
+ [tabModel_ insertTabWithURL:kURL
+ referrer:kReferrer
+ windowName:@"window 3"
+ opener:nil
+ atIndex:1];
+
+ ASSERT_EQ(3U, [tabModel_ count]);
+ EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:0] windowName]);
+ EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:1] windowName]);
+ EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:2] windowName]);
+}
+
+TEST_F(TabModelTest, AppendUrlSingle) {
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
+ ASSERT_EQ(1U, [tabModel_ count]);
+ EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:0] windowName]);
+}
+
+TEST_F(TabModelTest, AppendUrlMultiple) {
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
+
+ ASSERT_EQ(3U, [tabModel_ count]);
+ EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:0] windowName]);
+ EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:1] windowName]);
+ EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:2] windowName]);
+}
+
+TEST_F(TabModelTest, CloseTabAtIndexBeginning) {
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
+
+ [tabModel_ closeTabAtIndex:0];
+
+ ASSERT_EQ(2U, [tabModel_ count]);
+ EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:0] windowName]);
+ EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:1] windowName]);
+}
+
+TEST_F(TabModelTest, CloseTabAtIndexMiddle) {
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
+
+ [tabModel_ closeTabAtIndex:1];
+
+ ASSERT_EQ(2U, [tabModel_ count]);
+ EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:0] windowName]);
+ EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:1] windowName]);
+}
+
+TEST_F(TabModelTest, CloseTabAtIndexLast) {
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
+
+ [tabModel_ closeTabAtIndex:2];
+
+ ASSERT_EQ(2U, [tabModel_ count]);
+ EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:0] windowName]);
+ EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:1] windowName]);
+}
+
+TEST_F(TabModelTest, CloseTabAtIndexOnlyOne) {
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
+
+ [tabModel_ closeTabAtIndex:0];
+
+ EXPECT_EQ(0U, [tabModel_ count]);
+}
+
+TEST_F(TabModelTest, RestoreSessionOnNTPTest) {
+ [tabModel_ insertTabWithURL:GURL(kChromeUINewTabURL)
+ referrer:kEmptyReferrer
+ windowName:@"old window"
+ opener:nil
+ atIndex:0];
+ base::scoped_nsobject<SessionWindowIOS> window(CreateSessionWindow(3));
+
+ RestoreSession(window.get());
+ ASSERT_EQ(3U, [tabModel_ count]);
+ EXPECT_NSEQ(@"window 2", [[tabModel_ currentTab] windowName]);
+ EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:0] windowName]);
+ EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:1] windowName]);
+ EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:2] windowName]);
+}
+
+TEST_F(TabModelTest, RestoreSessionOn2NtpTest) {
+ [tabModel_ insertTabWithURL:GURL(kChromeUINewTabURL)
+ referrer:kEmptyReferrer
+ windowName:@"old window 1"
+ opener:nil
+ atIndex:0];
+ [tabModel_ insertTabWithURL:GURL(kChromeUINewTabURL)
+ referrer:kEmptyReferrer
+ windowName:@"old window 2"
+ opener:nil
+ atIndex:1];
+ base::scoped_nsobject<SessionWindowIOS> window(CreateSessionWindow(3));
+
+ RestoreSession(window.get());
+ ASSERT_EQ(5U, [tabModel_ count]);
+ EXPECT_NSEQ(@"window 2", [[tabModel_ currentTab] windowName]);
+ EXPECT_NSEQ(@"old window 1", [[tabModel_ tabAtIndex:0] windowName]);
+ EXPECT_NSEQ(@"old window 2", [[tabModel_ tabAtIndex:1] windowName]);
+ EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:2] windowName]);
+ EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:3] windowName]);
+ EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:4] windowName]);
+}
+
+TEST_F(TabModelTest, RestoreSessionOnAnyTest) {
+ [tabModel_ insertTabWithURL:kURL
+ referrer:kEmptyReferrer
+ windowName:@"old window 1"
+ opener:nil
+ atIndex:0];
+ base::scoped_nsobject<SessionWindowIOS> window(CreateSessionWindow(3));
+
+ RestoreSession(window.get());
+ ASSERT_EQ(4U, [tabModel_ count]);
+ EXPECT_NSEQ(@"window 2", [[tabModel_ currentTab] windowName]);
+ EXPECT_NSEQ(@"old window 1", [[tabModel_ tabAtIndex:0] windowName]);
+ EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:1] windowName]);
+ EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:2] windowName]);
+ EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:3] windowName]);
+}
+
+TEST_F(TabModelTest, TabForWindowName) {
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
+ [tabModel_ addTabWithURL:GURL("https://www.some.url2.com")
+ referrer:kReferrer2
+ windowName:@"window 2"];
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
+
+ Tab* tab = [tabModel_ tabWithWindowName:@"window 2"];
+
+ EXPECT_NSEQ([tab windowName], @"window 2");
+ EXPECT_EQ(tab.url, GURL("https://www.some.url2.com/"));
+}
+
+TEST_F(TabModelTest, TabForWindowNameNotFound) {
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
+ [tabModel_ addTabWithURL:GURL("https://www.some.url2.com")
+ referrer:kReferrer2
+ windowName:@"window 2"];
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
+
+ Tab* tab = [tabModel_ tabWithWindowName:@"window not found"];
+
+ EXPECT_EQ(nil, tab);
+}
+
+TEST_F(TabModelTest, CloseAllTabs) {
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
+ [tabModel_ addTabWithURL:GURL("https://www.some.url2.com")
+ referrer:kReferrer2
+ windowName:@"window 2"];
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
+
+ [tabModel_ closeAllTabs];
+
+ EXPECT_EQ(0U, [tabModel_ count]);
+}
+
+TEST_F(TabModelTest, CloseAllTabsWithNoTabs) {
+ [tabModel_ closeAllTabs];
+
+ EXPECT_EQ(0U, [tabModel_ count]);
+}
+
+TEST_F(TabModelTest, InsertWithSessionController) {
+ EXPECT_EQ([tabModel_ count], 0U);
+ EXPECT_TRUE([tabModel_ isEmpty]);
+
+ Tab* new_tab =
+ [tabModel_ insertTabWithWebState:CreateWebState(@"window", @"opener", -1)
+ atIndex:0];
+ EXPECT_EQ([tabModel_ count], 1U);
+ [tabModel_ setCurrentTab:new_tab];
+ Tab* current_tab = [tabModel_ currentTab];
+ EXPECT_TRUE(current_tab);
+}
+
+TEST_F(TabModelTest, OpenerOfTab) {
+ // Start off with a couple tabs.
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+
+ // Create parent tab.
+ Tab* parent_tab = [tabModel_ insertTabWithWebState:CreateWebState(@"window")
+ atIndex:[tabModel_ count]];
+ // Create child tab.
+ Tab* child_tab =
+ [tabModel_ insertTabWithWebState:CreateChildWebState(parent_tab)
+ atIndex:[tabModel_ count]];
+ // Create another unrelated tab.
+ Tab* another_tab = [tabModel_ insertTabWithWebState:CreateWebState(@"window")
+ atIndex:[tabModel_ count]];
+
+ // Create another child of the first tab.
+ Tab* child_tab2 =
+ [tabModel_ insertTabWithWebState:CreateChildWebState(parent_tab)
+ atIndex:[tabModel_ count]];
+
+ EXPECT_FALSE([tabModel_ openerOfTab:parent_tab]);
+ EXPECT_FALSE([tabModel_ openerOfTab:another_tab]);
+ EXPECT_EQ(parent_tab, [tabModel_ openerOfTab:child_tab]);
+ EXPECT_EQ(parent_tab, [tabModel_ openerOfTab:child_tab2]);
+}
+
+TEST_F(TabModelTest, OpenerOfTabEmptyModel) {
+ EXPECT_FALSE([tabModel_ openerOfTab:nil]);
+}
+
+TEST_F(TabModelTest, OpenersEmptyModel) {
+ // Empty model.
+ EXPECT_TRUE([tabModel_ isEmpty]);
+ EXPECT_FALSE([tabModel_ nextTabWithOpener:nil afterTab:nil]);
+ EXPECT_FALSE([tabModel_ lastTabWithOpener:nil]);
+ EXPECT_FALSE([tabModel_ firstTabWithOpener:nil]);
+}
+
+TEST_F(TabModelTest, OpenersNothingOpenedGeneral) {
+ // Start with a few tabs.
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+
+ Tab* tab = [tabModel_ insertTabWithWebState:CreateWebState(@"window")
+ atIndex:[tabModel_ count]];
+
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+
+ // All should fail since this hasn't opened anything else.
+ EXPECT_FALSE([tabModel_ nextTabWithOpener:tab afterTab:nil]);
+ EXPECT_FALSE([tabModel_ lastTabWithOpener:tab]);
+ EXPECT_FALSE([tabModel_ firstTabWithOpener:tab]);
+
+ // Add more items to the tab, expect the same results.
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+ EXPECT_FALSE([tabModel_ nextTabWithOpener:tab afterTab:nil]);
+ EXPECT_FALSE([tabModel_ lastTabWithOpener:tab]);
+ EXPECT_FALSE([tabModel_ firstTabWithOpener:tab]);
+}
+
+TEST_F(TabModelTest, OpenersNothingOpenedFirst) {
+ // Our tab is first.
+ Tab* tab = [tabModel_ insertTabWithWebState:CreateWebState(@"window")
+ atIndex:[tabModel_ count]];
+
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+
+ // All should fail since this hasn't opened anything else.
+ EXPECT_FALSE([tabModel_ nextTabWithOpener:tab afterTab:nil]);
+ EXPECT_FALSE([tabModel_ lastTabWithOpener:tab]);
+ EXPECT_FALSE([tabModel_ firstTabWithOpener:tab]);
+}
+
+TEST_F(TabModelTest, OpenersNothingOpenedLast) {
+ // Our tab is last.
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+ Tab* tab = [tabModel_ insertTabWithWebState:CreateWebState(@"window")
+ atIndex:[tabModel_ count]];
+
+ // All should fail since this hasn't opened anything else.
+ EXPECT_FALSE([tabModel_ nextTabWithOpener:tab afterTab:nil]);
+ EXPECT_FALSE([tabModel_ lastTabWithOpener:tab]);
+ EXPECT_FALSE([tabModel_ firstTabWithOpener:tab]);
+}
+
+TEST_F(TabModelTest, OpenersChildTabBeforeOpener) {
+ Tab* parent_tab = [tabModel_ insertTabWithWebState:CreateWebState(@"window")
+ atIndex:[tabModel_ count]];
+ // Insert child at start
+ Tab* child_tab =
+ [tabModel_ insertTabWithWebState:CreateChildWebState(parent_tab)
+ atIndex:0];
+
+ // Insert a few more between them.
+ [tabModel_ insertTabWithWebState:CreateWebState(@"window") atIndex:1];
+ [tabModel_ insertTabWithWebState:CreateWebState(@"window") atIndex:1];
+
+ EXPECT_FALSE([tabModel_ nextTabWithOpener:parent_tab afterTab:nil]);
+ EXPECT_FALSE([tabModel_ lastTabWithOpener:parent_tab]);
+ EXPECT_EQ([tabModel_ firstTabWithOpener:parent_tab], child_tab);
+}
+
+TEST_F(TabModelTest, OpenersChildTabAfterOpener) {
+ Tab* parent_tab = [tabModel_ insertTabWithWebState:CreateWebState(@"window")
+ atIndex:[tabModel_ count]];
+
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+ // Insert two children at end.
+ Tab* child_tab1 =
+ [tabModel_ insertTabWithWebState:CreateChildWebState(parent_tab)
+ atIndex:[tabModel_ count]];
+ Tab* child_tab2 =
+ [tabModel_ insertTabWithWebState:CreateChildWebState(parent_tab)
+ atIndex:[tabModel_ count]];
+
+ EXPECT_EQ([tabModel_ nextTabWithOpener:parent_tab afterTab:nil], child_tab1);
+ EXPECT_EQ([tabModel_ nextTabWithOpener:parent_tab afterTab:child_tab1],
+ child_tab2);
+ EXPECT_EQ([tabModel_ lastTabWithOpener:parent_tab], child_tab2);
+ EXPECT_FALSE([tabModel_ firstTabWithOpener:parent_tab]);
+}
+
+TEST_F(TabModelTest, AddWithOrderController) {
+ // Create a few tabs with the controller at the front.
+ Tab* parent =
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+
+ // Add a new tab, it should be added behind the parent.
+ Tab* child = [tabModel_
+ insertOrUpdateTabWithURL:kURL
+ referrer:kEmptyReferrer
+ transition:ui::PAGE_TRANSITION_LINK
+ windowName:nil
+ opener:parent
+ openedByDOM:NO
+ atIndex:TabModelConstants::kTabPositionAutomatically
+ inBackground:NO];
+ EXPECT_EQ([tabModel_ indexOfTab:parent], 0U);
+ EXPECT_EQ([tabModel_ indexOfTab:child], 1U);
+
+ // Add another new tab without a parent, should go at the end.
+ Tab* tab = [tabModel_
+ insertOrUpdateTabWithURL:kURL
+ referrer:kEmptyReferrer
+ transition:ui::PAGE_TRANSITION_LINK
+ windowName:nil
+ opener:nil
+ openedByDOM:NO
+ atIndex:TabModelConstants::kTabPositionAutomatically
+ inBackground:NO];
+ EXPECT_EQ([tabModel_ indexOfTab:tab], [tabModel_ count] - 1);
+
+ // Same for a tab that's not opened via a LINK transition.
+ Tab* tab2 = [tabModel_ insertOrUpdateTabWithURL:kURL
+ referrer:kEmptyReferrer
+ transition:ui::PAGE_TRANSITION_TYPED
+ windowName:nil
+ opener:nil
+ openedByDOM:NO
+ atIndex:[tabModel_ count]
+ inBackground:NO];
+ EXPECT_EQ([tabModel_ indexOfTab:tab2], [tabModel_ count] - 1);
+
+ // Add a tab in the background. It should appear behind the opening tab.
+ Tab* tab3 = [tabModel_
+ insertOrUpdateTabWithURL:kURL
+ referrer:kEmptyReferrer
+ transition:ui::PAGE_TRANSITION_LINK
+ windowName:nil
+ opener:tab
+ openedByDOM:NO
+ atIndex:TabModelConstants::kTabPositionAutomatically
+ inBackground:YES];
+ EXPECT_EQ([tabModel_ indexOfTab:tab3], [tabModel_ indexOfTab:tab] + 1);
+
+ // Add another background tab behind the one we just opened.
+ Tab* tab4 = [tabModel_
+ insertOrUpdateTabWithURL:kURL
+ referrer:kEmptyReferrer
+ transition:ui::PAGE_TRANSITION_LINK
+ windowName:nil
+ opener:tab3
+ openedByDOM:NO
+ atIndex:TabModelConstants::kTabPositionAutomatically
+ inBackground:YES];
+ EXPECT_EQ([tabModel_ indexOfTab:tab4], [tabModel_ indexOfTab:tab3] + 1);
+}
+
+TEST_F(TabModelTest, AddWithOrderControllerAndGrouping) {
+ // Create a few tabs with the controller at the front.
+ Tab* parent =
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+ // Force the history to update, as it is used to determine grouping.
+ ASSERT_TRUE([parent navigationManager]);
+ [[parent navigationManager]->GetSessionController() commitPendingEntry];
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+
+ ASSERT_TRUE(chrome_browser_state_->CreateHistoryService(true));
+
+ // Add a new tab, it should be added behind the parent.
+ Tab* child1 = [tabModel_
+ insertOrUpdateTabWithURL:kURL
+ referrer:kEmptyReferrer
+ transition:ui::PAGE_TRANSITION_LINK
+ windowName:nil
+ opener:parent
+ openedByDOM:NO
+ atIndex:TabModelConstants::kTabPositionAutomatically
+ inBackground:NO];
+ EXPECT_EQ([tabModel_ indexOfTab:parent], 0U);
+ EXPECT_EQ([tabModel_ indexOfTab:child1], 1U);
+
+ // Add a second child tab in the background. It should be added behind the
+ // first child.
+ Tab* child2 = [tabModel_
+ insertOrUpdateTabWithURL:kURL
+ referrer:kEmptyReferrer
+ transition:ui::PAGE_TRANSITION_LINK
+ windowName:nil
+ opener:parent
+ openedByDOM:NO
+ atIndex:TabModelConstants::kTabPositionAutomatically
+ inBackground:YES];
+ EXPECT_EQ([tabModel_ indexOfTab:child2], 2U);
+
+ // Navigate the parent tab to a new URL. It should not change any ordering.
+ web::NavigationManager::WebLoadParams parent_params(
+ GURL("http://www.espn.com"));
+ parent_params.transition_type = ui::PAGE_TRANSITION_TYPED;
+ [[parent webController] loadWithParams:parent_params];
+ ASSERT_TRUE([parent navigationManager]);
+ [[parent navigationManager]->GetSessionController() commitPendingEntry];
+ EXPECT_EQ([tabModel_ indexOfTab:parent], 0U);
+
+ // Add a new tab. It should be added behind the parent. It should not be added
+ // after the previous two children.
+ Tab* child3 = [tabModel_
+ insertOrUpdateTabWithURL:kURL
+ referrer:kEmptyReferrer
+ transition:ui::PAGE_TRANSITION_LINK
+ windowName:nil
+ opener:parent
+ openedByDOM:NO
+ atIndex:TabModelConstants::kTabPositionAutomatically
+ inBackground:NO];
+ EXPECT_EQ([tabModel_ indexOfTab:child3], 1U);
+
+ // Add a fourt child tab in the background. It should be added behind the
+ // third child.
+ Tab* child4 = [tabModel_
+ insertOrUpdateTabWithURL:kURL
+ referrer:kEmptyReferrer
+ transition:ui::PAGE_TRANSITION_LINK
+ windowName:nil
+ opener:parent
+ openedByDOM:NO
+ atIndex:TabModelConstants::kTabPositionAutomatically
+ inBackground:YES];
+ EXPECT_EQ([tabModel_ indexOfTab:child4], 2U);
+
+ // The first two children should have been moved to the right.
+ EXPECT_EQ([tabModel_ indexOfTab:child1], 3U);
+ EXPECT_EQ([tabModel_ indexOfTab:child2], 4U);
+
+ // Now add a non-owned tab and make sure it is added at the end.
+ Tab* nonChild =
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+ EXPECT_EQ([tabModel_ indexOfTab:nonChild], [tabModel_ count] - 1);
+}
+
+TEST_F(TabModelTest, AddWithLinkTransitionAndIndex) {
+ // Create a few tabs with the controller at the front.
+ Tab* parent =
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+ // Force the history to update, as it is used to determine grouping.
+ ASSERT_TRUE([parent navigationManager]);
+ [[parent navigationManager]->GetSessionController() commitPendingEntry];
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+ [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+
+ ASSERT_TRUE(chrome_browser_state_->CreateHistoryService(true));
+
+ // Add a new tab, it should be added before the parent since the index
+ // parameter has been specified with a valid value.
+ Tab* child1 = [tabModel_ insertOrUpdateTabWithURL:kURL
+ referrer:kEmptyReferrer
+ transition:ui::PAGE_TRANSITION_LINK
+ windowName:nil
+ opener:parent
+ openedByDOM:NO
+ atIndex:0
+ inBackground:NO];
+ EXPECT_EQ([tabModel_ indexOfTab:parent], 1U);
+ EXPECT_EQ([tabModel_ indexOfTab:child1], 0U);
+
+ // Add a new tab, it should be added at the beginning of the stack because
+ // the index parameter has been specified with a valid value.
+ Tab* child2 = [tabModel_ insertOrUpdateTabWithURL:kURL
+ referrer:kEmptyReferrer
+ transition:ui::PAGE_TRANSITION_LINK
+ windowName:nil
+ opener:parent
+ openedByDOM:NO
+ atIndex:0
+ inBackground:NO];
+ EXPECT_EQ([tabModel_ indexOfTab:parent], 2U);
+ EXPECT_EQ([tabModel_ indexOfTab:child1], 1U);
+ EXPECT_EQ([tabModel_ indexOfTab:child2], 0U);
+
+ // Add a new tab, it should be added at position 1 because the index parameter
+ // has been specified with a valid value.
+ Tab* child3 = [tabModel_ insertOrUpdateTabWithURL:kURL
+ referrer:kEmptyReferrer
+ transition:ui::PAGE_TRANSITION_LINK
+ windowName:nil
+ opener:parent
+ openedByDOM:NO
+ atIndex:1
+ inBackground:NO];
+ EXPECT_EQ([tabModel_ indexOfTab:parent], 3U);
+ EXPECT_EQ([tabModel_ indexOfTab:child1], 2U);
+ EXPECT_EQ([tabModel_ indexOfTab:child3], 1U);
+ EXPECT_EQ([tabModel_ indexOfTab:child2], 0U);
+}
+
+TEST_F(TabModelTest, MoveTabs) {
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
+ [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
+
+ // Basic sanity checks before moving on.
+ ASSERT_EQ(3U, [tabModel_ count]);
+ ASSERT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:0] windowName]);
+ ASSERT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:1] windowName]);
+ ASSERT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:2] windowName]);
+
+ // Move a tab from index 1 to index 0 (move tab left by one).
+ [tabModelObserver_ setTabMovedWasCalled:NO];
+ [tabModel_ moveTab:[tabModel_ tabAtIndex:1] toIndex:0];
+ ASSERT_EQ(3U, [tabModel_ count]);
+ EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:0] windowName]);
+ EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:1] windowName]);
+ EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:2] windowName]);
+ EXPECT_TRUE([tabModelObserver_ tabMovedWasCalled]);
+
+ // Move a tab from index 1 to index 2 (move tab right by one).
+ [tabModelObserver_ setTabMovedWasCalled:NO];
+ [tabModel_ moveTab:[tabModel_ tabAtIndex:1] toIndex:2];
+ ASSERT_EQ(3U, [tabModel_ count]);
+ EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:0] windowName]);
+ EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:1] windowName]);
+ EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:2] windowName]);
+ EXPECT_TRUE([tabModelObserver_ tabMovedWasCalled]);
+
+ // Move a tab from index 0 to index 2 (move tab right by more than one).
+ [tabModelObserver_ setTabMovedWasCalled:NO];
+ [tabModel_ moveTab:[tabModel_ tabAtIndex:0] toIndex:2];
+ ASSERT_EQ(3U, [tabModel_ count]);
+ EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:0] windowName]);
+ EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:1] windowName]);
+ EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:2] windowName]);
+ EXPECT_TRUE([tabModelObserver_ tabMovedWasCalled]);
+
+ // Move a tab from index 2 to index 0 (move tab left by more than one).
+ [tabModelObserver_ setTabMovedWasCalled:NO];
+ [tabModel_ moveTab:[tabModel_ tabAtIndex:2] toIndex:0];
+ ASSERT_EQ(3U, [tabModel_ count]);
+ EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:0] windowName]);
+ EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:1] windowName]);
+ EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:2] windowName]);
+ EXPECT_TRUE([tabModelObserver_ tabMovedWasCalled]);
+
+ // Move a tab from index 2 to index 2 (move tab to the same index).
+ [tabModelObserver_ setTabMovedWasCalled:NO];
+ [tabModel_ moveTab:[tabModel_ tabAtIndex:2] toIndex:2];
+ ASSERT_EQ(3U, [tabModel_ count]);
+ EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:0] windowName]);
+ EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:1] windowName]);
+ EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:2] windowName]);
+ EXPECT_FALSE([tabModelObserver_ tabMovedWasCalled]);
+}
+
+TEST_F(TabModelTest, SetParentModel) {
+ // Create a tab without a parent model and make sure it doesn't crash. Then
+ // set its parent TabModel and make sure that works as well.
+ base::scoped_nsobject<TabTest> tab([[TabTest alloc]
+ initWithWindowName:@"parentless"
+ lastVisitedTimestamp:100
+ browserState:chrome_browser_state_.get()
+ tabModel:nil]);
+ EXPECT_TRUE([tab parentTabModel] == nil);
+ [tabModel_ insertTab:tab atIndex:0];
+ [tab setParentTabModel:tabModel_.get()];
+ EXPECT_FALSE([tab parentTabModel] == nil);
+ [tabModel_ closeTabAtIndex:0];
+}
+
+TEST_F(TabModelTest, PersistSelectionChange) {
+ NSString* stashPath =
+ base::SysUTF8ToNSString(chrome_browser_state_->GetStatePath().value());
+
+ base::scoped_nsobject<TabModel> model([[TabModel alloc]
+ initWithSessionWindow:sessionWindow_.get()
+ sessionService:[SessionServiceIOS sharedService]
+ browserState:chrome_browser_state_.get()]);
+
+ [model addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
+ [model addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
+ [model addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
+
+ ASSERT_EQ(3U, [model count]);
+ model.get().currentTab = [model tabAtIndex:1];
+ // Force state to flush to disk on the main thread so it can be immediately
+ // tested below.
+ SessionWindowIOS* window = [model windowForSavingSession];
+ [[SessionServiceIOS sharedService] performSaveWindow:window
+ toDirectory:stashPath];
+ [model browserStateDestroyed];
+ model.reset();
+ base::RunLoop().RunUntilIdle();
+
+ SessionWindowIOS* sessionWindow = [[SessionServiceIOS sharedService]
+ loadWindowForBrowserState:chrome_browser_state_.get()];
+
+ // Create tab model from saved session.
+ base::scoped_nsobject<TestSessionService> test_service(
+ [[TestSessionService alloc] init]);
+
+ model.reset([[TabModel alloc]
+ initWithSessionWindow:sessionWindow
+ sessionService:test_service
+ browserState:chrome_browser_state_.get()]);
+ EXPECT_EQ(model.get().currentTab, [model tabAtIndex:1]);
+ [model browserStateDestroyed];
+
+ // Clean up.
+ EXPECT_TRUE([[NSFileManager defaultManager] removeItemAtPath:stashPath
+ error:nullptr]);
+}
+
+} // anonymous namespace
« no previous file with comments | « ios/chrome/browser/tabs/tab_model_synced_window_delegate_getter.mm ('k') | ios/chrome/browser/tabs/tab_private.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698