Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(408)

Side by Side Diff: chrome/browser/ui/cocoa/passwords/account_chooser_view_controller_unittest.mm

Issue 1610653002: Integrate the account chooser dialog on Mac. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "chrome/browser/ui/cocoa/passwords/account_chooser_view_controller.h" 5 #import "chrome/browser/ui/cocoa/passwords/account_chooser_view_controller.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/mac/foundation_util.h" 9 #include "base/mac/foundation_util.h"
10 #include "base/memory/scoped_vector.h"
11 #include "base/strings/string16.h" 10 #include "base/strings/string16.h"
12 #include "base/strings/utf_string_conversions.h" 11 #include "base/strings/utf_string_conversions.h"
13 #import "chrome/browser/ui/cocoa/bubble_combobox.h" 12 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
14 #include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
15 #import "chrome/browser/ui/cocoa/passwords/account_avatar_fetcher_manager.h" 13 #import "chrome/browser/ui/cocoa/passwords/account_avatar_fetcher_manager.h"
16 #import "chrome/browser/ui/cocoa/passwords/account_chooser_view_controller.h" 14 #import "chrome/browser/ui/cocoa/passwords/account_chooser_view_controller.h"
17 #include "chrome/browser/ui/cocoa/passwords/base_passwords_controller_test.h" 15 #include "chrome/browser/ui/passwords/password_dialog_controller.h"
18 #include "chrome/browser/ui/passwords/account_chooser_more_combobox_model.h" 16 #include "testing/gmock/include/gmock/gmock.h"
19 #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h" 17 #include "testing/gtest/include/gtest/gtest.h"
20 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.h"
21 #include "components/password_manager/core/common/password_manager_ui.h"
22 #include "testing/gtest_mac.h" 18 #include "testing/gtest_mac.h"
23 #include "url/gurl.h" 19 #include "url/gurl.h"
24 20
25 @interface ManagePasswordsBubbleAccountChooserViewController(Testing)
26 - (id)initWithModel:(ManagePasswordsBubbleModel*)model
27 avatarManager:(AccountAvatarFetcherManager*)avatarManager
28 delegate:(id<ManagePasswordsBubbleContentViewDelegate>)delegate;
29 @property(nonatomic, readonly) NSButton* cancelButton;
30 @property(nonatomic, readonly) BubbleCombobox* moreButton;
31 @property(nonatomic, readonly) NSTableView* credentialsView;
32 @end
33 21
34 @interface CredentialItemView(Testing) 22 @interface CredentialItemView(Testing)
35 @property(nonatomic, readonly) NSTextField* upperLabel; 23 @property(nonatomic, readonly) NSTextField* upperLabel;
36 @end 24 @end
37 25
38 @interface AccountAvatarFetcherTestManager : AccountAvatarFetcherManager { 26 @interface AccountAvatarFetcherTestManager : AccountAvatarFetcherManager {
39 std::vector<GURL> fetchedAvatars_; 27 std::vector<GURL> fetchedAvatars_;
40 } 28 }
41 @property(nonatomic, readonly) const std::vector<GURL>& fetchedAvatars; 29 @property(nonatomic, readonly) const std::vector<GURL>& fetchedAvatars;
42 @end 30 @end
43 31
44 @implementation AccountAvatarFetcherTestManager 32 @implementation AccountAvatarFetcherTestManager
45 33
46 - (void)fetchAvatar:(const GURL&)avatarURL forView:(CredentialItemView*)view { 34 - (void)fetchAvatar:(const GURL&)avatarURL forView:(CredentialItemView*)view {
47 fetchedAvatars_.push_back(avatarURL); 35 fetchedAvatars_.push_back(avatarURL);
48 } 36 }
49 37
50 - (const std::vector<GURL>&)fetchedAvatars { 38 - (const std::vector<GURL>&)fetchedAvatars {
51 return fetchedAvatars_; 39 return fetchedAvatars_;
52 } 40 }
53 41
54 @end 42 @end
55 43
56 namespace { 44 namespace {
57 45
46 const char kDialogTitle[] = "Choose an account";
47
58 // Returns a PasswordForm with only a username. 48 // Returns a PasswordForm with only a username.
59 scoped_ptr<autofill::PasswordForm> Credential(const char* username) { 49 scoped_ptr<autofill::PasswordForm> Credential(const char* username) {
60 scoped_ptr<autofill::PasswordForm> credential(new autofill::PasswordForm); 50 scoped_ptr<autofill::PasswordForm> credential(new autofill::PasswordForm);
61 credential->username_value = base::ASCIIToUTF16(username); 51 credential->username_value = base::ASCIIToUTF16(username);
62 return credential; 52 return credential;
63 } 53 }
64 54
65 // Tests for the account chooser view of the password management bubble. 55 class PasswordDialogControllerMock : public PasswordDialogController {
66 class ManagePasswordsBubbleAccountChooserViewControllerTest
67 : public ManagePasswordsControllerTest {
68 public: 56 public:
69 ManagePasswordsBubbleAccountChooserViewControllerTest() : controller_(nil) {} 57 MOCK_CONST_METHOD0(GetLocalForms, const FormsVector&());
58 MOCK_CONST_METHOD0(GetFederationsForms, const FormsVector&());
59 MOCK_CONST_METHOD0(GetAccoutChooserTitle,
60 std::pair<base::string16, gfx::Range>());
61 MOCK_METHOD0(OnSmartLockLinkClicked, void());
62 MOCK_METHOD2(OnChooseCredentials, void(
63 const autofill::PasswordForm& password_form,
64 password_manager::CredentialType credential_type));
65 MOCK_METHOD0(OnCloseAccountChooser, void());
66 };
70 67
71 void SetUp() override { 68 // Tests for the account chooser dialog view.
72 ManagePasswordsControllerTest::SetUp(); 69 class AccountChooserViewControllerTest : public CocoaProfileTest,
73 delegate_.reset([[ContentViewDelegateMock alloc] init]); 70 public AccountChooserBridge {
74 avatar_manager_.reset([[AccountAvatarFetcherTestManager alloc] init]); 71 public:
72 void SetUp() override;
73
74 PasswordDialogControllerMock& dialog_controller() {
75 return dialog_controller_;
75 } 76 }
76 77
77 ContentViewDelegateMock* delegate() { return delegate_.get(); }
78
79 AccountAvatarFetcherTestManager* avatar_manager() { 78 AccountAvatarFetcherTestManager* avatar_manager() {
80 return avatar_manager_.get(); 79 return avatar_manager_.get();
81 } 80 }
82 81
83 ManagePasswordsBubbleAccountChooserViewController* controller() { 82 AccountChooserViewController* view_controller() {
84 if (!controller_) { 83 return view_controller_.get();
85 controller_.reset(
86 [[ManagePasswordsBubbleAccountChooserViewController alloc]
87 initWithModel:GetModelAndCreateIfNull()
88 avatarManager:avatar_manager()
89 delegate:delegate()]);
90 [controller_ loadView];
91 }
92 return controller_.get();
93 } 84 }
94 85
86 void SetUpAccountChooser(
87 PasswordDialogController::FormsVector local,
88 PasswordDialogController::FormsVector federations);
89
90 MOCK_METHOD0(OnPerformClose, void());
91
92 // AccountChooserBridge:
93 void PerformClose() override;
94 PasswordDialogController* GetDialogController() override;
95 net::URLRequestContextGetter* GetRequestContext() const override;
96
95 private: 97 private:
98 PasswordDialogControllerMock dialog_controller_;
96 base::scoped_nsobject<AccountAvatarFetcherTestManager> avatar_manager_; 99 base::scoped_nsobject<AccountAvatarFetcherTestManager> avatar_manager_;
97 base::scoped_nsobject<ManagePasswordsBubbleAccountChooserViewController> 100 base::scoped_nsobject<AccountChooserViewController> view_controller_;
98 controller_;
99 base::scoped_nsobject<ContentViewDelegateMock> delegate_;
100 }; 101 };
101 102
102 TEST_F(ManagePasswordsBubbleAccountChooserViewControllerTest, ConfiguresViews) { 103 void AccountChooserViewControllerTest::SetUp() {
103 ScopedVector<const autofill::PasswordForm> local_forms; 104 CocoaProfileTest::SetUp();
105 avatar_manager_.reset([[AccountAvatarFetcherTestManager alloc] init]);
106 }
107
108 void AccountChooserViewControllerTest::SetUpAccountChooser(
109 PasswordDialogController::FormsVector local,
110 PasswordDialogController::FormsVector federations) {
111 view_controller_.reset([[AccountChooserViewController alloc]
112 initWithBridge:this
113 avatarManager:avatar_manager()]);
114 EXPECT_CALL(dialog_controller_, GetLocalForms())
115 .WillOnce(testing::ReturnRef(local));
116 EXPECT_CALL(dialog_controller_, GetFederationsForms())
117 .WillOnce(testing::ReturnRef(federations));
118 EXPECT_CALL(dialog_controller_, GetAccoutChooserTitle())
119 .WillOnce(testing::Return(std::make_pair(base::ASCIIToUTF16(kDialogTitle),
120 gfx::Range(0, 5))));
121 [view_controller_ view];
122 ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&dialog_controller_));
123 }
124
125 void AccountChooserViewControllerTest::PerformClose() {
126 view_controller_.reset();
127 OnPerformClose();
128 }
129
130 PasswordDialogController*
131 AccountChooserViewControllerTest::GetDialogController() {
132 return &dialog_controller_;
133 }
134
135 net::URLRequestContextGetter*
136 AccountChooserViewControllerTest::GetRequestContext() const {
137 NOTREACHED();
138 return nullptr;
139 }
140
141 TEST_F(AccountChooserViewControllerTest, ConfiguresViews) {
142 PasswordDialogController::FormsVector local_forms;
104 local_forms.push_back(Credential("pizza")); 143 local_forms.push_back(Credential("pizza"));
105 ScopedVector<const autofill::PasswordForm> federated_forms; 144 PasswordDialogController::FormsVector federated_forms;
106 federated_forms.push_back(Credential("taco")); 145 federated_forms.push_back(Credential("taco"));
107 SetUpAccountChooser(std::move(local_forms), std::move(federated_forms)); 146 SetUpAccountChooser(std::move(local_forms), std::move(federated_forms));
108 // Trigger creation of controller and check the views. 147 // Trigger creation of controller and check the views.
109 NSTableView* view = controller().credentialsView; 148 NSTableView* view = view_controller().credentialsView;
110 ASSERT_NSNE(nil, view); 149 ASSERT_NSNE(nil, view);
111 ASSERT_EQ(2U, view.numberOfRows); 150 ASSERT_EQ(2U, view.numberOfRows);
112 EXPECT_NSEQ( 151 EXPECT_NSEQ(
113 @"pizza", 152 @"pizza",
114 base::mac::ObjCCastStrict<CredentialItemView>( 153 base::mac::ObjCCastStrict<CredentialItemView>(
115 base::mac::ObjCCastStrict<CredentialItemCell>( 154 base::mac::ObjCCastStrict<CredentialItemCell>(
116 [view.delegate tableView:view dataCellForTableColumn:nil row:0]) 155 [view.delegate tableView:view dataCellForTableColumn:nil row:0])
117 .view).upperLabel.stringValue); 156 .view).upperLabel.stringValue);
118 EXPECT_NSEQ( 157 EXPECT_NSEQ(
119 @"taco", 158 @"taco",
120 base::mac::ObjCCastStrict<CredentialItemView>( 159 base::mac::ObjCCastStrict<CredentialItemView>(
121 base::mac::ObjCCastStrict<CredentialItemCell>( 160 base::mac::ObjCCastStrict<CredentialItemCell>(
122 [view.delegate tableView:view dataCellForTableColumn:nil row:1]) 161 [view.delegate tableView:view dataCellForTableColumn:nil row:1])
123 .view).upperLabel.stringValue); 162 .view).upperLabel.stringValue);
124 EXPECT_TRUE(avatar_manager().fetchedAvatars.empty()); 163 EXPECT_TRUE(avatar_manager().fetchedAvatars.empty());
125 } 164 }
126 165
127 TEST_F(ManagePasswordsBubbleAccountChooserViewControllerTest, 166 TEST_F(AccountChooserViewControllerTest, ForwardsAvatarFetchToManager) {
128 ForwardsAvatarFetchToManager) { 167 PasswordDialogController::FormsVector local_forms;
129 ScopedVector<const autofill::PasswordForm> local_forms;
130 scoped_ptr<autofill::PasswordForm> form = Credential("taco"); 168 scoped_ptr<autofill::PasswordForm> form = Credential("taco");
131 form->icon_url = GURL("http://foo"); 169 form->icon_url = GURL("http://foo.com");
132 local_forms.push_back(std::move(form)); 170 local_forms.push_back(std::move(form));
133 SetUpAccountChooser(std::move(local_forms), 171 SetUpAccountChooser(std::move(local_forms),
134 ScopedVector<const autofill::PasswordForm>()); 172 PasswordDialogController::FormsVector());
135 // Trigger creation of the controller and check the fetched URLs.
136 controller();
137 EXPECT_FALSE(avatar_manager().fetchedAvatars.empty()); 173 EXPECT_FALSE(avatar_manager().fetchedAvatars.empty());
138 EXPECT_TRUE(std::find(avatar_manager().fetchedAvatars.begin(), 174 EXPECT_TRUE(std::find(avatar_manager().fetchedAvatars.begin(),
139 avatar_manager().fetchedAvatars.end(), 175 avatar_manager().fetchedAvatars.end(),
140 GURL("http://foo")) != 176 GURL("http://foo.com")) !=
141 avatar_manager().fetchedAvatars.end()); 177 avatar_manager().fetchedAvatars.end());
142 } 178 }
143 179
144 TEST_F(ManagePasswordsBubbleAccountChooserViewControllerTest, 180 TEST_F(AccountChooserViewControllerTest,
145 SelectingCredentialInformsModelAndClosesDialog) { 181 SelectingCredentialInformsModelAndClosesDialog) {
146 ScopedVector<const autofill::PasswordForm> local_forms; 182 PasswordDialogController::FormsVector local_forms;
147 local_forms.push_back(Credential("pizza")); 183 local_forms.push_back(Credential("pizza"));
148 ScopedVector<const autofill::PasswordForm> federated_forms; 184 PasswordDialogController::FormsVector federated_forms;
149 federated_forms.push_back(Credential("taco")); 185 federated_forms.push_back(Credential("taco"));
150 SetUpAccountChooser(std::move(local_forms), std::move(federated_forms)); 186 SetUpAccountChooser(std::move(local_forms), std::move(federated_forms));
151 EXPECT_CALL(*ui_controller(), 187 EXPECT_CALL(dialog_controller(),
152 ChooseCredential( 188 OnChooseCredentials(
153 *Credential("taco"), 189 *Credential("taco"),
154 password_manager::CredentialType::CREDENTIAL_TYPE_FEDERATED)); 190 password_manager::CredentialType::CREDENTIAL_TYPE_FEDERATED));
155 [controller().credentialsView 191 [view_controller().credentialsView
156 selectRowIndexes:[NSIndexSet indexSetWithIndex:1] 192 selectRowIndexes:[NSIndexSet indexSetWithIndex:1]
157 byExtendingSelection:NO]; 193 byExtendingSelection:NO];
158 EXPECT_TRUE(delegate().dismissed);
159 } 194 }
160 195
161 TEST_F(ManagePasswordsBubbleAccountChooserViewControllerTest, 196 TEST_F(AccountChooserViewControllerTest, SelectingNopeDismissesDialog) {
162 SelectingNopeDismissesDialog) { 197 PasswordDialogController::FormsVector local_forms;
163 ScopedVector<const autofill::PasswordForm> local_forms;
164 local_forms.push_back(Credential("pizza")); 198 local_forms.push_back(Credential("pizza"));
165 SetUpAccountChooser(std::move(local_forms), 199 SetUpAccountChooser(std::move(local_forms),
166 ScopedVector<const autofill::PasswordForm>()); 200 PasswordDialogController::FormsVector());
167 [controller().cancelButton performClick:nil]; 201 EXPECT_CALL(*this, OnPerformClose());
168 EXPECT_TRUE(delegate().dismissed); 202 [view_controller().cancelButton performClick:nil];
169 } 203 }
170 204
171 TEST_F(ManagePasswordsBubbleAccountChooserViewControllerTest, 205 TEST_F(AccountChooserViewControllerTest, ClickTitleLink) {
172 SelectingSettingsShowsSettingsPage) { 206 PasswordDialogController::FormsVector local_forms;
173 SetUpAccountChooser(ScopedVector<const autofill::PasswordForm>(), 207 local_forms.push_back(Credential("pizza"));
174 ScopedVector<const autofill::PasswordForm>()); 208 SetUpAccountChooser(std::move(local_forms),
175 BubbleCombobox* moreButton = controller().moreButton; 209 PasswordDialogController::FormsVector());
176 EXPECT_TRUE(moreButton); 210 EXPECT_CALL(dialog_controller(), OnSmartLockLinkClicked());
177 EXPECT_CALL(*ui_controller(), NavigateToPasswordManagerSettingsPage()); 211 [view_controller().titleView clickedOnLink:@""
178 [[moreButton menu] performActionForItemAtIndex: 212 atIndex:0];
179 AccountChooserMoreComboboxModel::INDEX_SETTINGS];
180 EXPECT_TRUE(delegate().dismissed);
181 }
182
183 TEST_F(ManagePasswordsBubbleAccountChooserViewControllerTest,
184 SelectingLearnMoreShowsHelpCenterArticle) {
185 SetUpAccountChooser(ScopedVector<const autofill::PasswordForm>(),
186 ScopedVector<const autofill::PasswordForm>());
187 BubbleCombobox* moreButton = controller().moreButton;
188 EXPECT_TRUE(moreButton);
189 [[moreButton menu] performActionForItemAtIndex:
190 AccountChooserMoreComboboxModel::INDEX_LEARN_MORE];
191 EXPECT_TRUE(delegate().dismissed);
192 // TODO(dconnelly): Test this when the article is written.
193 } 213 }
194 214
195 } // namespace 215 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698