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    Profile* incognito = profile()->GetOffTheRecordProfile();
99    profile()->GetPrefs()->SetBoolean(
100        ::prefs::kAutofillDialogPayWithoutWallet, false);
101    incognito->GetPrefs()->SetBoolean(
102        ::prefs::kAutofillDialogPayWithoutWallet, false);
103
104    TestAccountChooserModel model(
105        delegate(), incognito, false, metric_logger());
106    EXPECT_FALSE(model.WalletIsSelected());
107  }
108}
109
110TEST_F(AccountChooserModelTest, IgnoresPrefChanges) {
111  ASSERT_FALSE(profile()->GetPrefs()->GetBoolean(
112      ::prefs::kAutofillDialogPayWithoutWallet));
113  EXPECT_TRUE(model()->WalletIsSelected());
114
115  // Check that nothing changes while this dialog is running if a pref changes
116  // (this could cause subtle bugs or annoyances if a user closes another
117  // running dialog).
118  profile()->GetPrefs()->SetBoolean(
119      ::prefs::kAutofillDialogPayWithoutWallet, true);
120  EXPECT_TRUE(model()->WalletIsSelected());
121}
122
123TEST_F(AccountChooserModelTest, HandlesError) {
124  EXPECT_CALL(*delegate(), AccountChoiceChanged()).Times(1);
125  EXPECT_CALL(*delegate(), UpdateAccountChooserView()).Times(1);
126
127  ASSERT_TRUE(model()->WalletIsSelected());
128  ASSERT_TRUE(model()->IsCommandIdEnabled(
129      TestAccountChooserModel::kWalletAccountsStartId));
130
131  model()->SetHadWalletError();
132  EXPECT_FALSE(model()->WalletIsSelected());
133  EXPECT_FALSE(model()->IsCommandIdEnabled(
134      TestAccountChooserModel::kWalletAccountsStartId));
135}
136
137TEST_F(AccountChooserModelTest, HandlesSigninError) {
138  EXPECT_CALL(*delegate(), AccountChoiceChanged()).Times(1);
139  EXPECT_CALL(*delegate(), UpdateAccountChooserView()).Times(2);
140
141  // 0. "Unknown" wallet account, we don't know if the user is signed-in yet.
142  ASSERT_TRUE(model()->WalletIsSelected());
143  ASSERT_TRUE(model()->IsCommandIdEnabled(
144      TestAccountChooserModel::kWalletAccountsStartId));
145  ASSERT_TRUE(model()->WalletIsSelected());
146  ASSERT_FALSE(model()->HasAccountsToChoose());
147  ASSERT_EQ(3, model()->GetItemCount());
148  EXPECT_EQ(base::string16(), model()->GetActiveWalletAccountName());
149
150  // 1. "Known" wallet account (e.g. after active/passive/automatic sign-in).
151  // Calls UpdateAccountChooserView.
152  std::vector<std::string> accounts;
153  accounts.push_back("john.doe@gmail.com");
154  model()->SetWalletAccounts(accounts, 0U);
155  ASSERT_TRUE(model()->WalletIsSelected());
156  ASSERT_TRUE(model()->IsCommandIdEnabled(
157      TestAccountChooserModel::kWalletAccountsStartId));
158  ASSERT_TRUE(model()->WalletIsSelected());
159  ASSERT_TRUE(model()->HasAccountsToChoose());
160  EXPECT_EQ(3, model()->GetItemCount());
161  EXPECT_EQ(ASCIIToUTF16(accounts[0]), model()->GetActiveWalletAccountName());
162
163  // 2. Sign-in failure.
164  // Autofill data should be selected and be the only valid choice.
165  // Calls UpdateAccountChooserView.
166  // Calls AccountChoiceChanged.
167  model()->SetHadWalletSigninError();
168  EXPECT_FALSE(model()->WalletIsSelected());
169  EXPECT_TRUE(model()->IsCommandIdEnabled(
170      TestAccountChooserModel::kWalletAccountsStartId));
171  EXPECT_FALSE(model()->WalletIsSelected());
172  EXPECT_FALSE(model()->HasAccountsToChoose());
173  EXPECT_EQ(2, model()->GetItemCount());
174  EXPECT_EQ(base::string16(), model()->GetActiveWalletAccountName());
175}
176
177TEST_F(AccountChooserModelTest, RespectsUserChoice) {
178  EXPECT_CALL(*delegate(), AccountChoiceChanged()).Times(2);
179
180  model()->ExecuteCommand(TestAccountChooserModel::kAutofillItemId, 0);
181  EXPECT_FALSE(model()->WalletIsSelected());
182
183  EXPECT_CALL(*delegate(), AddAccount());
184  model()->ExecuteCommand(TestAccountChooserModel::kWalletAddAccountId, 0);
185  EXPECT_FALSE(model()->WalletIsSelected());
186
187  model()->ExecuteCommand(TestAccountChooserModel::kWalletAccountsStartId, 0);
188  EXPECT_TRUE(model()->WalletIsSelected());
189}
190
191TEST_F(AccountChooserModelTest, HandlesMultipleAccounts) {
192  EXPECT_FALSE(model()->HasAccountsToChoose());
193
194  std::vector<std::string> accounts;
195  accounts.push_back("john.doe@gmail.com");
196  accounts.push_back("jane.smith@gmail.com");
197  model()->SetWalletAccounts(accounts, 0U);
198  EXPECT_TRUE(model()->HasAccountsToChoose());
199  EXPECT_TRUE(model()->WalletIsSelected());
200  ASSERT_EQ(4, model()->GetItemCount());
201  EXPECT_TRUE(model()->IsCommandIdEnabled(
202      TestAccountChooserModel::kWalletAccountsStartId));
203  EXPECT_TRUE(model()->IsCommandIdEnabled(
204      TestAccountChooserModel::kWalletAccountsStartId + 1));
205  EXPECT_EQ(ASCIIToUTF16(accounts[0]), model()->GetActiveWalletAccountName());
206  model()->SetWalletAccounts(accounts, 1U);
207  EXPECT_EQ(ASCIIToUTF16(accounts[1]), model()->GetActiveWalletAccountName());
208
209  model()->ExecuteCommand(TestAccountChooserModel::kWalletAccountsStartId, 0);
210  EXPECT_EQ(ASCIIToUTF16(accounts[0]), model()->GetActiveWalletAccountName());
211  model()->ExecuteCommand(TestAccountChooserModel::kWalletAccountsStartId + 1,
212                          0);
213  EXPECT_EQ(ASCIIToUTF16(accounts[1]), model()->GetActiveWalletAccountName());
214
215  // Setting the wallet accounts forces the switch to wallet.
216  model()->ExecuteCommand(TestAccountChooserModel::kAutofillItemId, 0);
217  EXPECT_FALSE(model()->WalletIsSelected());
218  model()->SetWalletAccounts(accounts, 1U);
219  EXPECT_TRUE(model()->WalletIsSelected());
220}
221
222}  // namespace autofill
223