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 |