blob: 207bf131d6aa93ba84dbf038a1c0574f655cc003 [file] [log] [blame]
// Copyright 2014 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 "ios/web/navigation/navigation_manager_impl.h"
#include "base/logging.h"
#import "base/mac/scoped_nsobject.h"
#import "ios/web/navigation/crw_session_controller+private_constructors.h"
#import "ios/web/navigation/navigation_manager_delegate.h"
#include "ios/web/public/test/test_browser_state.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
namespace web {
namespace {
// Stub class for NavigationManagerDelegate.
class TestNavigationManagerDelegate : public NavigationManagerDelegate {
void GoToIndex(int index) override {}
void LoadURLWithParams(const NavigationManager::WebLoadParams&) override {}
void OnNavigationItemsPruned(size_t pruned_item_count) override {}
void OnNavigationItemChanged() override{};
void OnNavigationItemCommitted(const LoadCommittedDetails&) override {}
WebState* GetWebState() override { return nullptr; }
};
} // namespace
// Test fixture for NavigationManagerImpl testing.
class NavigationManagerTest : public PlatformTest {
protected:
NavigationManagerTest()
: manager_(new NavigationManagerImpl(&delegate_, &browser_state_)) {
controller_.reset([[CRWSessionController alloc]
initWithWindowName:nil
openerId:nil
openedByDOM:NO
openerNavigationIndex:0
browserState:&browser_state_]);
manager_->SetSessionController(controller_.get());
}
CRWSessionController* session_controller() { return controller_.get(); }
NavigationManagerImpl* navigation_manager() { return manager_.get(); }
private:
TestBrowserState browser_state_;
TestNavigationManagerDelegate delegate_;
std::unique_ptr<NavigationManagerImpl> manager_;
base::scoped_nsobject<CRWSessionController> controller_;
};
// Tests state of an empty navigation manager.
TEST_F(NavigationManagerTest, EmptyManager) {
EXPECT_EQ(0, navigation_manager()->GetItemCount());
EXPECT_EQ(-1, navigation_manager()->GetCurrentItemIndex());
EXPECT_FALSE(navigation_manager()->GetPreviousItem());
EXPECT_EQ(-1, navigation_manager()->GetCurrentItemIndex());
EXPECT_FALSE(navigation_manager()->GetPendingItem());
EXPECT_EQ(-1, navigation_manager()->GetPendingItemIndex());
EXPECT_EQ(-1, navigation_manager()->GetIndexForOffset(0));
}
// Tests that GetPendingItemIndex() returns -1 if there is no pending entry.
TEST_F(NavigationManagerTest, GetPendingItemIndexWithoutPendingEntry) {
[session_controller() addPendingEntry:GURL("http://www.url.com")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_TYPED
rendererInitiated:NO];
[session_controller() commitPendingEntry];
EXPECT_EQ(-1, navigation_manager()->GetPendingItemIndex());
}
// Tests that GetPendingItemIndex() returns current item index if there is a
// pending entry.
TEST_F(NavigationManagerTest, GetPendingItemIndexWithPendingEntry) {
[session_controller() addPendingEntry:GURL("http://www.url.com")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_TYPED
rendererInitiated:NO];
[session_controller() commitPendingEntry];
[session_controller() addPendingEntry:GURL("http://www.url.com/0")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_TYPED
rendererInitiated:NO];
EXPECT_EQ(0, navigation_manager()->GetPendingItemIndex());
}
// Tests that GetPendingItemIndex() returns same index as was set by
// -[CRWSessionController setPendingEntryIndex:].
TEST_F(NavigationManagerTest, GetPendingItemIndexWithIndexedPendingEntry) {
[session_controller() addPendingEntry:GURL("http://www.url.com")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_TYPED
rendererInitiated:NO];
[session_controller() commitPendingEntry];
[session_controller() addPendingEntry:GURL("http://www.url.com/0")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_TYPED
rendererInitiated:NO];
[session_controller() commitPendingEntry];
EXPECT_EQ(-1, navigation_manager()->GetPendingItemIndex());
[session_controller() setPendingEntryIndex:0];
EXPECT_EQ(0, navigation_manager()->GetPendingItemIndex());
}
// Tests that going back or negative offset is not possible without a committed
// item.
TEST_F(NavigationManagerTest, CanGoBackWithoutCommitedItem) {
EXPECT_FALSE(navigation_manager()->CanGoBack());
EXPECT_FALSE(navigation_manager()->CanGoToOffset(-1));
}
// Tests that going back or negative offset is not possible if there is a
// transient item, but not committed items.
TEST_F(NavigationManagerTest, CanGoBackWithTransientItem) {
[session_controller() addTransientEntryWithURL:GURL("http://www.url.com")];
EXPECT_FALSE(navigation_manager()->CanGoBack());
EXPECT_FALSE(navigation_manager()->CanGoToOffset(-1));
}
// Tests that going back or negative offset is possible if there is a transient
// item and at least one committed item.
TEST_F(NavigationManagerTest, CanGoBackWithTransientItemAndCommittedItem) {
[session_controller() addPendingEntry:GURL("http://www.url.com")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_TYPED
rendererInitiated:NO];
[session_controller() commitPendingEntry];
[session_controller() addTransientEntryWithURL:GURL("http://www.url.com/0")];
EXPECT_TRUE(navigation_manager()->CanGoBack());
EXPECT_TRUE(navigation_manager()->CanGoToOffset(-1));
}
// Tests that going back or negative offset is not possible if there is ony one
// committed item and no transient item.
TEST_F(NavigationManagerTest, CanGoBackWithSingleCommitedItem) {
[session_controller() addPendingEntry:GURL("http://www.url.com")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_TYPED
rendererInitiated:NO];
[session_controller() commitPendingEntry];
EXPECT_FALSE(navigation_manager()->CanGoBack());
EXPECT_FALSE(navigation_manager()->CanGoToOffset(-1));
}
// Tests going back possibility with multiple committed items.
TEST_F(NavigationManagerTest, CanGoBackWithMultipleCommitedItems) {
[session_controller() addPendingEntry:GURL("http://www.url.com")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_TYPED
rendererInitiated:NO];
[session_controller() commitPendingEntry];
[session_controller() addPendingEntry:GURL("http://www.url.com/0")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_TYPED
rendererInitiated:NO];
[session_controller() commitPendingEntry];
[session_controller() addPendingEntry:GURL("http://www.url.com/1")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_TYPED
rendererInitiated:NO];
[session_controller() commitPendingEntry];
EXPECT_TRUE(navigation_manager()->CanGoBack());
EXPECT_TRUE(navigation_manager()->CanGoToOffset(-1));
[session_controller() goToEntryAtIndex:1];
EXPECT_TRUE(navigation_manager()->CanGoBack());
EXPECT_TRUE(navigation_manager()->CanGoToOffset(-1));
[session_controller() goToEntryAtIndex:0];
EXPECT_FALSE(navigation_manager()->CanGoBack());
EXPECT_FALSE(navigation_manager()->CanGoToOffset(-1));
[session_controller() goToEntryAtIndex:1];
EXPECT_TRUE(navigation_manager()->CanGoBack());
EXPECT_TRUE(navigation_manager()->CanGoToOffset(-1));
}
// Tests that going forward or positive offset is not possible if there is a
// pending entry.
TEST_F(NavigationManagerTest, CanGoForwardWithPendingItem) {
[session_controller() addPendingEntry:GURL("http://www.url.com")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_TYPED
rendererInitiated:NO];
[session_controller() commitPendingEntry];
[session_controller() addPendingEntry:GURL("http://www.url.com/0")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_TYPED
rendererInitiated:NO];
[session_controller() commitPendingEntry];
[session_controller() goToEntryAtIndex:0];
[session_controller() addPendingEntry:GURL("http://www.url.com/1")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_TYPED
rendererInitiated:NO];
// Pending entry should not allow going forward.
EXPECT_FALSE(navigation_manager()->CanGoForward());
EXPECT_FALSE(navigation_manager()->CanGoToOffset(1));
}
// Tests that going forward or positive offset is not possible without a
// committed item.
TEST_F(NavigationManagerTest, CanGoForwardWithoutCommitedItem) {
EXPECT_FALSE(navigation_manager()->CanGoForward());
EXPECT_FALSE(navigation_manager()->CanGoToOffset(1));
}
// Tests that going forward or positive offset is not possible if there is ony
// one committed item and no transient item.
TEST_F(NavigationManagerTest, CanGoForwardWithSingleCommitedItem) {
[session_controller() addPendingEntry:GURL("http://www.url.com")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_TYPED
rendererInitiated:NO];
[session_controller() commitPendingEntry];
EXPECT_FALSE(navigation_manager()->CanGoForward());
EXPECT_FALSE(navigation_manager()->CanGoToOffset(1));
}
// Tests going forward possibility with multiple committed items.
TEST_F(NavigationManagerTest, CanGoForwardWithMultipleCommitedEntries) {
[session_controller() addPendingEntry:GURL("http://www.url.com")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_TYPED
rendererInitiated:NO];
[session_controller() commitPendingEntry];
[session_controller() addPendingEntry:GURL("http://www.url.com/0")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_TYPED
rendererInitiated:NO];
[session_controller() commitPendingEntry];
[session_controller() addPendingEntry:GURL("http://www.url.com/1")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_TYPED
rendererInitiated:NO];
[session_controller() commitPendingEntry];
EXPECT_FALSE(navigation_manager()->CanGoForward());
EXPECT_FALSE(navigation_manager()->CanGoToOffset(1));
[session_controller() goToEntryAtIndex:1];
EXPECT_TRUE(navigation_manager()->CanGoForward());
EXPECT_TRUE(navigation_manager()->CanGoToOffset(1));
[session_controller() goToEntryAtIndex:0];
EXPECT_TRUE(navigation_manager()->CanGoForward());
EXPECT_TRUE(navigation_manager()->CanGoToOffset(1));
[session_controller() goToEntryAtIndex:1];
EXPECT_TRUE(navigation_manager()->CanGoForward());
EXPECT_TRUE(navigation_manager()->CanGoToOffset(1));
[session_controller() goToEntryAtIndex:2];
EXPECT_FALSE(navigation_manager()->CanGoForward());
EXPECT_FALSE(navigation_manager()->CanGoToOffset(1));
}
// Tests CanGoToOffset API for positive, negative and zero delta. Tested
// navigation manager will have redirect entries to make sure they are
// appropriately skipped.
TEST_F(NavigationManagerTest, OffsetsWithoutPendingIndex) {
[session_controller() addPendingEntry:GURL("http://www.url.com/0")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_LINK
rendererInitiated:NO];
[session_controller() commitPendingEntry];
[session_controller() addPendingEntry:GURL("http://www.url.com/redirect")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_IS_REDIRECT_MASK
rendererInitiated:NO];
[session_controller() commitPendingEntry];
[session_controller() addPendingEntry:GURL("http://www.url.com/1")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_LINK
rendererInitiated:NO];
[session_controller() commitPendingEntry];
[session_controller() addPendingEntry:GURL("http://www.url.com/2")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_LINK
rendererInitiated:NO];
[session_controller() commitPendingEntry];
[session_controller() addPendingEntry:GURL("http://www.url.com/redirect")
referrer:Referrer()
transition:ui::PAGE_TRANSITION_IS_REDIRECT_MASK
rendererInitiated:NO];
[session_controller() commitPendingEntry];
ASSERT_EQ(5, navigation_manager()->GetItemCount());
ASSERT_EQ(4, navigation_manager()->GetCurrentItemIndex());
// Go to entry at index 1 and test API from that state.
[session_controller() goToEntryAtIndex:1];
ASSERT_EQ(1, navigation_manager()->GetCurrentItemIndex());
ASSERT_EQ(-1, navigation_manager()->GetPendingItemIndex());
EXPECT_FALSE(navigation_manager()->CanGoToOffset(-1));
EXPECT_EQ(-1, navigation_manager()->GetIndexForOffset(-1));
EXPECT_FALSE(navigation_manager()->CanGoToOffset(-2));
EXPECT_EQ(-2, navigation_manager()->GetIndexForOffset(-2));
EXPECT_TRUE(navigation_manager()->CanGoToOffset(1));
EXPECT_EQ(2, navigation_manager()->GetIndexForOffset(1));
EXPECT_TRUE(navigation_manager()->CanGoToOffset(2));
EXPECT_EQ(4, navigation_manager()->GetIndexForOffset(2));
EXPECT_FALSE(navigation_manager()->CanGoToOffset(3));
EXPECT_EQ(5, navigation_manager()->GetIndexForOffset(3));
// Go to entry at index 2 and test API from that state.
[session_controller() goToEntryAtIndex:2];
ASSERT_EQ(2, navigation_manager()->GetCurrentItemIndex());
ASSERT_EQ(-1, navigation_manager()->GetPendingItemIndex());
EXPECT_TRUE(navigation_manager()->CanGoToOffset(-1));
EXPECT_EQ(1, navigation_manager()->GetIndexForOffset(-1));
EXPECT_FALSE(navigation_manager()->CanGoToOffset(-2));
EXPECT_EQ(-1, navigation_manager()->GetIndexForOffset(-2));
EXPECT_TRUE(navigation_manager()->CanGoToOffset(1));
EXPECT_EQ(4, navigation_manager()->GetIndexForOffset(1));
EXPECT_FALSE(navigation_manager()->CanGoToOffset(2));
EXPECT_EQ(5, navigation_manager()->GetIndexForOffset(2));
// Go to entry at index 4 and test API from that state.
[session_controller() goToEntryAtIndex:4];
ASSERT_EQ(4, navigation_manager()->GetCurrentItemIndex());
ASSERT_EQ(-1, navigation_manager()->GetPendingItemIndex());
EXPECT_TRUE(navigation_manager()->CanGoToOffset(-1));
EXPECT_EQ(2, navigation_manager()->GetIndexForOffset(-1));
EXPECT_TRUE(navigation_manager()->CanGoToOffset(-2));
EXPECT_EQ(1, navigation_manager()->GetIndexForOffset(-2));
EXPECT_FALSE(navigation_manager()->CanGoToOffset(1));
EXPECT_EQ(5, navigation_manager()->GetIndexForOffset(1));
EXPECT_FALSE(navigation_manager()->CanGoToOffset(2));
EXPECT_EQ(6, navigation_manager()->GetIndexForOffset(2));
// Test with existing transient entry.
[session_controller() addTransientEntryWithURL:GURL("http://www.url.com")];
ASSERT_EQ(5, navigation_manager()->GetItemCount());
ASSERT_EQ(4, navigation_manager()->GetCurrentItemIndex());
ASSERT_EQ(-1, navigation_manager()->GetPendingItemIndex());
EXPECT_TRUE(navigation_manager()->CanGoToOffset(-1));
EXPECT_EQ(4, navigation_manager()->GetIndexForOffset(-1));
EXPECT_TRUE(navigation_manager()->CanGoToOffset(-2));
EXPECT_EQ(2, navigation_manager()->GetIndexForOffset(-2));
EXPECT_TRUE(navigation_manager()->CanGoToOffset(-3));
EXPECT_EQ(1, navigation_manager()->GetIndexForOffset(-3));
EXPECT_FALSE(navigation_manager()->CanGoToOffset(1));
EXPECT_EQ(5, navigation_manager()->GetIndexForOffset(1));
EXPECT_FALSE(navigation_manager()->CanGoToOffset(2));
EXPECT_EQ(6, navigation_manager()->GetIndexForOffset(2));
// Now test with pending item index.
[session_controller() discardNonCommittedEntries];
// Set pending index to 1 and test API from that state.
[session_controller() setPendingEntryIndex:1];
ASSERT_EQ(4, navigation_manager()->GetCurrentItemIndex());
ASSERT_EQ(1, navigation_manager()->GetPendingItemIndex());
EXPECT_FALSE(navigation_manager()->CanGoToOffset(-1));
EXPECT_EQ(-1, navigation_manager()->GetIndexForOffset(-1));
EXPECT_FALSE(navigation_manager()->CanGoToOffset(-2));
EXPECT_EQ(-2, navigation_manager()->GetIndexForOffset(-2));
EXPECT_TRUE(navigation_manager()->CanGoToOffset(1));
EXPECT_EQ(2, navigation_manager()->GetIndexForOffset(1));
EXPECT_TRUE(navigation_manager()->CanGoToOffset(2));
EXPECT_EQ(4, navigation_manager()->GetIndexForOffset(2));
EXPECT_FALSE(navigation_manager()->CanGoToOffset(3));
EXPECT_EQ(5, navigation_manager()->GetIndexForOffset(3));
// Set pending index to 2 and test API from that state.
[session_controller() setPendingEntryIndex:2];
ASSERT_EQ(4, navigation_manager()->GetCurrentItemIndex());
ASSERT_EQ(2, navigation_manager()->GetPendingItemIndex());
EXPECT_TRUE(navigation_manager()->CanGoToOffset(-1));
EXPECT_EQ(1, navigation_manager()->GetIndexForOffset(-1));
EXPECT_FALSE(navigation_manager()->CanGoToOffset(-2));
EXPECT_EQ(-1, navigation_manager()->GetIndexForOffset(-2));
EXPECT_TRUE(navigation_manager()->CanGoToOffset(1));
EXPECT_EQ(4, navigation_manager()->GetIndexForOffset(1));
EXPECT_FALSE(navigation_manager()->CanGoToOffset(2));
EXPECT_EQ(5, navigation_manager()->GetIndexForOffset(2));
// Set pending index to 4 and committed entry to 1 and test.
[session_controller() goToEntryAtIndex:1];
[session_controller() setPendingEntryIndex:4];
ASSERT_EQ(1, navigation_manager()->GetCurrentItemIndex());
ASSERT_EQ(4, navigation_manager()->GetPendingItemIndex());
EXPECT_TRUE(navigation_manager()->CanGoToOffset(-1));
EXPECT_EQ(2, navigation_manager()->GetIndexForOffset(-1));
EXPECT_TRUE(navigation_manager()->CanGoToOffset(-2));
EXPECT_EQ(1, navigation_manager()->GetIndexForOffset(-2));
EXPECT_FALSE(navigation_manager()->CanGoToOffset(1));
EXPECT_EQ(5, navigation_manager()->GetIndexForOffset(1));
EXPECT_FALSE(navigation_manager()->CanGoToOffset(2));
EXPECT_EQ(6, navigation_manager()->GetIndexForOffset(2));
// Test with existing transient entry.
[session_controller() addTransientEntryWithURL:GURL("http://www.url.com")];
ASSERT_EQ(5, navigation_manager()->GetItemCount());
ASSERT_EQ(1, navigation_manager()->GetCurrentItemIndex());
ASSERT_EQ(4, navigation_manager()->GetPendingItemIndex());
EXPECT_TRUE(navigation_manager()->CanGoToOffset(-1));
EXPECT_EQ(4, navigation_manager()->GetIndexForOffset(-1));
EXPECT_TRUE(navigation_manager()->CanGoToOffset(-2));
EXPECT_EQ(2, navigation_manager()->GetIndexForOffset(-2));
EXPECT_TRUE(navigation_manager()->CanGoToOffset(-3));
EXPECT_EQ(1, navigation_manager()->GetIndexForOffset(-3));
EXPECT_FALSE(navigation_manager()->CanGoToOffset(1));
EXPECT_EQ(5, navigation_manager()->GetIndexForOffset(1));
EXPECT_FALSE(navigation_manager()->CanGoToOffset(2));
EXPECT_EQ(6, navigation_manager()->GetIndexForOffset(2));
}
} // namespace web