blob: 564c6640c65470052b80efda2371911e6fc71965 [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/web/repost_form_tab_helper.h"
#import <UIKit/UIKit.h>
#include "base/bind.h"
#include "base/mac/bind_objc_block.h"
#import "ios/chrome/browser/web/repost_form_tab_helper_delegate.h"
#import "ios/web/public/test/fakes/test_web_state.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
// A configurable TabHelper delegate for testing.
@interface RepostFormTabHelperTestDelegate
: NSObject<RepostFormTabHelperDelegate>
// YES if repost form dialog is currently presented.
@property(nonatomic, readonly, getter=isPresentingDialog) BOOL presentingDialog;
// Location where the dialog was presented last time.
@property(nonatomic, assign) CGPoint location;
// Tab helper which delegates to this class.
@property(nonatomic, assign) RepostFormTabHelper* tabHelper;
// Calls |repostFormTabHelper:presentRepostFromDialogAtPoint:completionHandler:|
// completion handler.
- (void)allowRepost:(BOOL)shouldContinue;
@end
@implementation RepostFormTabHelperTestDelegate {
void (^_completionHandler)(BOOL);
}
@synthesize presentingDialog = _presentingDialog;
@synthesize location = _location;
@synthesize tabHelper = _tabHelper;
- (void)allowRepost:(BOOL)allow {
_completionHandler(allow);
_presentingDialog = NO;
}
- (void)repostFormTabHelper:(RepostFormTabHelper*)helper
presentRepostFromDialogAtPoint:(CGPoint)location
completionHandler:(void (^)(BOOL))completionHandler {
EXPECT_EQ(_tabHelper, helper);
EXPECT_FALSE(_presentingDialog);
_presentingDialog = YES;
_location = location;
_completionHandler = [completionHandler copy];
}
- (void)repostFormTabHelperDismissRepostFormDialog:
(RepostFormTabHelper*)helper {
EXPECT_EQ(_tabHelper, helper);
EXPECT_TRUE(_presentingDialog);
_presentingDialog = NO;
_completionHandler = nil;
}
@end
namespace {
// Test location passed to RepostFormTabHelper.
const CGFloat kDialogHLocation = 10;
const CGFloat kDialogVLocation = 20;
// No-op callback for RepostFormTabHelper.
void IgnoreBool(bool) {}
} // namespace
// Test fixture for RepostFormTabHelper class.
class RepostFormTabHelperTest : public PlatformTest {
protected:
RepostFormTabHelperTest()
: web_state_(new web::TestWebState()),
delegate_([[RepostFormTabHelperTestDelegate alloc] init]),
location_(CGPointMake(kDialogHLocation, kDialogVLocation)) {
RepostFormTabHelper::CreateForWebState(web_state_.get(), delegate_);
delegate_.tabHelper = tab_helper();
}
RepostFormTabHelper* tab_helper() {
return RepostFormTabHelper::FromWebState(web_state_.get());
}
protected:
std::unique_ptr<web::TestWebState> web_state_;
RepostFormTabHelperTestDelegate* delegate_;
CGPoint location_;
};
// Tests presentation location.
TEST_F(RepostFormTabHelperTest, Location) {
EXPECT_FALSE(CGPointEqualToPoint(delegate_.location, location_));
tab_helper()->PresentDialog(location_, base::Bind(&IgnoreBool));
EXPECT_TRUE(CGPointEqualToPoint(delegate_.location, location_));
}
// Tests cancelling repost.
TEST_F(RepostFormTabHelperTest, CancelRepost) {
ASSERT_FALSE(delegate_.presentingDialog);
__block bool callback_called = false;
tab_helper()->PresentDialog(location_, base::BindBlockArc(^(bool repost) {
EXPECT_FALSE(repost);
callback_called = true;
}));
EXPECT_TRUE(delegate_.presentingDialog);
ASSERT_FALSE(callback_called);
[delegate_ allowRepost:NO];
EXPECT_TRUE(callback_called);
}
// Tests allowing repost.
TEST_F(RepostFormTabHelperTest, AllowRepost) {
ASSERT_FALSE(delegate_.presentingDialog);
__block bool callback_called = false;
tab_helper()->PresentDialog(location_, base::BindBlockArc(^(bool repost) {
EXPECT_TRUE(repost);
callback_called = true;
}));
EXPECT_TRUE(delegate_.presentingDialog);
ASSERT_FALSE(callback_called);
[delegate_ allowRepost:YES];
EXPECT_TRUE(callback_called);
}
// Tests that dialog is dismissed when WebState is destroyed.
TEST_F(RepostFormTabHelperTest, DismissingOnWebStateDestruction) {
ASSERT_FALSE(delegate_.presentingDialog);
tab_helper()->PresentDialog(location_, base::Bind(&IgnoreBool));
EXPECT_TRUE(delegate_.presentingDialog);
web_state_.reset();
EXPECT_FALSE(delegate_.presentingDialog);
}
// Tests that dialog is dismissed after provisional navigation has started.
TEST_F(RepostFormTabHelperTest, DismissingOnNavigationStart) {
ASSERT_FALSE(delegate_.presentingDialog);
tab_helper()->PresentDialog(location_, base::Bind(&IgnoreBool));
EXPECT_TRUE(delegate_.presentingDialog);
web_state_->OnNavigationStarted(nullptr /* navigation_context */);
EXPECT_FALSE(delegate_.presentingDialog);
}