1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/prefs/pref_service.h" 6#include "base/strings/utf_string_conversions.h" 7#include "chrome/browser/ui/autofill/account_chooser_model.h" 8#include "chrome/common/pref_names.h" 9#include "chrome/test/base/testing_profile.h" 10#include "components/autofill/core/browser/autofill_metrics.h" 11#include "testing/gmock/include/gmock/gmock.h" 12#include "testing/gtest/include/gtest/gtest.h" 13 14using base::ASCIIToUTF16; 15 16namespace autofill { 17 18namespace { 19 20class TestAccountChooserModel : public AccountChooserModel { 21 public: 22 TestAccountChooserModel(AccountChooserModelDelegate* delegate, 23 Profile* profile, 24 bool disable_wallet, 25 const AutofillMetrics& metric_logger) 26 : AccountChooserModel(delegate, profile, disable_wallet, metric_logger) {} 27 virtual ~TestAccountChooserModel() {} 28 29 using AccountChooserModel::kWalletAccountsStartId; 30 using AccountChooserModel::kWalletAddAccountId; 31 using AccountChooserModel::kAutofillItemId; 32 33 private: 34 DISALLOW_COPY_AND_ASSIGN(TestAccountChooserModel); 35}; 36 37class MockAccountChooserModelDelegate : public AccountChooserModelDelegate { 38 public: 39 MockAccountChooserModelDelegate() {} 40 virtual ~MockAccountChooserModelDelegate() {} 41 42 MOCK_METHOD0(AccountChoiceChanged, void()); 43 MOCK_METHOD0(AddAccount, void()); 44 MOCK_METHOD0(UpdateAccountChooserView, void()); 45}; 46 47class AccountChooserModelTest : public testing::Test { 48 public: 49 AccountChooserModelTest() 50 : model_(&delegate_, &profile_, false, metric_logger_) {} 51 virtual ~AccountChooserModelTest() {} 52 53 TestingProfile* profile() { return &profile_; } 54 MockAccountChooserModelDelegate* delegate() { return &delegate_; } 55 TestAccountChooserModel* model() { return &model_; } 56 const AutofillMetrics& metric_logger() { return metric_logger_; } 57 58 private: 59 TestingProfile profile_; 60 testing::NiceMock<MockAccountChooserModelDelegate> delegate_; 61 TestAccountChooserModel model_; 62 AutofillMetrics metric_logger_; 63}; 64 65} // namespace 66 67TEST_F(AccountChooserModelTest, ObeysPref) { 68 // When "Pay without wallet" is false, use Wallet by default. 69 { 70 profile()->GetPrefs()->SetBoolean( 71 ::prefs::kAutofillDialogPayWithoutWallet, false); 72 TestAccountChooserModel model(delegate(), 73 profile(), 74 false, 75 metric_logger()); 76 EXPECT_TRUE(model.WalletIsSelected()); 77 } 78 // When the user chose to "Pay without wallet", use Autofill. 79 { 80 profile()->GetPrefs()->SetBoolean( 81 ::prefs::kAutofillDialogPayWithoutWallet, true); 82 TestAccountChooserModel model(delegate(), 83 profile(), 84 false, 85 metric_logger()); 86 EXPECT_FALSE(model.WalletIsSelected()); 87 } 88 // When the |disable_wallet| argument is true, use Autofill regardless 89 // of the pref. 90 { 91 profile()->GetPrefs()->SetBoolean( 92 ::prefs::kAutofillDialogPayWithoutWallet, false); 93 TestAccountChooserModel model(delegate(), profile(), true, metric_logger()); 94 EXPECT_FALSE(model.WalletIsSelected()); 95 } 96 // In incognito, use local data regardless of the pref. 97 { 98 TestingProfile::Builder builder; 99 builder.SetIncognito(); 100 scoped_ptr<TestingProfile> incognito = builder.Build(); 101 incognito->SetOriginalProfile(profile()); 102 profile()->GetPrefs()->SetBoolean( 103 ::prefs::kAutofillDialogPayWithoutWallet, false); 104 incognito->GetPrefs()->SetBoolean( 105 ::prefs::kAutofillDialogPayWithoutWallet, false); 106 107 TestAccountChooserModel model(delegate(), 108 incognito.get(), 109 false, 110 metric_logger()); 111 EXPECT_FALSE(model.WalletIsSelected()); 112 } 113} 114 115TEST_F(AccountChooserModelTest, IgnoresPrefChanges) { 116 ASSERT_FALSE(profile()->GetPrefs()->GetBoolean( 117 ::prefs::kAutofillDialogPayWithoutWallet)); 118 EXPECT_TRUE(model()->WalletIsSelected()); 119 120 // Check that nothing changes while this dialog is running if a pref changes 121 // (this could cause subtle bugs or annoyances if a user closes another 122 // running dialog). 123 profile()->GetPrefs()->SetBoolean( 124 ::prefs::kAutofillDialogPayWithoutWallet, true); 125 EXPECT_TRUE(model()->WalletIsSelected()); 126} 127 128TEST_F(AccountChooserModelTest, HandlesError) { 129 EXPECT_CALL(*delegate(), AccountChoiceChanged()).Times(1); 130 EXPECT_CALL(*delegate(), UpdateAccountChooserView()).Times(1); 131 132 ASSERT_TRUE(model()->WalletIsSelected()); 133 ASSERT_TRUE(model()->IsCommandIdEnabled( 134 TestAccountChooserModel::kWalletAccountsStartId)); 135 136 model()->SetHadWalletError(); 137 EXPECT_FALSE(model()->WalletIsSelected()); 138 EXPECT_FALSE(model()->IsCommandIdEnabled( 139 TestAccountChooserModel::kWalletAccountsStartId)); 140} 141 142TEST_F(AccountChooserModelTest, HandlesSigninError) { 143 EXPECT_CALL(*delegate(), AccountChoiceChanged()).Times(1); 144 EXPECT_CALL(*delegate(), UpdateAccountChooserView()).Times(2); 145 146 // 0. "Unknown" wallet account, we don't know if the user is signed-in yet. 147 ASSERT_TRUE(model()->WalletIsSelected()); 148 ASSERT_TRUE(model()->IsCommandIdEnabled( 149 TestAccountChooserModel::kWalletAccountsStartId)); 150 ASSERT_TRUE(model()->WalletIsSelected()); 151 ASSERT_FALSE(model()->HasAccountsToChoose()); 152 ASSERT_EQ(3, model()->GetItemCount()); 153 EXPECT_EQ(base::string16(), model()->GetActiveWalletAccountName()); 154 155 // 1. "Known" wallet account (e.g. after active/passive/automatic sign-in). 156 // Calls UpdateAccountChooserView. 157 std::vector<std::string> accounts; 158 accounts.push_back("john.doe@gmail.com"); 159 model()->SetWalletAccounts(accounts, 0U); 160 ASSERT_TRUE(model()->WalletIsSelected()); 161 ASSERT_TRUE(model()->IsCommandIdEnabled( 162 TestAccountChooserModel::kWalletAccountsStartId)); 163 ASSERT_TRUE(model()->WalletIsSelected()); 164 ASSERT_TRUE(model()->HasAccountsToChoose()); 165 EXPECT_EQ(3, model()->GetItemCount()); 166 EXPECT_EQ(ASCIIToUTF16(accounts[0]), model()->GetActiveWalletAccountName()); 167 168 // 2. Sign-in failure. 169 // Autofill data should be selected and be the only valid choice. 170 // Calls UpdateAccountChooserView. 171 // Calls AccountChoiceChanged. 172 model()->SetHadWalletSigninError(); 173 EXPECT_FALSE(model()->WalletIsSelected()); 174 EXPECT_TRUE(model()->IsCommandIdEnabled( 175 TestAccountChooserModel::kWalletAccountsStartId)); 176 EXPECT_FALSE(model()->WalletIsSelected()); 177 EXPECT_FALSE(model()->HasAccountsToChoose()); 178 EXPECT_EQ(2, model()->GetItemCount()); 179 EXPECT_EQ(base::string16(), model()->GetActiveWalletAccountName()); 180} 181 182TEST_F(AccountChooserModelTest, RespectsUserChoice) { 183 EXPECT_CALL(*delegate(), AccountChoiceChanged()).Times(2); 184 185 model()->ExecuteCommand(TestAccountChooserModel::kAutofillItemId, 0); 186 EXPECT_FALSE(model()->WalletIsSelected()); 187 188 EXPECT_CALL(*delegate(), AddAccount()); 189 model()->ExecuteCommand(TestAccountChooserModel::kWalletAddAccountId, 0); 190 EXPECT_FALSE(model()->WalletIsSelected()); 191 192 model()->ExecuteCommand(TestAccountChooserModel::kWalletAccountsStartId, 0); 193 EXPECT_TRUE(model()->WalletIsSelected()); 194} 195 196TEST_F(AccountChooserModelTest, HandlesMultipleAccounts) { 197 EXPECT_FALSE(model()->HasAccountsToChoose()); 198 199 std::vector<std::string> accounts; 200 accounts.push_back("john.doe@gmail.com"); 201 accounts.push_back("jane.smith@gmail.com"); 202 model()->SetWalletAccounts(accounts, 0U); 203 EXPECT_TRUE(model()->HasAccountsToChoose()); 204 EXPECT_TRUE(model()->WalletIsSelected()); 205 ASSERT_EQ(4, model()->GetItemCount()); 206 EXPECT_TRUE(model()->IsCommandIdEnabled( 207 TestAccountChooserModel::kWalletAccountsStartId)); 208 EXPECT_TRUE(model()->IsCommandIdEnabled( 209 TestAccountChooserModel::kWalletAccountsStartId + 1)); 210 EXPECT_EQ(ASCIIToUTF16(accounts[0]), model()->GetActiveWalletAccountName()); 211 model()->SetWalletAccounts(accounts, 1U); 212 EXPECT_EQ(ASCIIToUTF16(accounts[1]), model()->GetActiveWalletAccountName()); 213 214 model()->ExecuteCommand(TestAccountChooserModel::kWalletAccountsStartId, 0); 215 EXPECT_EQ(ASCIIToUTF16(accounts[0]), model()->GetActiveWalletAccountName()); 216 model()->ExecuteCommand(TestAccountChooserModel::kWalletAccountsStartId + 1, 217 0); 218 EXPECT_EQ(ASCIIToUTF16(accounts[1]), model()->GetActiveWalletAccountName()); 219 220 // Setting the wallet accounts forces the switch to wallet. 221 model()->ExecuteCommand(TestAccountChooserModel::kAutofillItemId, 0); 222 EXPECT_FALSE(model()->WalletIsSelected()); 223 model()->SetWalletAccounts(accounts, 1U); 224 EXPECT_TRUE(model()->WalletIsSelected()); 225} 226 227} // namespace autofill 228