blob: 243f223c7f4e864bfac23c24a997674ede6cd894 [file] [log] [blame]
// Copyright 2017 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/chrome/browser/ui/toolbar/clean/toolbar_mediator.h"
#include <memory>
#include "base/strings/sys_string_conversions.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/browser/bookmark_node.h"
#include "components/bookmarks/test/bookmark_test_helpers.h"
#include "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
#import "ios/chrome/browser/ui/toolbar/clean/toolbar_consumer.h"
#import "ios/chrome/browser/ui/toolbar/test/toolbar_test_navigation_manager.h"
#import "ios/chrome/browser/ui/toolbar/test/toolbar_test_web_state.h"
#include "ios/chrome/browser/web_state_list/fake_web_state_list_delegate.h"
#include "ios/chrome/browser/web_state_list/web_state_list.h"
#import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h"
#import "ios/chrome/browser/web_state_list/web_state_opener.h"
#import "ios/public/provider/chrome/browser/voice/voice_search_provider.h"
#import "ios/web/public/test/fakes/fake_navigation_context.h"
#import "ios/web/public/test/fakes/test_navigation_manager.h"
#import "ios/web/public/test/fakes/test_web_state.h"
#include "ios/web/public/test/test_web_thread_bundle.h"
#import "ios/web/public/web_state/web_state_observer_bridge.h"
#include "testing/platform_test.h"
#import "third_party/ocmock/OCMock/OCMock.h"
#include "third_party/ocmock/gtest_support.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
using bookmarks::BookmarkNode;
using bookmarks::BookmarkModel;
namespace {
class MockEnabledVoiceSearchProvider : public VoiceSearchProvider {
bool IsVoiceSearchEnabled() const override { return true; }
};
}
@interface TestToolbarMediator
: ToolbarMediator<CRWWebStateObserver, WebStateListObserving>
@end
@implementation TestToolbarMediator
@end
namespace {
static const int kNumberOfWebStates = 3;
static const char kTestUrl[] = "http://www.chromium.org";
static const char kTestUrl2[] = "http://www.notChromium.org";
class ToolbarMediatorTest : public PlatformTest {
public:
ToolbarMediatorTest() {
TestChromeBrowserState::Builder test_cbs_builder;
chrome_browser_state_ = test_cbs_builder.Build();
chrome_browser_state_->CreateBookmarkModel(false);
bookmark_model_ = ios::BookmarkModelFactory::GetForBrowserState(
chrome_browser_state_.get());
bookmarks::test::WaitForBookmarkModelToLoad(bookmark_model_);
std::unique_ptr<ToolbarTestNavigationManager> navigation_manager =
std::make_unique<ToolbarTestNavigationManager>();
navigation_manager_ = navigation_manager.get();
test_web_state_ = std::make_unique<ToolbarTestWebState>();
test_web_state_->SetNavigationManager(std::move(navigation_manager));
test_web_state_->SetLoading(true);
web_state_ = test_web_state_.get();
mediator_ = [[TestToolbarMediator alloc] init];
consumer_ = OCMProtocolMock(@protocol(ToolbarConsumer));
strict_consumer_ = OCMStrictProtocolMock(@protocol(ToolbarConsumer));
SetUpWebStateList();
}
// Explicitly disconnect the mediator so there won't be any WebStateList
// observers when web_state_list_ gets dealloc.
~ToolbarMediatorTest() override { [mediator_ disconnect]; }
protected:
web::TestWebThreadBundle thread_bundle_;
void SetUpWebStateList() {
web_state_list_ = std::make_unique<WebStateList>(&web_state_list_delegate_);
web_state_list_->InsertWebState(0, std::move(test_web_state_),
WebStateList::INSERT_FORCE_INDEX,
WebStateOpener());
for (int i = 1; i < kNumberOfWebStates; i++) {
InsertNewWebState(i);
}
}
void SetUpBookmarks() {
bookmark_model_ = ios::BookmarkModelFactory::GetForBrowserState(
chrome_browser_state_.get());
GURL URL = GURL(kTestUrl);
const BookmarkNode* defaultFolder = bookmark_model_->mobile_node();
bookmark_model_->AddURL(defaultFolder, defaultFolder->child_count(),
base::SysNSStringToUTF16(@"Test bookmark 1"), URL);
}
void InsertNewWebState(int index) {
auto web_state = std::make_unique<web::TestWebState>();
GURL url("http://test/" + std::to_string(index));
web_state->SetCurrentURL(url);
web_state_list_->InsertWebState(index, std::move(web_state),
WebStateList::INSERT_FORCE_INDEX,
WebStateOpener());
}
void SetUpActiveWebState() { web_state_list_->ActivateWebStateAt(0); }
TestToolbarMediator* mediator_;
ToolbarTestWebState* web_state_;
ToolbarTestNavigationManager* navigation_manager_;
std::unique_ptr<WebStateList> web_state_list_;
FakeWebStateListDelegate web_state_list_delegate_;
id consumer_;
id strict_consumer_;
std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
BookmarkModel* bookmark_model_;
private:
std::unique_ptr<ToolbarTestWebState> test_web_state_;
};
// Test that the consumer bookmarks status is only updated when the page is
// added to the bookmark model.
TEST_F(ToolbarMediatorTest, TestToolbarAddedToBookmarks) {
web_state_->SetCurrentURL(GURL(kTestUrl));
mediator_.webStateList = web_state_list_.get();
SetUpActiveWebState();
mediator_.consumer = consumer_;
mediator_.bookmarkModel = bookmark_model_;
// Add a different bookmark and verify it is not set as bookmarked.
OCMExpect([consumer_ setPageBookmarked:NO]);
bookmark_model_ = ios::BookmarkModelFactory::GetForBrowserState(
chrome_browser_state_.get());
GURL URL = GURL(kTestUrl2);
const BookmarkNode* defaultFolder = bookmark_model_->mobile_node();
bookmark_model_->AddURL(defaultFolder, defaultFolder->child_count(),
base::SysNSStringToUTF16(@"Test bookmark 1"), URL);
EXPECT_OCMOCK_VERIFY(consumer_);
// Bookmark the page and check it is set.
OCMExpect([consumer_ setPageBookmarked:YES]);
bookmark_model_ = ios::BookmarkModelFactory::GetForBrowserState(
chrome_browser_state_.get());
URL = GURL(kTestUrl);
bookmark_model_->AddURL(defaultFolder, defaultFolder->child_count(),
base::SysNSStringToUTF16(@"Test bookmark 2"), URL);
EXPECT_OCMOCK_VERIFY(consumer_);
bookmark_model_->RemoveAllUserBookmarks();
}
// Test that the consumer bookmarks status is only updated when the page is
// removed from the bookmark model.
TEST_F(ToolbarMediatorTest, TestToolbarRemovedFromBookmarks) {
SetUpBookmarks();
bookmark_model_ = ios::BookmarkModelFactory::GetForBrowserState(
chrome_browser_state_.get());
GURL URL = GURL(kTestUrl2);
const BookmarkNode* defaultFolder = bookmark_model_->mobile_node();
bookmark_model_->AddURL(defaultFolder, defaultFolder->child_count(),
base::SysNSStringToUTF16(@"Test bookmark 1"), URL);
web_state_->SetCurrentURL(GURL(kTestUrl));
mediator_.webStateList = web_state_list_.get();
SetUpActiveWebState();
mediator_.consumer = consumer_;
mediator_.bookmarkModel = bookmark_model_;
// Removes another bookmark and check it is still bookmarked.
OCMExpect([consumer_ setPageBookmarked:YES]);
std::vector<const BookmarkNode*> vec;
bookmark_model_->GetNodesByURL(GURL(kTestUrl2), &vec);
bookmark_model_->Remove(vec.front());
EXPECT_OCMOCK_VERIFY(consumer_);
vec.clear();
// Removes the page from the bookmarks and check it is updated.
OCMExpect([consumer_ setPageBookmarked:NO]);
bookmark_model_->GetNodesByURL(GURL(kTestUrl), &vec);
bookmark_model_->Remove(vec.front());
EXPECT_OCMOCK_VERIFY(consumer_);
bookmark_model_->RemoveAllUserBookmarks();
}
// Test that the consumer bookmarks status is updated when the page is
// bookmarked.
TEST_F(ToolbarMediatorTest, TestToolbarBookmarked) {
SetUpBookmarks();
OCMExpect([consumer_ setPageBookmarked:YES]);
web_state_->SetCurrentURL(GURL(kTestUrl));
mediator_.bookmarkModel = bookmark_model_;
mediator_.webStateList = web_state_list_.get();
SetUpActiveWebState();
mediator_.consumer = consumer_;
EXPECT_OCMOCK_VERIFY(consumer_);
bookmark_model_->RemoveAllUserBookmarks();
}
// Test that the consumer bookmarks status is updated when the page is
// bookmarked, when the bookmarkModel is set last.
TEST_F(ToolbarMediatorTest, TestToolbarBookmarkedModelSetLast) {
SetUpBookmarks();
OCMExpect([consumer_ setPageBookmarked:NO]);
OCMExpect([consumer_ setShareMenuEnabled:YES]);
web_state_->SetCurrentURL(GURL(kTestUrl));
mediator_.webStateList = web_state_list_.get();
SetUpActiveWebState();
mediator_.consumer = consumer_;
mediator_.bookmarkModel = bookmark_model_;
EXPECT_OCMOCK_VERIFY(consumer_);
bookmark_model_->RemoveAllUserBookmarks();
}
// Test that the consumer bookmarks status is updated when the page is
// NOT bookmarked.
TEST_F(ToolbarMediatorTest, TestToolbarNotBookmarked) {
SetUpBookmarks();
OCMExpect([consumer_ setPageBookmarked:NO]);
web_state_->SetCurrentURL(GURL(kTestUrl2));
mediator_.bookmarkModel = bookmark_model_;
mediator_.webStateList = web_state_list_.get();
SetUpActiveWebState();
mediator_.consumer = consumer_;
EXPECT_OCMOCK_VERIFY(consumer_);
bookmark_model_->RemoveAllUserBookmarks();
}
// Test no setup is being done on the Toolbar if there's no Webstate.
TEST_F(ToolbarMediatorTest, TestToolbarSetupWithNoWebstate) {
mediator_.consumer = consumer_;
[[consumer_ reject] setCanGoForward:NO];
[[consumer_ reject] setCanGoBack:NO];
[[consumer_ reject] setLoadingState:YES];
}
// Test no setup is being done on the Toolbar if there's no active Webstate.
TEST_F(ToolbarMediatorTest, TestToolbarSetupWithNoActiveWebstate) {
SetUpBookmarks();
mediator_.webStateList = web_state_list_.get();
mediator_.consumer = consumer_;
mediator_.bookmarkModel = bookmark_model_;
[[consumer_ reject] setCanGoForward:NO];
[[consumer_ reject] setCanGoBack:NO];
[[consumer_ reject] setLoadingState:YES];
[[consumer_ reject] setPageBookmarked:NO];
}
// Test no WebstateList related setup is being done on the Toolbar if there's no
// WebstateList.
TEST_F(ToolbarMediatorTest, TestToolbarSetupWithNoWebstateList) {
mediator_.consumer = consumer_;
[[[consumer_ reject] ignoringNonObjectArgs] setTabCount:0];
}
// Test the Toolbar Setup gets called when the mediator's WebState and Consumer
// have been set.
TEST_F(ToolbarMediatorTest, TestToolbarSetup) {
mediator_.webStateList = web_state_list_.get();
SetUpActiveWebState();
mediator_.consumer = consumer_;
[[consumer_ verify] setCanGoForward:NO];
[[consumer_ verify] setCanGoBack:NO];
[[consumer_ verify] setLoadingState:YES];
[[consumer_ verify] setShareMenuEnabled:NO];
}
// Test the Toolbar Setup gets called when the mediator's WebState and Consumer
// have been set in reverse order.
TEST_F(ToolbarMediatorTest, TestToolbarSetupReverse) {
mediator_.consumer = consumer_;
mediator_.webStateList = web_state_list_.get();
SetUpActiveWebState();
[[consumer_ verify] setCanGoForward:NO];
[[consumer_ verify] setCanGoBack:NO];
[[consumer_ verify] setLoadingState:YES];
[[consumer_ verify] setShareMenuEnabled:NO];
}
// Test the WebstateList related setup gets called when the mediator's WebState
// and Consumer have been set.
TEST_F(ToolbarMediatorTest, TestWebstateListRelatedSetup) {
mediator_.webStateList = web_state_list_.get();
mediator_.consumer = consumer_;
[[consumer_ verify] setTabCount:3];
}
// Test the WebstateList related setup gets called when the mediator's WebState
// and Consumer have been set in reverse order.
TEST_F(ToolbarMediatorTest, TestWebstateListRelatedSetupReverse) {
mediator_.consumer = consumer_;
mediator_.webStateList = web_state_list_.get();
[[consumer_ verify] setTabCount:3];
}
// Test the Toolbar is updated when the Webstate observer method DidStartLoading
// is triggered by SetLoading.
TEST_F(ToolbarMediatorTest, TestDidStartLoading) {
// Change the default loading state to false to verify the Webstate
// callback with true.
web_state_->SetLoading(false);
mediator_.webStateList = web_state_list_.get();
SetUpActiveWebState();
mediator_.consumer = consumer_;
web_state_->SetLoading(true);
[[consumer_ verify] setLoadingState:YES];
}
// Test the Toolbar is updated when the Webstate observer method DidStopLoading
// is triggered by SetLoading.
TEST_F(ToolbarMediatorTest, TestDidStopLoading) {
mediator_.webStateList = web_state_list_.get();
SetUpActiveWebState();
mediator_.consumer = consumer_;
web_state_->SetLoading(false);
[[consumer_ verify] setLoadingState:NO];
}
// Test the Toolbar is updated when the Webstate observer method
// DidLoadPageWithSuccess is triggered by OnPageLoaded.
TEST_F(ToolbarMediatorTest, TestDidLoadPageWithSucess) {
SetUpBookmarks();
mediator_.webStateList = web_state_list_.get();
SetUpActiveWebState();
mediator_.consumer = consumer_;
mediator_.bookmarkModel = bookmark_model_;
navigation_manager_->set_can_go_forward(true);
navigation_manager_->set_can_go_back(true);
web_state_->SetCurrentURL(GURL(kTestUrl));
web_state_->OnPageLoaded(web::PageLoadCompletionStatus::SUCCESS);
[[consumer_ verify] setCanGoForward:YES];
[[consumer_ verify] setCanGoBack:YES];
[[consumer_ verify] setPageBookmarked:YES];
[[consumer_ verify] setShareMenuEnabled:YES];
}
// Test the Toolbar is updated when the Webstate observer method
// didFinishNavigation is called.
TEST_F(ToolbarMediatorTest, TestDidFinishNavigation) {
SetUpBookmarks();
mediator_.webStateList = web_state_list_.get();
SetUpActiveWebState();
mediator_.consumer = consumer_;
mediator_.bookmarkModel = bookmark_model_;
navigation_manager_->set_can_go_forward(true);
navigation_manager_->set_can_go_back(true);
web_state_->SetCurrentURL(GURL(kTestUrl));
web::FakeNavigationContext context;
web_state_->OnNavigationFinished(&context);
[[consumer_ verify] setCanGoForward:YES];
[[consumer_ verify] setCanGoBack:YES];
[[consumer_ verify] setPageBookmarked:YES];
[[consumer_ verify] setShareMenuEnabled:YES];
}
// Test the Toolbar is updated when the Webstate observer method
// didChangeLoadingProgress is called.
TEST_F(ToolbarMediatorTest, TestLoadingProgress) {
mediator_.webStateList = web_state_list_.get();
SetUpActiveWebState();
mediator_.consumer = consumer_;
[mediator_ webState:web_state_ didChangeLoadingProgress:0.42];
[[consumer_ verify] setLoadingProgressFraction:0.42];
}
// Test that increasing the number of Webstates will update the consumer with
// the right value.
TEST_F(ToolbarMediatorTest, TestIncreaseNumberOfWebstates) {
mediator_.webStateList = web_state_list_.get();
mediator_.consumer = consumer_;
InsertNewWebState(0);
[[consumer_ verify] setTabCount:kNumberOfWebStates + 1];
}
// Test that decreasing the number of Webstates will update the consumer with
// the right value.
TEST_F(ToolbarMediatorTest, TestDecreaseNumberOfWebstates) {
mediator_.webStateList = web_state_list_.get();
mediator_.consumer = consumer_;
web_state_list_->DetachWebStateAt(0);
[[consumer_ verify] setTabCount:kNumberOfWebStates - 1];
}
// Test that setting the voice search provider after the consumer works.
TEST_F(ToolbarMediatorTest, TestVoiceSearchProviderAfterConsumer) {
MockEnabledVoiceSearchProvider provider;
OCMExpect([consumer_ setVoiceSearchEnabled:YES]);
mediator_.consumer = consumer_;
mediator_.voiceSearchProvider = &provider;
EXPECT_OCMOCK_VERIFY(consumer_);
}
// Test that setting the voice search provider after the consumer works.
TEST_F(ToolbarMediatorTest, TestVoiceSearchProviderBeforeConsumer) {
MockEnabledVoiceSearchProvider provider;
OCMExpect([consumer_ setVoiceSearchEnabled:YES]);
mediator_.voiceSearchProvider = &provider;
mediator_.consumer = consumer_;
EXPECT_OCMOCK_VERIFY(consumer_);
}
// Test that setting the voice search provider after the consumer works.
TEST_F(ToolbarMediatorTest, TestVoiceSearchProviderNotEnabled) {
VoiceSearchProvider provider;
OCMExpect([consumer_ setVoiceSearchEnabled:NO]);
mediator_.voiceSearchProvider = &provider;
mediator_.consumer = consumer_;
EXPECT_OCMOCK_VERIFY(consumer_);
}
} // namespace