blob: f64cd2171156aa41acc7cb7326b25b8dae1f0deb [file] [log] [blame]
// Copyright 2018 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/popup_menu/popup_menu_mediator.h"
#include "base/time/default_clock.h"
#include "components/feature_engagement/test/mock_tracker.h"
#include "components/reading_list/core/reading_list_model_impl.h"
#import "ios/chrome/browser/ui/popup_menu/public/popup_menu_table_view_controller.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"
#include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
#import "ios/public/provider/chrome/browser/user_feedback/user_feedback_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/gmock/include/gmock/gmock.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
namespace {
const int kNumberOfWebStates = 3;
} // namespace
@interface TestPopupMenuMediator
: PopupMenuMediator<CRWWebStateObserver, WebStateListObserving>
@end
@implementation TestPopupMenuMediator
@end
class PopupMenuMediatorTest : public PlatformTest {
public:
PopupMenuMediatorTest() {
reading_list_model_.reset(new ReadingListModelImpl(
nullptr, nullptr, base::DefaultClock::GetInstance()));
popup_menu_ = OCMClassMock([PopupMenuTableViewController class]);
popup_menu_strict_ =
OCMStrictClassMock([PopupMenuTableViewController class]);
OCMExpect([popup_menu_strict_ setPopupMenuItems:[OCMArg any]]);
OCMExpect([popup_menu_strict_ setDelegate:[OCMArg any]]);
SetUpWebStateList();
}
// Explicitly disconnect the mediator so there won't be any WebStateList
// observers when web_state_list_ gets dealloc.
~PopupMenuMediatorTest() override {
[mediator_ disconnect];
}
protected:
PopupMenuMediator* CreateMediator(PopupMenuType type,
BOOL is_incognito,
BOOL trigger_incognito_hint) {
mediator_ =
[[PopupMenuMediator alloc] initWithType:type
isIncognito:is_incognito
readingListModel:reading_list_model_.get()
triggerNewIncognitoTabTip:trigger_incognito_hint];
return mediator_;
}
void SetUpWebStateList() {
auto navigation_manager = std::make_unique<ToolbarTestNavigationManager>();
navigation_manager_ = navigation_manager.get();
std::unique_ptr<ToolbarTestWebState> 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();
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 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); }
// Checks that the popup_menu_ is receiving a number of items corresponding to
// |number_items|.
void CheckMediatorSetItems(NSArray<NSNumber*>* number_items) {
mediator_.webStateList = web_state_list_.get();
SetUpActiveWebState();
auto same_number_items = ^BOOL(id items) {
if (![items isKindOfClass:[NSArray class]])
return NO;
if ([items count] != number_items.count)
return NO;
for (NSUInteger index = 0; index < number_items.count; index++) {
NSArray* section = [items objectAtIndex:index];
if (section.count != number_items[index].unsignedIntegerValue)
return NO;
}
return YES;
};
OCMExpect([popup_menu_
setPopupMenuItems:[OCMArg checkWithBlock:same_number_items]]);
mediator_.popupMenu = popup_menu_;
EXPECT_OCMOCK_VERIFY(popup_menu_);
}
PopupMenuMediator* mediator_;
std::unique_ptr<ReadingListModelImpl> reading_list_model_;
ToolbarTestWebState* web_state_;
ToolbarTestNavigationManager* navigation_manager_;
std::unique_ptr<WebStateList> web_state_list_;
FakeWebStateListDelegate web_state_list_delegate_;
id popup_menu_;
// Mock refusing all calls except -setPopupMenuItems:.
id popup_menu_strict_;
};
// Tests that the feature engagement tracker get notified when the mediator is
// disconnected and the tracker wants the notification badge displayed.
TEST_F(PopupMenuMediatorTest, TestFeatureEngagementDisconnect) {
CreateMediator(PopupMenuTypeToolsMenu, NO, NO);
feature_engagement::test::MockTracker tracker;
EXPECT_CALL(tracker, ShouldTriggerHelpUI(testing::_))
.WillRepeatedly(testing::Return(true));
mediator_.popupMenu = popup_menu_;
mediator_.engagementTracker = &tracker;
EXPECT_CALL(tracker, Dismissed(testing::_));
[mediator_ disconnect];
}
// Tests that the mediator is returning the right number of items and sections
// for the Tools Menu type.
TEST_F(PopupMenuMediatorTest, TestElementsToolsMenu) {
CreateMediator(PopupMenuTypeToolsMenu, NO, NO);
NSUInteger number_of_action_items = 6;
if (ios::GetChromeBrowserProvider()
->GetUserFeedbackProvider()
->IsUserFeedbackEnabled()) {
number_of_action_items++;
}
CheckMediatorSetItems(@[ @(3), @(5), @(number_of_action_items) ]);
}
// Tests that the mediator is returning the right number of items and sections
// for the Tab Grid type, in non-incognito.
TEST_F(PopupMenuMediatorTest, TestElementsTabGridNonIncognito) {
CreateMediator(PopupMenuTypeTabGrid, NO, NO);
CheckMediatorSetItems(@[ @(2), @(1) ]);
}
// Tests that the mediator is returning the right number of items and sections
// for the Tab Grid type, in incognito.
TEST_F(PopupMenuMediatorTest, TestElementsTabGridIncognito) {
CreateMediator(PopupMenuTypeTabGrid, YES, NO);
CheckMediatorSetItems(@[ @(2), @(1) ]);
}
// Tests that the mediator is asking for an item to be highlighted when asked.
TEST_F(PopupMenuMediatorTest, TestNewIncognitoHint) {
CreateMediator(PopupMenuTypeToolsMenu, NO, YES);
mediator_.webStateList = web_state_list_.get();
SetUpActiveWebState();
OCMExpect([popup_menu_ setItemToHighlight:[OCMArg isNotNil]]);
mediator_.popupMenu = popup_menu_;
EXPECT_OCMOCK_VERIFY(popup_menu_);
}
// Test that the mediator isn't asking for an highlighted item.
TEST_F(PopupMenuMediatorTest, TestNewIncognitoNoHint) {
CreateMediator(PopupMenuTypeToolsMenu, NO, NO);
[[popup_menu_ reject] setItemToHighlight:[OCMArg any]];
mediator_.webStateList = web_state_list_.get();
SetUpActiveWebState();
mediator_.popupMenu = popup_menu_;
}
// Tests that the mediator is asking for an item to be highlighted when asked.
TEST_F(PopupMenuMediatorTest, TestNewIncognitoHintTabGrid) {
CreateMediator(PopupMenuTypeTabGrid, NO, YES);
OCMExpect([popup_menu_ setItemToHighlight:[OCMArg isNotNil]]);
mediator_.webStateList = web_state_list_.get();
SetUpActiveWebState();
mediator_.popupMenu = popup_menu_;
EXPECT_OCMOCK_VERIFY(popup_menu_);
}