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

Side by Side Diff: components/ntp_snippets/offline_pages/offline_page_suggestions_provider_unittest.cc

Issue 2297493002: Revert of Add OfflinePageSuggestionsProviderTest (Closed)
Patch Set: Created 4 years, 3 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
« no previous file with comments | « components/ntp_snippets/offline_pages/offline_page_suggestions_provider.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 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 "components/ntp_snippets/offline_pages/offline_page_suggestions_provide r.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/files/file_path.h"
12 #include "base/guid.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/time/time.h"
16 #include "components/ntp_snippets/category.h"
17 #include "components/ntp_snippets/category_factory.h"
18 #include "components/ntp_snippets/content_suggestions_provider.h"
19 #include "components/ntp_snippets/mock_content_suggestions_provider_observer.h"
20 #include "components/offline_pages/client_namespace_constants.h"
21 #include "components/offline_pages/offline_page_item.h"
22 #include "components/offline_pages/stub_offline_page_model.h"
23 #include "components/prefs/testing_pref_service.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26
27 using offline_pages::ClientId;
28 using offline_pages::MultipleOfflinePageItemCallback;
29 using offline_pages::OfflinePageItem;
30 using offline_pages::StubOfflinePageModel;
31 using testing::AllOf;
32 using testing::Eq;
33 using testing::Invoke;
34 using testing::IsEmpty;
35 using testing::Property;
36 using testing::ElementsAre;
37 using testing::Mock;
38 using testing::UnorderedElementsAre;
39 using testing::UnorderedElementsAreArray;
40 using testing::SizeIs;
41 using testing::WhenSortedBy;
42 using testing::_;
43
44 namespace ntp_snippets {
45
46 namespace {
47
48 struct OrderByMostRecentlyVisited {
49 bool operator()(const OfflinePageItem* left,
50 const OfflinePageItem* right) const {
51 return left->last_access_time > right->last_access_time;
52 }
53 };
54
55 OfflinePageItem CreateDummyItem(std::string name_space, int id) {
56 std::string strid = base::IntToString(id);
57 return OfflinePageItem(
58 GURL("http://dummy.com/" + strid), id,
59 ClientId(name_space, base::GenerateGUID()),
60 base::FilePath::FromUTF8Unsafe("some/folder/test" + strid + ".mhtml"), 0,
61 base::Time::Now());
62 }
63
64 OfflinePageItem CreateDummyRecentTab(int id) {
65 return CreateDummyItem(offline_pages::kLastNNamespace, id);
66 }
67
68 OfflinePageItem CreateDummyRecentTab(int id, base::Time time) {
69 OfflinePageItem item = CreateDummyRecentTab(id);
70 item.last_access_time = time;
71 return item;
72 }
73
74 OfflinePageItem CreateDummyDownload(int id) {
75 return CreateDummyItem(offline_pages::kAsyncNamespace, id);
76 }
77
78 } // namespace
79
80 class MockOfflinePageModel : public StubOfflinePageModel {
81 public:
82 MockOfflinePageModel() {}
83
84 void GetAllPages(const MultipleOfflinePageItemCallback& callback) override {
85 callback.Run(items_);
86 }
87
88 std::vector<OfflinePageItem>* items() { return &items_; }
89
90 private:
91 std::vector<OfflinePageItem> items_;
92 };
93
94 class OfflinePageSuggestionsProviderTest : public testing::Test {
95 public:
96 OfflinePageSuggestionsProviderTest()
97 : pref_service_(new TestingPrefServiceSimple()) {
98 OfflinePageSuggestionsProvider::RegisterProfilePrefs(
99 pref_service()->registry());
100 CreateProvider(true, true, true);
101 }
102
103 void RecreateProvider(bool recent_tabs_enabled,
104 bool downloads_enabled,
105 bool download_manager_ui_enabled) {
106 provider_.reset();
107 CreateProvider(recent_tabs_enabled, downloads_enabled,
108 download_manager_ui_enabled);
109 }
110
111 void CreateProvider(bool recent_tabs_enabled,
112 bool downloads_enabled,
113 bool download_manager_ui_enabled) {
114 DCHECK(!provider_);
115
116 provider_.reset(new OfflinePageSuggestionsProvider(
117 recent_tabs_enabled, downloads_enabled, download_manager_ui_enabled,
118 &observer_, &category_factory_, &model_, pref_service()));
119 }
120
121 Category recent_tabs_category() {
122 return category_factory_.FromKnownCategory(KnownCategories::RECENT_TABS);
123 }
124
125 Category downloads_category() {
126 return category_factory_.FromKnownCategory(KnownCategories::DOWNLOADS);
127 }
128
129 void AddItem(OfflinePageItem item) { model()->items()->push_back(item); }
130
131 std::string GetDummySuggestionId(Category category, int id) {
132 return provider_->MakeUniqueID(category, base::IntToString(id));
133 }
134
135 ContentSuggestion CreateDummySuggestion(Category category, int id) {
136 std::string strid = base::IntToString(id);
137 ContentSuggestion result(
138 GetDummySuggestionId(category, id),
139 GURL("file:///some/folder/test" + strid + ".mhtml"));
140 result.set_title(base::UTF8ToUTF16("http://dummy.com/" + strid));
141 return result;
142 }
143
144 void FireOfflinePageModelChanged() {
145 provider_->OfflinePageModelChanged(model());
146 }
147
148 void FireOfflinePageDeleted(const OfflinePageItem& item) {
149 provider_->OfflinePageDeleted(item.offline_id, item.client_id);
150 }
151
152 std::set<std::string> ReadDismissedIDsFromPrefs(Category category) {
153 return provider_->ReadDismissedIDsFromPrefs(category);
154 }
155
156 // Workaround to realize a DismissedSuggestionsCallback. Because gMock can't
157 // handle non-movable parameters, a helper method is needed to forward the
158 // call to the actual MOCK_METHOD.
159 void DismissedSuggestionsHelper(
160 std::vector<ContentSuggestion> dismissed_suggestions) {
161 ReceivedDismissedSuggestions(dismissed_suggestions);
162 }
163 MOCK_METHOD1(
164 ReceivedDismissedSuggestions,
165 void(const std::vector<ContentSuggestion>& dismissed_suggestions));
166
167 ContentSuggestionsProvider* provider() { return provider_.get(); }
168 MockOfflinePageModel* model() { return &model_; }
169 MockContentSuggestionsProviderObserver* observer() { return &observer_; }
170 TestingPrefServiceSimple* pref_service() { return pref_service_.get(); }
171
172 private:
173 MockOfflinePageModel model_;
174 MockContentSuggestionsProviderObserver observer_;
175 CategoryFactory category_factory_;
176 std::unique_ptr<TestingPrefServiceSimple> pref_service_;
177 // Last so that the dependencies are deleted after the provider.
178 std::unique_ptr<OfflinePageSuggestionsProvider> provider_;
179
180 DISALLOW_COPY_AND_ASSIGN(OfflinePageSuggestionsProviderTest);
181 };
182
183 TEST_F(OfflinePageSuggestionsProviderTest, ShouldSplitAndConvertToSuggestions) {
184 AddItem(CreateDummyRecentTab(1));
185 AddItem(CreateDummyRecentTab(2));
186 AddItem(CreateDummyRecentTab(3));
187 AddItem(CreateDummyDownload(101));
188
189 EXPECT_CALL(
190 *observer(),
191 OnNewSuggestions(_, recent_tabs_category(),
192 UnorderedElementsAre(
193 Property(&ContentSuggestion::url,
194 GURL("file:///some/folder/test1.mhtml")),
195 Property(&ContentSuggestion::url,
196 GURL("file:///some/folder/test2.mhtml")),
197 Property(&ContentSuggestion::url,
198 GURL("file:///some/folder/test3.mhtml")))));
199
200 EXPECT_CALL(*observer(),
201 OnNewSuggestions(
202 _, downloads_category(),
203 UnorderedElementsAre(AllOf(
204 Property(&ContentSuggestion::url,
205 GURL("file:///some/folder/test101.mhtml")),
206 Property(&ContentSuggestion::title,
207 base::UTF8ToUTF16("http://dummy.com/101"))))));
208
209 FireOfflinePageModelChanged();
210 }
211
212 TEST_F(OfflinePageSuggestionsProviderTest, ShouldIgnoreDisabledCategories) {
213 AddItem(CreateDummyRecentTab(1));
214 AddItem(CreateDummyRecentTab(2));
215 AddItem(CreateDummyRecentTab(3));
216 AddItem(CreateDummyDownload(101));
217
218 // Disable recent tabs, enable downloads.
219 EXPECT_CALL(*observer(), OnNewSuggestions(_, recent_tabs_category(), _))
220 .Times(0);
221 EXPECT_CALL(
222 *observer(),
223 OnNewSuggestions(_, downloads_category(),
224 UnorderedElementsAre(Property(
225 &ContentSuggestion::url,
226 GURL("file:///some/folder/test101.mhtml")))));
227 RecreateProvider(false, true, true);
228 Mock::VerifyAndClearExpectations(observer());
229
230 // Enable recent tabs, disable downloads.
231 EXPECT_CALL(
232 *observer(),
233 OnNewSuggestions(_, recent_tabs_category(),
234 UnorderedElementsAre(
235 Property(&ContentSuggestion::url,
236 GURL("file:///some/folder/test1.mhtml")),
237 Property(&ContentSuggestion::url,
238 GURL("file:///some/folder/test2.mhtml")),
239 Property(&ContentSuggestion::url,
240 GURL("file:///some/folder/test3.mhtml")))));
241 EXPECT_CALL(*observer(), OnNewSuggestions(_, downloads_category(), _))
242 .Times(0);
243 RecreateProvider(true, false, true);
244 Mock::VerifyAndClearExpectations(observer());
245 }
246
247 TEST_F(OfflinePageSuggestionsProviderTest, ShouldSortByMostRecentlyVisited) {
248 base::Time now = base::Time::Now();
249 base::Time yesterday = now - base::TimeDelta::FromDays(1);
250 base::Time tomorrow = now + base::TimeDelta::FromDays(1);
251 AddItem(CreateDummyRecentTab(1, now));
252 AddItem(CreateDummyRecentTab(2, yesterday));
253 AddItem(CreateDummyRecentTab(3, tomorrow));
254
255 EXPECT_CALL(
256 *observer(),
257 OnNewSuggestions(
258 _, recent_tabs_category(),
259 ElementsAre(Property(&ContentSuggestion::url,
260 GURL("file:///some/folder/test3.mhtml")),
261 Property(&ContentSuggestion::url,
262 GURL("file:///some/folder/test1.mhtml")),
263 Property(&ContentSuggestion::url,
264 GURL("file:///some/folder/test2.mhtml")))));
265 EXPECT_CALL(*observer(), OnNewSuggestions(_, downloads_category(), _));
266 FireOfflinePageModelChanged();
267 }
268
269 TEST_F(OfflinePageSuggestionsProviderTest, ShouldDeliverCorrectCategoryInfo) {
270 EXPECT_FALSE(
271 provider()->GetCategoryInfo(recent_tabs_category()).has_more_button());
272 EXPECT_TRUE(
273 provider()->GetCategoryInfo(downloads_category()).has_more_button());
274 RecreateProvider(true, true, false);
275 EXPECT_FALSE(
276 provider()->GetCategoryInfo(recent_tabs_category()).has_more_button());
277 EXPECT_FALSE(
278 provider()->GetCategoryInfo(downloads_category()).has_more_button());
279 }
280
281 TEST_F(OfflinePageSuggestionsProviderTest, ShouldDismiss) {
282 AddItem(CreateDummyRecentTab(1));
283 AddItem(CreateDummyRecentTab(2));
284 AddItem(CreateDummyRecentTab(3));
285 AddItem(CreateDummyRecentTab(4));
286 FireOfflinePageModelChanged();
287
288 // Dismiss 2 and 3.
289 EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(0);
290 provider()->DismissSuggestion(
291 GetDummySuggestionId(recent_tabs_category(), 2));
292 provider()->DismissSuggestion(
293 GetDummySuggestionId(recent_tabs_category(), 3));
294 Mock::VerifyAndClearExpectations(observer());
295
296 // They should disappear from the reported suggestions.
297 EXPECT_CALL(
298 *observer(),
299 OnNewSuggestions(_, recent_tabs_category(),
300 UnorderedElementsAre(
301 Property(&ContentSuggestion::url,
302 GURL("file:///some/folder/test1.mhtml")),
303 Property(&ContentSuggestion::url,
304 GURL("file:///some/folder/test4.mhtml")))));
305 EXPECT_CALL(*observer(),
306 OnNewSuggestions(_, downloads_category(), IsEmpty()));
307 FireOfflinePageModelChanged();
308 Mock::VerifyAndClearExpectations(observer());
309
310 // And appear in the dismissed suggestions for the right category.
311 EXPECT_CALL(*this, ReceivedDismissedSuggestions(UnorderedElementsAre(
312 Property(&ContentSuggestion::url,
313 GURL("file:///some/folder/test2.mhtml")),
314 Property(&ContentSuggestion::url,
315 GURL("file:///some/folder/test3.mhtml")))));
316 provider()->GetDismissedSuggestionsForDebugging(
317 recent_tabs_category(),
318 base::Bind(
319 &OfflinePageSuggestionsProviderTest::DismissedSuggestionsHelper,
320 base::Unretained(this)));
321 Mock::VerifyAndClearExpectations(this);
322
323 // The other category should have no dismissed suggestions.
324 EXPECT_CALL(*this, ReceivedDismissedSuggestions(IsEmpty()));
325 provider()->GetDismissedSuggestionsForDebugging(
326 downloads_category(),
327 base::Bind(
328 &OfflinePageSuggestionsProviderTest::DismissedSuggestionsHelper,
329 base::Unretained(this)));
330 Mock::VerifyAndClearExpectations(this);
331
332 // Clear dismissed suggestions.
333 provider()->ClearDismissedSuggestionsForDebugging(recent_tabs_category());
334
335 // They should be gone from the dismissed suggestions.
336 EXPECT_CALL(*this, ReceivedDismissedSuggestions(IsEmpty()));
337 provider()->GetDismissedSuggestionsForDebugging(
338 recent_tabs_category(),
339 base::Bind(
340 &OfflinePageSuggestionsProviderTest::DismissedSuggestionsHelper,
341 base::Unretained(this)));
342 Mock::VerifyAndClearExpectations(this);
343
344 // And appear in the reported suggestions for the category again.
345 EXPECT_CALL(*observer(),
346 OnNewSuggestions(_, recent_tabs_category(), SizeIs(4)));
347 EXPECT_CALL(*observer(),
348 OnNewSuggestions(_, downloads_category(), IsEmpty()));
349 FireOfflinePageModelChanged();
350 Mock::VerifyAndClearExpectations(observer());
351 }
352
353 TEST_F(OfflinePageSuggestionsProviderTest,
354 ShouldInvalidateWhenOfflinePageDeleted) {
355 AddItem(CreateDummyRecentTab(1));
356 AddItem(CreateDummyRecentTab(2));
357 AddItem(CreateDummyRecentTab(3));
358 FireOfflinePageModelChanged();
359
360 // Invalidation of suggestion 2 should be forwarded.
361 EXPECT_CALL(
362 *observer(),
363 OnSuggestionInvalidated(_, recent_tabs_category(),
364 GetDummySuggestionId(recent_tabs_category(), 2)));
365 FireOfflinePageDeleted(model()->items()->at(1));
366 }
367
368 TEST_F(OfflinePageSuggestionsProviderTest, ShouldClearDismissedOnInvalidate) {
369 AddItem(CreateDummyRecentTab(1));
370 AddItem(CreateDummyRecentTab(2));
371 AddItem(CreateDummyRecentTab(3));
372 FireOfflinePageModelChanged();
373 EXPECT_THAT(ReadDismissedIDsFromPrefs(recent_tabs_category()), IsEmpty());
374 EXPECT_THAT(ReadDismissedIDsFromPrefs(downloads_category()), IsEmpty());
375
376 provider()->DismissSuggestion(
377 GetDummySuggestionId(recent_tabs_category(), 2));
378 EXPECT_THAT(ReadDismissedIDsFromPrefs(recent_tabs_category()), SizeIs(1));
379 EXPECT_THAT(ReadDismissedIDsFromPrefs(downloads_category()), IsEmpty());
380
381 FireOfflinePageDeleted(model()->items()->at(1));
382 EXPECT_THAT(ReadDismissedIDsFromPrefs(recent_tabs_category()), IsEmpty());
383 EXPECT_THAT(ReadDismissedIDsFromPrefs(downloads_category()), IsEmpty());
384 }
385
386 TEST_F(OfflinePageSuggestionsProviderTest, ShouldClearDismissedOnFetch) {
387 AddItem(CreateDummyDownload(1));
388 AddItem(CreateDummyDownload(2));
389 AddItem(CreateDummyDownload(3));
390 FireOfflinePageModelChanged();
391
392 provider()->DismissSuggestion(GetDummySuggestionId(downloads_category(), 2));
393 provider()->DismissSuggestion(GetDummySuggestionId(downloads_category(), 3));
394 EXPECT_THAT(ReadDismissedIDsFromPrefs(recent_tabs_category()), IsEmpty());
395 EXPECT_THAT(ReadDismissedIDsFromPrefs(downloads_category()), SizeIs(2));
396
397 model()->items()->clear();
398 AddItem(CreateDummyDownload(2));
399 FireOfflinePageModelChanged();
400 EXPECT_THAT(ReadDismissedIDsFromPrefs(recent_tabs_category()), IsEmpty());
401 EXPECT_THAT(ReadDismissedIDsFromPrefs(downloads_category()), SizeIs(1));
402
403 model()->items()->clear();
404 FireOfflinePageModelChanged();
405 EXPECT_THAT(ReadDismissedIDsFromPrefs(recent_tabs_category()), IsEmpty());
406 EXPECT_THAT(ReadDismissedIDsFromPrefs(downloads_category()), IsEmpty());
407 }
408
409 } // namespace ntp_snippets
OLDNEW
« no previous file with comments | « components/ntp_snippets/offline_pages/offline_page_suggestions_provider.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698