| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #import "ios/chrome/browser/ui/settings/native_apps_collection_view_controller.h
" | |
| 6 #import "ios/chrome/browser/ui/settings/native_apps_collection_view_controller_p
rivate.h" | |
| 7 | |
| 8 #include <memory> | |
| 9 | |
| 10 #include "base/compiler_specific.h" | |
| 11 #import "base/ios/block_types.h" | |
| 12 #include "base/test/histogram_tester.h" | |
| 13 #include "base/threading/thread_task_runner_handle.h" | |
| 14 #import "ios/chrome/browser/ui/collection_view/collection_view_controller_test.h
" | |
| 15 #import "ios/chrome/browser/ui/settings/cells/native_app_item.h" | |
| 16 #import "ios/public/provider/chrome/browser/native_app_launcher/fake_native_app_
metadata.h" | |
| 17 #import "ios/public/provider/chrome/browser/native_app_launcher/fake_native_app_
whitelist_manager.h" | |
| 18 #include "ios/web/public/test/test_web_thread_bundle.h" | |
| 19 #include "net/url_request/url_request_test_util.h" | |
| 20 #include "testing/gtest/include/gtest/gtest.h" | |
| 21 #import "testing/gtest_mac.h" | |
| 22 #import "third_party/ocmock/OCMock/OCMock.h" | |
| 23 #include "ui/base/l10n/l10n_util.h" | |
| 24 | |
| 25 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
| 26 #error "This file requires ARC support." | |
| 27 #endif | |
| 28 | |
| 29 @interface NativeAppsCollectionViewController (Testing) | |
| 30 @property(nonatomic, retain) NSArray* appsInSettings; | |
| 31 @property(nonatomic, assign) id<StoreKitLauncher> storeKitLauncher; | |
| 32 - (void)configureWithNativeAppWhiteListManager: | |
| 33 (id<NativeAppWhitelistManager>)nativeAppWhitelistManager; | |
| 34 - (void)autoOpenInAppChanged:(UISwitch*)switchControl; | |
| 35 - (void)installApp:(UIButton*)button; | |
| 36 - (void)recordUserAction:(settings::NativeAppsAction)action; | |
| 37 - (void)appDidInstall:(NSNotification*)note; | |
| 38 - (id<NativeAppMetadata>)nativeAppAtIndex:(NSUInteger)index; | |
| 39 @end | |
| 40 | |
| 41 @interface MockNativeAppWhitelistManager : FakeNativeAppWhitelistManager | |
| 42 @end | |
| 43 | |
| 44 @implementation MockNativeAppWhitelistManager | |
| 45 | |
| 46 - (id)init { | |
| 47 self = [super init]; | |
| 48 if (self) { | |
| 49 FakeNativeAppMetadata* app1 = [[FakeNativeAppMetadata alloc] init]; | |
| 50 [app1 setAppName:@"App1"]; | |
| 51 [app1 setAppId:@"1"]; | |
| 52 [app1 setGoogleOwnedApp:YES]; | |
| 53 | |
| 54 FakeNativeAppMetadata* app2 = [[FakeNativeAppMetadata alloc] init]; | |
| 55 [app2 setAppName:@"App2"]; | |
| 56 [app2 setAppId:@"2"]; | |
| 57 [app2 setGoogleOwnedApp:YES]; | |
| 58 | |
| 59 FakeNativeAppMetadata* app3 = [[FakeNativeAppMetadata alloc] init]; | |
| 60 [app3 setAppName:@"App3"]; | |
| 61 [app3 setAppId:@"3"]; | |
| 62 [app3 setGoogleOwnedApp:YES]; | |
| 63 | |
| 64 FakeNativeAppMetadata* notOwnedApp = [[FakeNativeAppMetadata alloc] init]; | |
| 65 [notOwnedApp setAppName:@"NotOwnedApp"]; | |
| 66 [notOwnedApp setAppId:@"999"]; | |
| 67 [notOwnedApp setGoogleOwnedApp:NO]; | |
| 68 | |
| 69 [self setAppList:@[ app1, app2, notOwnedApp, app3 ] | |
| 70 tldList:nil | |
| 71 acceptStoreIDs:nil]; | |
| 72 } | |
| 73 return self; | |
| 74 } | |
| 75 | |
| 76 @end | |
| 77 | |
| 78 @interface MockStoreKitLauncher : NSObject<StoreKitLauncher> | |
| 79 @end | |
| 80 | |
| 81 @implementation MockStoreKitLauncher | |
| 82 - (void)openAppStore:(id<NativeAppMetadata>)metadata { | |
| 83 } | |
| 84 @end | |
| 85 | |
| 86 namespace { | |
| 87 | |
| 88 class NativeAppsCollectionViewControllerTest | |
| 89 : public CollectionViewControllerTest { | |
| 90 protected: | |
| 91 void SetUp() override { | |
| 92 CollectionViewControllerTest::SetUp(); | |
| 93 request_context_getter_ = new net::TestURLRequestContextGetter( | |
| 94 base::ThreadTaskRunnerHandle::Get()); | |
| 95 NativeAppsCollectionViewController* native_apps_controller = | |
| 96 static_cast<NativeAppsCollectionViewController*>(controller()); | |
| 97 | |
| 98 mock_whitelist_manager_ = [[MockNativeAppWhitelistManager alloc] init]; | |
| 99 [native_apps_controller | |
| 100 configureWithNativeAppWhiteListManager:mock_whitelist_manager_]; | |
| 101 } | |
| 102 | |
| 103 CollectionViewController* InstantiateController() override { | |
| 104 DCHECK(request_context_getter_.get()); | |
| 105 return [[NativeAppsCollectionViewController alloc] | |
| 106 initWithURLRequestContextGetter:request_context_getter_.get()]; | |
| 107 } | |
| 108 | |
| 109 // Runs the block and checks that the |action| (and only the action) has been | |
| 110 // recorded. | |
| 111 void ExpectUserActionAfterBlock(settings::NativeAppsAction action, | |
| 112 ProceduralBlock block) { | |
| 113 std::unique_ptr<base::HistogramTester> histogram_tester( | |
| 114 new base::HistogramTester()); | |
| 115 block(); | |
| 116 histogram_tester->ExpectUniqueSample("NativeAppLauncher.Settings", action, | |
| 117 1); | |
| 118 } | |
| 119 | |
| 120 // Adds a mocked app of class MockNativeAppMetadata at the end of the apps' | |
| 121 // list. | |
| 122 void AddMockedApp() { | |
| 123 NativeAppsCollectionViewController* native_apps_controller = | |
| 124 static_cast<NativeAppsCollectionViewController*>(controller()); | |
| 125 // Add a mock app at the end of the app list. | |
| 126 NSMutableArray* apps = | |
| 127 [NSMutableArray arrayWithArray:[native_apps_controller appsInSettings]]; | |
| 128 ASSERT_GT([apps count], 0U); | |
| 129 FakeNativeAppMetadata* installed_app = [[FakeNativeAppMetadata alloc] init]; | |
| 130 [installed_app setAppName:@"App4"]; | |
| 131 [installed_app setAppId:@"4"]; | |
| 132 [installed_app setGoogleOwnedApp:YES]; | |
| 133 [installed_app resetInfobarHistory]; | |
| 134 [installed_app unsetShouldAutoOpenLinks]; | |
| 135 [installed_app setInstalled:YES]; | |
| 136 [apps addObject:installed_app]; | |
| 137 [native_apps_controller setAppsInSettings:apps]; | |
| 138 } | |
| 139 | |
| 140 // Checks that the object's state is consistent with the represented app | |
| 141 // metadata at |index| in |section|. | |
| 142 void CheckNativeAppItem(NSUInteger section, NSUInteger index) { | |
| 143 NativeAppsCollectionViewController* native_apps_controller = | |
| 144 static_cast<NativeAppsCollectionViewController*>(controller()); | |
| 145 id<NativeAppMetadata> metadata = | |
| 146 [native_apps_controller nativeAppAtIndex:index]; | |
| 147 NativeAppItem* item = GetCollectionViewItem(section, index); | |
| 148 EXPECT_TRUE(item); | |
| 149 EXPECT_NSEQ([metadata appName], item.name); | |
| 150 if ([metadata isInstalled]) { | |
| 151 if ([metadata shouldAutoOpenLinks]) | |
| 152 EXPECT_EQ(NativeAppItemSwitchOn, item.state); | |
| 153 else | |
| 154 EXPECT_EQ(NativeAppItemSwitchOff, item.state); | |
| 155 } else { | |
| 156 EXPECT_EQ(NativeAppItemInstall, item.state); | |
| 157 } | |
| 158 } | |
| 159 | |
| 160 web::TestWebThreadBundle thread_bundle_; | |
| 161 scoped_refptr<net::URLRequestContextGetter> request_context_getter_; | |
| 162 MockNativeAppWhitelistManager* mock_whitelist_manager_; | |
| 163 }; | |
| 164 | |
| 165 // Tests the integrity of the loaded model: section titles, sections and rows, | |
| 166 // along with checking that objects are correctly set up and appear in the | |
| 167 // correct order. | |
| 168 TEST_F(NativeAppsCollectionViewControllerTest, TestModel) { | |
| 169 NativeAppsCollectionViewController* native_apps_controller = | |
| 170 static_cast<NativeAppsCollectionViewController*>(controller()); | |
| 171 CheckController(); | |
| 172 EXPECT_EQ(2, NumberOfSections()); | |
| 173 | |
| 174 // As many rows as there are apps. | |
| 175 NSInteger apps_count = [[native_apps_controller appsInSettings] count]; | |
| 176 EXPECT_EQ(apps_count, NumberOfItemsInSection(1)); | |
| 177 for (NSInteger i = 0; i < apps_count; i++) { | |
| 178 CheckNativeAppItem(1, i); | |
| 179 } | |
| 180 } | |
| 181 | |
| 182 // Tests that native app metadata are correctly updated when the user toggles | |
| 183 // switches. It checks that the appropriate UMA is sent for this user action. | |
| 184 TEST_F(NativeAppsCollectionViewControllerTest, AutoOpenInAppChanged) { | |
| 185 NativeAppsCollectionViewController* native_apps_controller = | |
| 186 static_cast<NativeAppsCollectionViewController*>(controller()); | |
| 187 AddMockedApp(); | |
| 188 // Make sure the last app is installed. | |
| 189 NSInteger last_index = [[native_apps_controller appsInSettings] count] - 1; | |
| 190 id<NativeAppMetadata> last_app = | |
| 191 [native_apps_controller nativeAppAtIndex:last_index]; | |
| 192 ASSERT_TRUE([last_app isInstalled]); | |
| 193 | |
| 194 EXPECT_FALSE([last_app shouldAutoOpenLinks]); | |
| 195 UISwitch* switch_from_cell = [[UISwitch alloc] init]; | |
| 196 switch_from_cell.on = YES; | |
| 197 switch_from_cell.tag = kTagShift + last_index; | |
| 198 | |
| 199 ExpectUserActionAfterBlock(settings::kNativeAppsActionTurnedAutoOpenOn, ^{ | |
| 200 [native_apps_controller autoOpenInAppChanged:switch_from_cell]; | |
| 201 EXPECT_TRUE([last_app shouldAutoOpenLinks]); | |
| 202 }); | |
| 203 | |
| 204 switch_from_cell.on = NO; | |
| 205 | |
| 206 ExpectUserActionAfterBlock(settings::kNativeAppsActionTurnedAutoOpenOff, ^{ | |
| 207 [native_apps_controller autoOpenInAppChanged:switch_from_cell]; | |
| 208 EXPECT_FALSE([last_app shouldAutoOpenLinks]); | |
| 209 }); | |
| 210 } | |
| 211 | |
| 212 // Tests that the App Store is launched when the user clicks on an Install | |
| 213 // button. It checks that the appropriate UMA is sent for this user action. | |
| 214 TEST_F(NativeAppsCollectionViewControllerTest, InstallApp) { | |
| 215 NativeAppsCollectionViewController* native_apps_controller = | |
| 216 static_cast<NativeAppsCollectionViewController*>(controller()); | |
| 217 id<StoreKitLauncher> real_opener = [native_apps_controller storeKitLauncher]; | |
| 218 id<StoreKitLauncher> mockLauncher = [[MockStoreKitLauncher alloc] init]; | |
| 219 [native_apps_controller setStoreKitLauncher:mockLauncher]; | |
| 220 UIButton* button_from_cell = [UIButton buttonWithType:UIButtonTypeCustom]; | |
| 221 button_from_cell.tag = kTagShift; | |
| 222 id mock_button = [OCMockObject partialMockForObject:button_from_cell]; | |
| 223 ExpectUserActionAfterBlock(settings::kNativeAppsActionClickedInstall, ^{ | |
| 224 [native_apps_controller installApp:mock_button]; | |
| 225 }); | |
| 226 | |
| 227 [mock_button verify]; | |
| 228 | |
| 229 [native_apps_controller setStoreKitLauncher:real_opener]; | |
| 230 } | |
| 231 | |
| 232 // Tests that native app metadata are correctly updated when the related app has | |
| 233 // been installed. | |
| 234 TEST_F(NativeAppsCollectionViewControllerTest, AppDidInstall) { | |
| 235 NativeAppsCollectionViewController* native_apps_controller = | |
| 236 static_cast<NativeAppsCollectionViewController*>(controller()); | |
| 237 AddMockedApp(); | |
| 238 // Make sure the last app can open any URL. | |
| 239 id<NativeAppMetadata> last_app = | |
| 240 [[native_apps_controller appsInSettings] lastObject]; | |
| 241 ASSERT_TRUE([last_app canOpenURL:GURL()]); | |
| 242 | |
| 243 EXPECT_FALSE([last_app shouldAutoOpenLinks]); | |
| 244 [native_apps_controller | |
| 245 appDidInstall:[NSNotification notificationWithName:@"App4" object:nil]]; | |
| 246 EXPECT_TRUE([last_app shouldAutoOpenLinks]); | |
| 247 | |
| 248 [last_app unsetShouldAutoOpenLinks]; | |
| 249 } | |
| 250 | |
| 251 } // namespace | |
| OLD | NEW |