OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 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 #import "ios/chrome/browser/ui/payments/contact_info_edit_coordinator.h" |
| 6 |
| 7 #include "base/logging.h" |
| 8 #include "base/mac/foundation_util.h" |
| 9 #include "base/memory/ptr_util.h" |
| 10 #include "base/strings/utf_string_conversions.h" |
| 11 #include "base/test/ios/wait_util.h" |
| 12 #include "components/autofill/core/browser/autofill_profile.h" |
| 13 #include "components/autofill/core/browser/autofill_test_utils.h" |
| 14 #include "components/autofill/core/browser/test_personal_data_manager.h" |
| 15 #include "components/autofill/core/browser/test_region_data_loader.h" |
| 16 #include "components/payments/core/payments_profile_comparator.h" |
| 17 #include "components/prefs/pref_service.h" |
| 18 #include "ios/chrome/browser/application_context.h" |
| 19 #include "ios/chrome/browser/payments/payment_request_test_util.h" |
| 20 #include "ios/chrome/browser/payments/test_payment_request.h" |
| 21 #import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller.h" |
| 22 #import "ios/chrome/browser/ui/payments/payment_request_editor_field.h" |
| 23 #include "testing/gmock/include/gmock/gmock.h" |
| 24 #include "testing/gtest/include/gtest/gtest.h" |
| 25 #include "testing/platform_test.h" |
| 26 #include "third_party/ocmock/OCMock/OCMock.h" |
| 27 #include "third_party/ocmock/gtest_support.h" |
| 28 |
| 29 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 30 #error "This file requires ARC support." |
| 31 #endif |
| 32 |
| 33 namespace { |
| 34 class MockTestPersonalDataManager : public autofill::TestPersonalDataManager { |
| 35 public: |
| 36 MockTestPersonalDataManager() : TestPersonalDataManager() {} |
| 37 MOCK_METHOD1(AddProfile, void(const autofill::AutofillProfile&)); |
| 38 MOCK_METHOD1(UpdateProfile, void(const autofill::AutofillProfile&)); |
| 39 }; |
| 40 |
| 41 class MockPaymentsProfileComparator |
| 42 : public payments::PaymentsProfileComparator { |
| 43 public: |
| 44 MockPaymentsProfileComparator(const std::string& app_locale, |
| 45 const payments::PaymentOptionsProvider& options) |
| 46 : PaymentsProfileComparator(app_locale, options) {} |
| 47 MOCK_METHOD1(Invalidate, void(const autofill::AutofillProfile&)); |
| 48 }; |
| 49 |
| 50 class MockTestPaymentRequest : public TestPaymentRequest { |
| 51 public: |
| 52 MockTestPaymentRequest(web::PaymentRequest web_payment_request, |
| 53 autofill::PersonalDataManager* personal_data_manager) |
| 54 : TestPaymentRequest(web_payment_request, personal_data_manager) {} |
| 55 MOCK_METHOD1(AddAutofillProfile, |
| 56 autofill::AutofillProfile*(const autofill::AutofillProfile&)); |
| 57 }; |
| 58 |
| 59 MATCHER_P3(ProfileMatches, name, email, phone_number, "") { |
| 60 return arg.GetRawInfo(autofill::NAME_FULL) == base::ASCIIToUTF16(name) && |
| 61 arg.GetRawInfo(autofill::EMAIL_ADDRESS) == base::ASCIIToUTF16(email) && |
| 62 arg.GetRawInfo(autofill::PHONE_HOME_WHOLE_NUMBER) == |
| 63 base::ASCIIToUTF16(phone_number); |
| 64 } |
| 65 |
| 66 NSArray<EditorField*>* GetEditorFields() { |
| 67 return @[ |
| 68 [[EditorField alloc] initWithAutofillUIType:AutofillUITypeProfileFullName |
| 69 fieldType:EditorFieldTypeTextField |
| 70 label:@"Name" |
| 71 value:@"John Doe" |
| 72 required:YES], |
| 73 [[EditorField alloc] |
| 74 initWithAutofillUIType:AutofillUITypeProfileEmailAddress |
| 75 fieldType:EditorFieldTypeTextField |
| 76 label:@"Email" |
| 77 value:@"john@doe.com" |
| 78 required:YES], |
| 79 [[EditorField alloc] |
| 80 initWithAutofillUIType:AutofillUITypeProfileHomePhoneWholeNumber |
| 81 fieldType:EditorFieldTypeTextField |
| 82 label:@"Phone" |
| 83 value:@"16502111111" |
| 84 required:YES], |
| 85 ]; |
| 86 } |
| 87 |
| 88 using ::testing::_; |
| 89 } // namespace |
| 90 |
| 91 class PaymentRequestContactInfoEditCoordinatorTest : public PlatformTest { |
| 92 protected: |
| 93 PaymentRequestContactInfoEditCoordinatorTest() |
| 94 : pref_service_(autofill::test::PrefServiceForTesting()) { |
| 95 personal_data_manager_.SetTestingPrefService(pref_service_.get()); |
| 96 payment_request_ = base::MakeUnique<MockTestPaymentRequest>( |
| 97 payment_request_test_util::CreateTestWebPaymentRequest(), |
| 98 &personal_data_manager_); |
| 99 |
| 100 profile_comparator_ = base::MakeUnique<MockPaymentsProfileComparator>( |
| 101 GetApplicationContext()->GetApplicationLocale(), |
| 102 *payment_request_.get()); |
| 103 payment_request_->SetProfileComparator(profile_comparator_.get()); |
| 104 |
| 105 test_region_data_loader_.set_synchronous_callback(true); |
| 106 payment_request_->SetRegionDataLoader(&test_region_data_loader_); |
| 107 } |
| 108 |
| 109 void TearDown() override { |
| 110 personal_data_manager_.SetTestingPrefService(nullptr); |
| 111 } |
| 112 |
| 113 std::unique_ptr<PrefService> pref_service_; |
| 114 MockTestPersonalDataManager personal_data_manager_; |
| 115 autofill::TestRegionDataLoader test_region_data_loader_; |
| 116 std::unique_ptr<MockPaymentsProfileComparator> profile_comparator_; |
| 117 std::unique_ptr<MockTestPaymentRequest> payment_request_; |
| 118 }; |
| 119 |
| 120 // Tests that invoking start and stop on the coordinator presents and dismisses |
| 121 // the contact info edit view controller, respectively. |
| 122 TEST_F(PaymentRequestContactInfoEditCoordinatorTest, StartAndStop) { |
| 123 UIViewController* base_view_controller = [[UIViewController alloc] init]; |
| 124 UINavigationController* navigation_controller = |
| 125 [[UINavigationController alloc] |
| 126 initWithRootViewController:base_view_controller]; |
| 127 |
| 128 ContactInfoEditCoordinator* coordinator = [[ContactInfoEditCoordinator alloc] |
| 129 initWithBaseViewController:base_view_controller]; |
| 130 [coordinator setPaymentRequest:payment_request_.get()]; |
| 131 |
| 132 EXPECT_EQ(1u, navigation_controller.viewControllers.count); |
| 133 |
| 134 [coordinator start]; |
| 135 // Short delay to allow animation to complete. |
| 136 base::test::ios::SpinRunLoopWithMaxDelay(base::TimeDelta::FromSecondsD(1.0)); |
| 137 EXPECT_EQ(2u, navigation_controller.viewControllers.count); |
| 138 |
| 139 [coordinator stop]; |
| 140 // Short delay to allow animation to complete. |
| 141 base::test::ios::SpinRunLoopWithMaxDelay(base::TimeDelta::FromSecondsD(1.0)); |
| 142 EXPECT_EQ(1u, navigation_controller.viewControllers.count); |
| 143 } |
| 144 |
| 145 // Tests that calling the view controller delegate method which signals that the |
| 146 // user has finished creating a new profile, causes the profile to be added to |
| 147 // the PaymentRequest instance and the corresponding coordinator delegate method |
| 148 // to get called. The new profile should also get added to the |
| 149 // PersonalDataManager. |
| 150 TEST_F(PaymentRequestContactInfoEditCoordinatorTest, DidFinishCreating) { |
| 151 UIViewController* base_view_controller = [[UIViewController alloc] init]; |
| 152 UINavigationController* navigation_controller = |
| 153 [[UINavigationController alloc] |
| 154 initWithRootViewController:base_view_controller]; |
| 155 |
| 156 ContactInfoEditCoordinator* coordinator = [[ContactInfoEditCoordinator alloc] |
| 157 initWithBaseViewController:base_view_controller]; |
| 158 [coordinator setPaymentRequest:payment_request_.get()]; |
| 159 |
| 160 // Mock the coordinator delegate. |
| 161 id delegate = [OCMockObject |
| 162 mockForProtocol:@protocol(ContactInfoEditCoordinatorDelegate)]; |
| 163 [[delegate expect] |
| 164 contactInfoEditCoordinator:coordinator |
| 165 didFinishEditingProfile:static_cast<autofill::AutofillProfile*>( |
| 166 [OCMArg anyPointer])]; |
| 167 [coordinator setDelegate:delegate]; |
| 168 |
| 169 EXPECT_EQ(1u, navigation_controller.viewControllers.count); |
| 170 |
| 171 [coordinator start]; |
| 172 // Short delay to allow animation to complete. |
| 173 base::test::ios::SpinRunLoopWithMaxDelay(base::TimeDelta::FromSecondsD(1.0)); |
| 174 EXPECT_EQ(2u, navigation_controller.viewControllers.count); |
| 175 |
| 176 // Expect an autofill profile to be added to the PaymentRequest. |
| 177 EXPECT_CALL(*payment_request_, |
| 178 AddAutofillProfile( |
| 179 ProfileMatches("John Doe", "john@doe.com", "16502111111"))) |
| 180 .Times(1); |
| 181 // Expect an autofill profile to be added to the PersonalDataManager. |
| 182 EXPECT_CALL( |
| 183 personal_data_manager_, |
| 184 AddProfile(ProfileMatches("John Doe", "john@doe.com", "16502111111"))) |
| 185 .Times(1); |
| 186 // No autofill profile should get updated in the PersonalDataManager. |
| 187 EXPECT_CALL(personal_data_manager_, UpdateProfile(_)).Times(0); |
| 188 // No autofill profile should get invalidated in PaymentsProfileComparator. |
| 189 EXPECT_CALL(*profile_comparator_, Invalidate(_)).Times(0); |
| 190 |
| 191 // Call the controller delegate method. |
| 192 PaymentRequestEditViewController* view_controller = |
| 193 base::mac::ObjCCastStrict<PaymentRequestEditViewController>( |
| 194 navigation_controller.visibleViewController); |
| 195 [coordinator paymentRequestEditViewController:view_controller |
| 196 didFinishEditingFields:GetEditorFields()]; |
| 197 |
| 198 EXPECT_OCMOCK_VERIFY(delegate); |
| 199 } |
| 200 |
| 201 // Tests that calling the view controller delegate method which signals that the |
| 202 // user has finished editing a profile, causes the corresponding coordinator |
| 203 // delegate method to get called. The profile should not get re-added to the |
| 204 // PaymentRequest instance or the PersonalDataManager. However, it is expected |
| 205 // to get updated in the PersonalDataManager. |
| 206 TEST_F(PaymentRequestContactInfoEditCoordinatorTest, DidFinishEditing) { |
| 207 UIViewController* base_view_controller = [[UIViewController alloc] init]; |
| 208 UINavigationController* navigation_controller = |
| 209 [[UINavigationController alloc] |
| 210 initWithRootViewController:base_view_controller]; |
| 211 |
| 212 ContactInfoEditCoordinator* coordinator = [[ContactInfoEditCoordinator alloc] |
| 213 initWithBaseViewController:base_view_controller]; |
| 214 [coordinator setPaymentRequest:payment_request_.get()]; |
| 215 |
| 216 // Set the profile to be edited. |
| 217 autofill::AutofillProfile profile; |
| 218 [coordinator setProfile:&profile]; |
| 219 |
| 220 // Mock the coordinator delegate. |
| 221 id delegate = [OCMockObject |
| 222 mockForProtocol:@protocol(ContactInfoEditCoordinatorDelegate)]; |
| 223 [[delegate expect] |
| 224 contactInfoEditCoordinator:coordinator |
| 225 didFinishEditingProfile:static_cast<autofill::AutofillProfile*>( |
| 226 [OCMArg anyPointer])]; |
| 227 [coordinator setDelegate:delegate]; |
| 228 |
| 229 EXPECT_EQ(1u, navigation_controller.viewControllers.count); |
| 230 |
| 231 [coordinator start]; |
| 232 // Short delay to allow animation to complete. |
| 233 base::test::ios::SpinRunLoopWithMaxDelay(base::TimeDelta::FromSecondsD(1.0)); |
| 234 EXPECT_EQ(2u, navigation_controller.viewControllers.count); |
| 235 |
| 236 // No autofill profile should get added to the PaymentRequest. |
| 237 EXPECT_CALL(*payment_request_, AddAutofillProfile(_)).Times(0); |
| 238 // No autofill profile should get added to the PersonalDataManager. |
| 239 EXPECT_CALL(personal_data_manager_, AddProfile(_)).Times(0); |
| 240 // Expect an autofill profile to be updated in the PersonalDataManager. |
| 241 EXPECT_CALL( |
| 242 personal_data_manager_, |
| 243 UpdateProfile(ProfileMatches("John Doe", "john@doe.com", "16502111111"))) |
| 244 .Times(1); |
| 245 // Expect an autofill profile to be invalidated in PaymentsProfileComparator. |
| 246 EXPECT_CALL( |
| 247 *profile_comparator_, |
| 248 Invalidate(ProfileMatches("John Doe", "john@doe.com", "16502111111"))) |
| 249 .Times(1); |
| 250 |
| 251 // Call the controller delegate method. |
| 252 PaymentRequestEditViewController* view_controller = |
| 253 base::mac::ObjCCastStrict<PaymentRequestEditViewController>( |
| 254 navigation_controller.visibleViewController); |
| 255 [coordinator paymentRequestEditViewController:view_controller |
| 256 didFinishEditingFields:GetEditorFields()]; |
| 257 |
| 258 EXPECT_OCMOCK_VERIFY(delegate); |
| 259 } |
| 260 |
| 261 // Tests that calling the view controller delegate method which signals that the |
| 262 // user has chosen to cancel creating/editing a profile, causes the |
| 263 // corresponding coordinator delegate method to get called. |
| 264 TEST_F(PaymentRequestContactInfoEditCoordinatorTest, DidCancel) { |
| 265 UIViewController* base_view_controller = [[UIViewController alloc] init]; |
| 266 UINavigationController* navigation_controller = |
| 267 [[UINavigationController alloc] |
| 268 initWithRootViewController:base_view_controller]; |
| 269 |
| 270 ContactInfoEditCoordinator* coordinator = [[ContactInfoEditCoordinator alloc] |
| 271 initWithBaseViewController:base_view_controller]; |
| 272 [coordinator setPaymentRequest:payment_request_.get()]; |
| 273 |
| 274 // Mock the coordinator delegate. |
| 275 id delegate = [OCMockObject |
| 276 mockForProtocol:@protocol(ContactInfoEditCoordinatorDelegate)]; |
| 277 [[delegate expect] contactInfoEditCoordinatorDidCancel:coordinator]; |
| 278 [coordinator setDelegate:delegate]; |
| 279 |
| 280 EXPECT_EQ(1u, navigation_controller.viewControllers.count); |
| 281 |
| 282 [coordinator start]; |
| 283 // Short delay to allow animation to complete. |
| 284 base::test::ios::SpinRunLoopWithMaxDelay(base::TimeDelta::FromSecondsD(1.0)); |
| 285 EXPECT_EQ(2u, navigation_controller.viewControllers.count); |
| 286 |
| 287 // Call the controller delegate method. |
| 288 PaymentRequestEditViewController* view_controller = |
| 289 base::mac::ObjCCastStrict<PaymentRequestEditViewController>( |
| 290 navigation_controller.visibleViewController); |
| 291 [coordinator paymentRequestEditViewControllerDidCancel:view_controller]; |
| 292 |
| 293 EXPECT_OCMOCK_VERIFY(delegate); |
| 294 } |
OLD | NEW |