blob: ce380293187cf7faf321a36a196960f0fd574bfe [file] [log] [blame]
// Copyright 2015 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/settings/sync_create_passphrase_table_view_controller.h"
#import <UIKit/UIKit.h>
#include "base/compiler_specific.h"
#import "base/test/ios/wait_util.h"
#include "components/browser_sync/profile_sync_service_mock.h"
#include "components/strings/grit/components_strings.h"
#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
#import "ios/chrome/browser/ui/settings/cells/byo_textfield_item.h"
#import "ios/chrome/browser/ui/settings/cells/passphrase_error_item.h"
#import "ios/chrome/browser/ui/settings/passphrase_table_view_controller_test.h"
#include "ios/chrome/grit/ios_strings.h"
#include "testing/gmock/include/gmock/gmock.h"
#import "testing/gtest_mac.h"
#include "testing/platform_test.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/l10n/l10n_util_mac.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
using testing::_;
using testing::AtLeast;
using testing::Return;
class SyncCreatePassphraseTableViewControllerTest
: public PassphraseTableViewControllerTest {
public:
SyncCreatePassphraseTableViewControllerTest() {}
protected:
void TearDown() override {
[SyncController() stopObserving];
PassphraseTableViewControllerTest::TearDown();
}
ChromeTableViewController* InstantiateController() override {
return [[SyncCreatePassphraseTableViewController alloc]
initWithBrowserState:chrome_browser_state_.get()];
}
SyncCreatePassphraseTableViewController* SyncController() {
return static_cast<SyncCreatePassphraseTableViewController*>(controller());
}
};
TEST_F(SyncCreatePassphraseTableViewControllerTest, TestConstructorDestructor) {
CreateController();
CheckController();
EXPECT_CALL(*fake_sync_service_->GetUserSettingsMock(),
SetEncryptionPassphrase(_))
.Times(0);
// Simulate the view appearing.
[controller() viewDidAppear:YES];
}
TEST_F(SyncCreatePassphraseTableViewControllerTest, TestModel) {
SyncCreatePassphraseTableViewController* controller = SyncController();
EXPECT_EQ(1, NumberOfSections());
NSInteger const kSection = 0;
EXPECT_EQ(2, NumberOfItemsInSection(kSection));
NSString* expectedTitle =
l10n_util::GetNSString(IDS_IOS_SYNC_ENCRYPTION_CREATE_PASSPHRASE);
CheckTitle(expectedTitle);
// Passphrase item.
BYOTextFieldItem* passphraseItem = GetTableViewItem(kSection, 0);
EXPECT_NSEQ(controller.passphrase, passphraseItem.textField);
// Confirm passphrase item.
BYOTextFieldItem* confirmPassphraseItem = GetTableViewItem(kSection, 1);
EXPECT_NSEQ(controller.confirmPassphrase, confirmPassphraseItem.textField);
}
TEST_F(SyncCreatePassphraseTableViewControllerTest, TestAllFieldsFilled) {
SyncCreatePassphraseTableViewController* sync_controller = SyncController();
// Both text fields empty should return false.
EXPECT_FALSE([sync_controller areAllFieldsFilled]);
// One text field empty should return false.
[[sync_controller passphrase] setText:@"decodeme"];
EXPECT_FALSE([sync_controller areAllFieldsFilled]);
[[sync_controller passphrase] setText:@""];
[[sync_controller confirmPassphrase] setText:@"decodeme"];
EXPECT_FALSE([sync_controller areAllFieldsFilled]);
[[sync_controller passphrase] setText:@"decodeme"];
// Neither text field empty ("decodeme") should return true.
EXPECT_TRUE([sync_controller areAllFieldsFilled]);
}
TEST_F(SyncCreatePassphraseTableViewControllerTest, TestCredentialsOkPressed) {
SyncCreatePassphraseTableViewController* sync_controller = SyncController();
EXPECT_CALL(*fake_sync_service_->GetUserSettingsMock(),
SetEncryptionPassphrase(_))
.Times(0);
EXPECT_FALSE([[sync_controller navigationItem].rightBarButtonItem isEnabled]);
[sync_controller signInPressed];
}
TEST_F(SyncCreatePassphraseTableViewControllerTest, TestNextTextField) {
SyncCreatePassphraseTableViewController* sync_controller = SyncController();
// The second call to -nextTextField is the same as hitting 'ok'.
// With matching text, this should cause an attempt to set the passphrase.
EXPECT_CALL(*fake_sync_service_, AddObserver(_)).Times(AtLeast(1));
EXPECT_CALL(*fake_sync_service_, RemoveObserver(_)).Times(AtLeast(1));
EXPECT_CALL(*fake_sync_service_->GetUserSettingsMock(),
SetEncryptionPassphrase("decodeme"));
[[sync_controller passphrase] setText:@"decodeme"];
[sync_controller textFieldDidChange:[sync_controller passphrase]];
[sync_controller textFieldDidEndEditing:[sync_controller passphrase]];
[[sync_controller confirmPassphrase] setText:@"decodeme"];
[sync_controller textFieldDidChange:[sync_controller confirmPassphrase]];
[sync_controller textFieldDidEndEditing:[sync_controller confirmPassphrase]];
}
TEST_F(SyncCreatePassphraseTableViewControllerTest, TestOneTextFieldEmpty) {
SyncCreatePassphraseTableViewController* sync_controller = SyncController();
EXPECT_CALL(*fake_sync_service_->GetUserSettingsMock(),
SetEncryptionPassphrase(_))
.Times(0);
[[sync_controller passphrase] setText:@"decodeme"];
[sync_controller textFieldDidChange:[sync_controller passphrase]];
// Expect the right button to be visible.
EXPECT_TRUE([sync_controller navigationItem].rightBarButtonItem);
// Expect the right button to be disabled.
EXPECT_FALSE([[sync_controller navigationItem].rightBarButtonItem isEnabled]);
}
// Tests that if user inputs incompatible passwords, an error message will be
// shown. If the user types again, the error messasge will be cleared.
TEST_F(SyncCreatePassphraseTableViewControllerTest, TestTextFieldsDoNotMatch) {
SyncCreatePassphraseTableViewController* sync_controller = SyncController();
// Mismatching text fields should not get to the point of trying to set the
// passphrase and adding the sync observer.
EXPECT_CALL(*fake_sync_service_, AddObserver(_)).Times(0);
EXPECT_CALL(*fake_sync_service_->GetUserSettingsMock(),
SetEncryptionPassphrase(_))
.Times(0);
[[sync_controller passphrase] setText:@"decodeme"];
[[sync_controller confirmPassphrase] setText:@"donothing"];
[sync_controller textFieldDidChange:[sync_controller passphrase]];
[sync_controller signInPressed];
// Check the error cell.
NSInteger const kSection = 0;
EXPECT_EQ(3, NumberOfItemsInSection(kSection));
PassphraseErrorItem* item = GetTableViewItem(kSection, 2);
EXPECT_NSEQ(l10n_util::GetNSString(IDS_SYNC_PASSPHRASE_MISMATCH_ERROR),
item.text);
// User types again.
[sync_controller textFieldDidBeginEditing:sync_controller.confirmPassphrase];
// Check that error message is cleared.
EXPECT_EQ(2, NumberOfItemsInSection(kSection));
EXPECT_FALSE([sync_controller.tableViewModel
hasItemForItemType:sync_encryption_passphrase::ItemTypeError
sectionIdentifier:sync_encryption_passphrase::
SectionIdentifierPassphrase]);
}
TEST_F(SyncCreatePassphraseTableViewControllerTest, TestTextFieldsMatch) {
SyncCreatePassphraseTableViewController* sync_controller = SyncController();
// Matching text should cause an attempt to set it and add a sync observer.
EXPECT_CALL(*fake_sync_service_, AddObserver(_)).Times(AtLeast(1));
EXPECT_CALL(*fake_sync_service_, RemoveObserver(_)).Times(AtLeast(1));
EXPECT_CALL(*fake_sync_service_->GetUserSettingsMock(),
SetEncryptionPassphrase("decodeme"));
[[sync_controller passphrase] setText:@"decodeme"];
[[sync_controller confirmPassphrase] setText:@"decodeme"];
[sync_controller textFieldDidChange:[sync_controller passphrase]];
[sync_controller signInPressed];
}
TEST_F(SyncCreatePassphraseTableViewControllerTest, TestOnStateChanged) {
SyncCreatePassphraseTableViewController* sync_controller = SyncController();
SetUpNavigationController(sync_controller);
EXPECT_EQ([nav_controller_ topViewController], sync_controller);
// Set up the fake sync service to have accepted the passphrase.
ON_CALL(*fake_sync_service_->GetUserSettingsMock(), IsPassphraseRequired())
.WillByDefault(Return(false));
ON_CALL(*fake_sync_service_->GetUserSettingsMock(),
IsUsingSecondaryPassphrase())
.WillByDefault(Return(true));
[sync_controller onSyncStateChanged];
// Calling -onStateChanged with an accepted secondary passphrase should
// cause the controller to be popped off the navigation stack.
EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
base::test::ios::kWaitForUIElementTimeout, ^bool() {
return [nav_controller_ topViewController] != sync_controller;
}));
}
// TODO(crbug.com/658269): Re-enable test once it's been deflaked.
// Verifies that sync errors don't make the navigation item disappear.
// Regression test for http://crbug.com/501784.
TEST_F(SyncCreatePassphraseTableViewControllerTest,
DISABLED_TestOnStateChangedError) {
SyncCreatePassphraseTableViewController* sync_controller = SyncController();
SetUpNavigationController(sync_controller);
EXPECT_EQ([nav_controller_ topViewController], sync_controller);
EXPECT_NE(nil, sync_controller.title);
// Install a fake left button item, to check it's not removed.
UIBarButtonItem* leftBarButtonItem =
[[UIBarButtonItem alloc] initWithTitle:@"Left"
style:UIBarButtonItemStylePlain
target:nil
action:nil];
sync_controller.navigationItem.leftBarButtonItem = leftBarButtonItem;
// Set up the fake sync service to be in a passphrase creation state.
ON_CALL(*fake_sync_service_->GetUserSettingsMock(), IsPassphraseRequired())
.WillByDefault(Return(false));
ON_CALL(*fake_sync_service_->GetUserSettingsMock(),
IsUsingSecondaryPassphrase())
.WillByDefault(Return(false));
[sync_controller onSyncStateChanged];
EXPECT_EQ([nav_controller_ topViewController], sync_controller);
EXPECT_NE(nil, sync_controller.title);
EXPECT_EQ(leftBarButtonItem,
sync_controller.navigationItem.leftBarButtonItem);
}
} // namespace