[go: nahoru, domu]

blob: ca8e64945ed93d5c98be7a53cf75a861330461ee [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <UIKit/UIKit.h>
#import "base/apple/foundation_util.h"
#import "ios/chrome/browser/ui/bubble/bubble_unittest_util.h"
#import "ios/chrome/browser/ui/bubble/bubble_view.h"
#import "ios/chrome/browser/ui/bubble/bubble_view_controller.h"
#import "ios/chrome/browser/ui/bubble/bubble_view_controller_presenter+private.h"
#import "ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.h"
#import "testing/gtest/include/gtest/gtest.h"
#import "testing/platform_test.h"
#import "third_party/abseil-cpp/absl/types/optional.h"
// Test fixture to test the BubbleViewControllerPresenter.
class BubbleViewControllerPresenterTest : public PlatformTest {
public:
BubbleViewControllerPresenterTest()
: bubbleViewControllerPresenter_([[BubbleViewControllerPresenter alloc]
initWithText:@"Text"
title:@"Title"
image:[[UIImage alloc] init]
arrowDirection:BubbleArrowDirectionUp
alignment:BubbleAlignmentCenter
bubbleType:BubbleViewTypeRichWithSnooze
dismissalCallback:^(
feature_engagement::Tracker::SnoozeAction action) {
dismissalCallbackCount_++;
dismissalCallbackAction_ = action;
}]),
window_([[UIWindow alloc]
initWithFrame:CGRectMake(0.0, 0.0, 500.0, 500.0)]),
parentViewController_([[UIViewController alloc] init]),
anchorPoint_(CGPointMake(250.0, 250.0)),
dismissalCallbackCount_(0),
dismissalCallbackAction_() {
parentViewController_.view.frame = CGRectMake(0.0, 0.0, 500.0, 500.0);
[window_ addSubview:parentViewController_.view];
}
~BubbleViewControllerPresenterTest() override {
// Dismiss the bubble, to ensure that its dismissalCallback runs
// before the test fixture is destroyed.
[bubbleViewControllerPresenter_ dismissAnimated:NO];
}
protected:
// The presenter object under test.
BubbleViewControllerPresenter* bubbleViewControllerPresenter_;
// The window the `parentViewController_`'s view is in.
// -presentInViewController: expects the `anchorPoint` parameter to be in
// window coordinates, which requires the `view` property to be in a window.
UIWindow* window_;
// The view controller the BubbleViewController is added as a child of.
UIViewController* parentViewController_;
// The point at which the bubble is anchored.
CGPoint anchorPoint_;
// How many times `bubbleViewControllerPresenter_`'s internal
// `dismissalCallback` has been invoked. Defaults to 0. Every time the
// callback is invoked, `dismissalCallbackCount_` increments.
int dismissalCallbackCount_;
absl::optional<feature_engagement::Tracker::SnoozeAction>
dismissalCallbackAction_;
};
// Tests that, after initialization, the internal BubbleViewController and
// BubbleView have not been added to the parent.
TEST_F(BubbleViewControllerPresenterTest, InitializedNotAdded) {
EXPECT_FALSE([parentViewController_.childViewControllers
containsObject:bubbleViewControllerPresenter_.bubbleViewController]);
EXPECT_FALSE([parentViewController_.view.subviews
containsObject:bubbleViewControllerPresenter_.bubbleViewController.view]);
}
// Tests that -presentInViewController: adds the BubbleViewController and
// BubbleView to the parent.
TEST_F(BubbleViewControllerPresenterTest, PresentAddsToViewController) {
[bubbleViewControllerPresenter_
presentInViewController:parentViewController_
view:parentViewController_.view
anchorPoint:anchorPoint_];
EXPECT_TRUE([parentViewController_.childViewControllers
containsObject:bubbleViewControllerPresenter_.bubbleViewController]);
EXPECT_TRUE([parentViewController_.view.subviews
containsObject:bubbleViewControllerPresenter_.bubbleViewController.view]);
}
// Tests that initially the dismissal callback has not been invoked.
TEST_F(BubbleViewControllerPresenterTest, DismissalCallbackCountInitialized) {
EXPECT_EQ(0, dismissalCallbackCount_);
}
// Tests that presenting the bubble but not dismissing it does not invoke the
// dismissal callback.
TEST_F(BubbleViewControllerPresenterTest, DismissalCallbackNotCalled) {
[bubbleViewControllerPresenter_
presentInViewController:parentViewController_
view:parentViewController_.view
anchorPoint:anchorPoint_];
EXPECT_EQ(0, dismissalCallbackCount_);
}
// Tests that presenting then dismissing the bubble invokes the dismissal
// callback.
TEST_F(BubbleViewControllerPresenterTest, DismissalCallbackCalledOnce) {
[bubbleViewControllerPresenter_
presentInViewController:parentViewController_
view:parentViewController_.view
anchorPoint:anchorPoint_];
[bubbleViewControllerPresenter_ dismissAnimated:NO];
EXPECT_EQ(1, dismissalCallbackCount_);
}
// Tests that calling -dismissAnimated: after the bubble has already been
// dismissed does not invoke the dismissal callback again.
TEST_F(BubbleViewControllerPresenterTest, DismissalCallbackNotCalledTwice) {
[bubbleViewControllerPresenter_
presentInViewController:parentViewController_
view:parentViewController_.view
anchorPoint:anchorPoint_];
[bubbleViewControllerPresenter_ dismissAnimated:NO];
[bubbleViewControllerPresenter_ dismissAnimated:NO];
EXPECT_EQ(1, dismissalCallbackCount_);
}
// Tests that calling -dismissAnimated: before the bubble has been presented
// does not invoke the dismissal callback.
TEST_F(BubbleViewControllerPresenterTest,
DismissalCallbackNotCalledBeforePresentation) {
[bubbleViewControllerPresenter_ dismissAnimated:NO];
EXPECT_EQ(0, dismissalCallbackCount_);
}
// Tests that the timers are `nil` before the bubble is presented on screen.
TEST_F(BubbleViewControllerPresenterTest, TimersInitiallyNil) {
EXPECT_EQ(nil, bubbleViewControllerPresenter_.bubbleDismissalTimer);
EXPECT_EQ(nil, bubbleViewControllerPresenter_.engagementTimer);
}
// Tests that the timers are not `nil` once the bubble is presented on screen.
TEST_F(BubbleViewControllerPresenterTest, TimersInstantiatedOnPresent) {
[bubbleViewControllerPresenter_
presentInViewController:parentViewController_
view:parentViewController_.view
anchorPoint:anchorPoint_];
EXPECT_NE(nil, bubbleViewControllerPresenter_.bubbleDismissalTimer);
EXPECT_NE(nil, bubbleViewControllerPresenter_.engagementTimer);
}
// Tests that the bubble timer is `nil` but the engagement timer is not `nil`
// when the bubble is presented and dismissed.
TEST_F(BubbleViewControllerPresenterTest, BubbleTimerNilOnDismissal) {
[bubbleViewControllerPresenter_
presentInViewController:parentViewController_
view:parentViewController_.view
anchorPoint:anchorPoint_];
[bubbleViewControllerPresenter_ dismissAnimated:NO];
EXPECT_EQ(nil, bubbleViewControllerPresenter_.bubbleDismissalTimer);
EXPECT_NE(nil, bubbleViewControllerPresenter_.engagementTimer);
}
// Tests that the `userEngaged` property is initially `NO`.
TEST_F(BubbleViewControllerPresenterTest, UserEngagedInitiallyNo) {
EXPECT_FALSE(bubbleViewControllerPresenter_.isUserEngaged);
}
// Tests that the `userEngaged` property is `YES` once the bubble is presented
// on screen.
TEST_F(BubbleViewControllerPresenterTest, UserEngagedYesOnPresent) {
[bubbleViewControllerPresenter_
presentInViewController:parentViewController_
view:parentViewController_.view
anchorPoint:anchorPoint_];
EXPECT_TRUE(bubbleViewControllerPresenter_.isUserEngaged);
}
// Tests that the `userEngaged` property remains `YES` once the bubble is
// presented and dismissed.
TEST_F(BubbleViewControllerPresenterTest, UserEngagedYesOnDismissal) {
[bubbleViewControllerPresenter_
presentInViewController:parentViewController_
view:parentViewController_.view
anchorPoint:anchorPoint_];
EXPECT_TRUE(bubbleViewControllerPresenter_.isUserEngaged);
}
// Tests that tapping the bubble view's close button invoke the dismissal
// callback with a dismiss action.
TEST_F(BubbleViewControllerPresenterTest,
BubbleViewCloseButtonCallDismissalCallback) {
[bubbleViewControllerPresenter_
presentInViewController:parentViewController_
view:parentViewController_.view
anchorPoint:anchorPoint_];
BubbleView* bubbleView = base::apple::ObjCCastStrict<BubbleView>(
bubbleViewControllerPresenter_.bubbleViewController.view);
EXPECT_TRUE(bubbleView);
UIButton* closeButton = GetCloseButtonFromBubbleView(bubbleView);
EXPECT_TRUE(closeButton);
[closeButton sendActionsForControlEvents:UIControlEventTouchUpInside];
EXPECT_TRUE(dismissalCallbackAction_);
EXPECT_EQ(feature_engagement::Tracker::SnoozeAction::DISMISSED,
dismissalCallbackAction_);
EXPECT_EQ(1, dismissalCallbackCount_);
}
// Tests that tapping the bubble view's snooze button invoke the dismissal
// callback with a snooze action.
TEST_F(BubbleViewControllerPresenterTest,
BubbleViewSnoozeButtonCallDismissalCallback) {
[bubbleViewControllerPresenter_
presentInViewController:parentViewController_
view:parentViewController_.view
anchorPoint:anchorPoint_];
BubbleView* bubbleView = base::apple::ObjCCastStrict<BubbleView>(
bubbleViewControllerPresenter_.bubbleViewController.view);
EXPECT_TRUE(bubbleView);
UIButton* snoozeButton = GetSnoozeButtonFromBubbleView(bubbleView);
EXPECT_TRUE(snoozeButton);
[snoozeButton sendActionsForControlEvents:UIControlEventTouchUpInside];
EXPECT_TRUE(dismissalCallbackAction_);
EXPECT_EQ(feature_engagement::Tracker::SnoozeAction::SNOOZED,
dismissalCallbackAction_);
EXPECT_EQ(1, dismissalCallbackCount_);
}