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

Side by Side Diff: components/ntp_snippets/content_suggestions_service_unittest.cc

Issue 2377663002: [NTP Snippets] Introduce ContentSuggestion::ID (Closed)
Patch Set: rebase Created 4 years, 2 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 2016 The Chromium Authors. All rights reserved. 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 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 #include "components/ntp_snippets/content_suggestions_service.h" 5 #include "components/ntp_snippets/content_suggestions_service.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <utility> 8 #include <utility>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 void FireCategoryStatusChanged(Category category, CategoryStatus new_status) { 70 void FireCategoryStatusChanged(Category category, CategoryStatus new_status) {
71 statuses_[category.id()] = new_status; 71 statuses_[category.id()] = new_status;
72 observer()->OnCategoryStatusChanged(this, category, new_status); 72 observer()->OnCategoryStatusChanged(this, category, new_status);
73 } 73 }
74 74
75 void FireCategoryStatusChangedWithCurrentStatus(Category category) { 75 void FireCategoryStatusChangedWithCurrentStatus(Category category) {
76 observer()->OnCategoryStatusChanged(this, category, 76 observer()->OnCategoryStatusChanged(this, category,
77 statuses_[category.id()]); 77 statuses_[category.id()]);
78 } 78 }
79 79
80 void FireSuggestionInvalidated(Category category, 80 void FireSuggestionInvalidated(const ContentSuggestion::ID& suggestion_id) {
81 const std::string& suggestion_id) { 81 observer()->OnSuggestionInvalidated(this, suggestion_id);
82 observer()->OnSuggestionInvalidated(this, category, suggestion_id);
83 } 82 }
84 83
85 MOCK_METHOD3(ClearHistory, 84 MOCK_METHOD3(ClearHistory,
86 void(base::Time begin, 85 void(base::Time begin,
87 base::Time end, 86 base::Time end,
88 const base::Callback<bool(const GURL& url)>& filter)); 87 const base::Callback<bool(const GURL& url)>& filter));
89 MOCK_METHOD1(ClearCachedSuggestions, void(Category category)); 88 MOCK_METHOD1(ClearCachedSuggestions, void(Category category));
90 MOCK_METHOD2(GetDismissedSuggestionsForDebugging, 89 MOCK_METHOD2(GetDismissedSuggestionsForDebugging,
91 void(Category category, 90 void(Category category,
92 const DismissedSuggestionsCallback& callback)); 91 const DismissedSuggestionsCallback& callback));
93 MOCK_METHOD1(ClearDismissedSuggestionsForDebugging, void(Category category)); 92 MOCK_METHOD1(ClearDismissedSuggestionsForDebugging, void(Category category));
94 MOCK_METHOD1(DismissSuggestion, void(const std::string& suggestion_id)); 93 MOCK_METHOD1(DismissSuggestion,
94 void(const ContentSuggestion::ID& suggestion_id));
95 MOCK_METHOD2(FetchSuggestionImage, 95 MOCK_METHOD2(FetchSuggestionImage,
96 void(const std::string& suggestion_id, 96 void(const ContentSuggestion::ID& suggestion_id,
97 const ImageFetchedCallback& callback)); 97 const ImageFetchedCallback& callback));
98 98
99 private: 99 private:
100 std::vector<Category> provided_categories_; 100 std::vector<Category> provided_categories_;
101 std::map<int, CategoryStatus> statuses_; 101 std::map<int, CategoryStatus> statuses_;
102 }; 102 };
103 103
104 class MockServiceObserver : public ContentSuggestionsService::Observer { 104 class MockServiceObserver : public ContentSuggestionsService::Observer {
105 public: 105 public:
106 MockServiceObserver() = default; 106 MockServiceObserver() = default;
107 ~MockServiceObserver() override = default; 107 ~MockServiceObserver() override = default;
108 108
109 MOCK_METHOD1(OnNewSuggestions, void(Category category)); 109 MOCK_METHOD1(OnNewSuggestions, void(Category category));
110 MOCK_METHOD2(OnCategoryStatusChanged, 110 MOCK_METHOD2(OnCategoryStatusChanged,
111 void(Category changed_category, CategoryStatus new_status)); 111 void(Category changed_category, CategoryStatus new_status));
112 MOCK_METHOD2(OnSuggestionInvalidated, 112 MOCK_METHOD1(OnSuggestionInvalidated,
113 void(Category category, const std::string& suggestion_id)); 113 void(const ContentSuggestion::ID& suggestion_id));
114 MOCK_METHOD0(ContentSuggestionsServiceShutdown, void()); 114 MOCK_METHOD0(ContentSuggestionsServiceShutdown, void());
115 115
116 private: 116 private:
117 DISALLOW_COPY_AND_ASSIGN(MockServiceObserver); 117 DISALLOW_COPY_AND_ASSIGN(MockServiceObserver);
118 }; 118 };
119 119
120 } // namespace 120 } // namespace
121 121
122 class ContentSuggestionsServiceTest : public testing::Test { 122 class ContentSuggestionsServiceTest : public testing::Test {
123 public: 123 public:
(...skipping 12 matching lines...) Expand all
136 // returned by the service for the given |category|. 136 // returned by the service for the given |category|.
137 void ExpectThatSuggestionsAre(Category category, std::vector<int> numbers) { 137 void ExpectThatSuggestionsAre(Category category, std::vector<int> numbers) {
138 std::vector<Category> categories = service()->GetCategories(); 138 std::vector<Category> categories = service()->GetCategories();
139 auto position = std::find(categories.begin(), categories.end(), category); 139 auto position = std::find(categories.begin(), categories.end(), category);
140 if (!numbers.empty()) { 140 if (!numbers.empty()) {
141 EXPECT_NE(categories.end(), position); 141 EXPECT_NE(categories.end(), position);
142 } 142 }
143 143
144 for (const auto& suggestion : 144 for (const auto& suggestion :
145 service()->GetSuggestionsForCategory(category)) { 145 service()->GetSuggestionsForCategory(category)) {
146 std::string within_category_id = 146 std::string id_within_category = suggestion.id().id_within_category();
147 service()->category_factory()->GetWithinCategoryIDFromUniqueID(
148 suggestion.id());
149 int id; 147 int id;
150 ASSERT_TRUE(base::StringToInt(within_category_id, &id)); 148 ASSERT_TRUE(base::StringToInt(id_within_category, &id));
151 auto position = std::find(numbers.begin(), numbers.end(), id); 149 auto position = std::find(numbers.begin(), numbers.end(), id);
152 if (position == numbers.end()) { 150 if (position == numbers.end()) {
153 ADD_FAILURE() << "Unexpected suggestion with ID " << id; 151 ADD_FAILURE() << "Unexpected suggestion with ID " << id;
154 } else { 152 } else {
155 numbers.erase(position); 153 numbers.erase(position);
156 } 154 }
157 } 155 }
158 for (int number : numbers) { 156 for (int number : numbers) {
159 ADD_FAILURE() << "Suggestion number " << number 157 ADD_FAILURE() << "Suggestion number " << number
160 << " not present, though expected"; 158 << " not present, though expected";
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 service_.reset(new ContentSuggestionsService(enabled, 196 service_.reset(new ContentSuggestionsService(enabled,
199 nullptr /* history_service */, 197 nullptr /* history_service */,
200 nullptr /* pref_service */)); 198 nullptr /* pref_service */));
201 } 199 }
202 200
203 ContentSuggestionsService* service() { return service_.get(); } 201 ContentSuggestionsService* service() { return service_.get(); }
204 202
205 // Returns a suggestion instance for testing. 203 // Returns a suggestion instance for testing.
206 ContentSuggestion CreateSuggestion(Category category, int number) { 204 ContentSuggestion CreateSuggestion(Category category, int number) {
207 return ContentSuggestion( 205 return ContentSuggestion(
208 service()->category_factory()->MakeUniqueID(category, 206 category, base::IntToString(number),
209 base::IntToString(number)),
210 GURL("http://testsuggestion/" + base::IntToString(number))); 207 GURL("http://testsuggestion/" + base::IntToString(number)));
211 } 208 }
212 209
213 std::vector<ContentSuggestion> CreateSuggestions( 210 std::vector<ContentSuggestion> CreateSuggestions(
214 Category category, 211 Category category,
215 const std::vector<int>& numbers) { 212 const std::vector<int>& numbers) {
216 std::vector<ContentSuggestion> result; 213 std::vector<ContentSuggestion> result;
217 for (int number : numbers) { 214 for (int number : numbers) {
218 result.push_back(CreateSuggestion(category, number)); 215 result.push_back(CreateSuggestion(category, number));
219 } 216 }
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 289
293 TEST_F(ContentSuggestionsServiceTest, ShouldRedirectFetchSuggestionImage) { 290 TEST_F(ContentSuggestionsServiceTest, ShouldRedirectFetchSuggestionImage) {
294 Category articles_category = FromKnownCategory(KnownCategories::ARTICLES); 291 Category articles_category = FromKnownCategory(KnownCategories::ARTICLES);
295 Category offline_pages_category = 292 Category offline_pages_category =
296 FromKnownCategory(KnownCategories::DOWNLOADS); 293 FromKnownCategory(KnownCategories::DOWNLOADS);
297 MockProvider* provider1 = RegisterProvider(articles_category); 294 MockProvider* provider1 = RegisterProvider(articles_category);
298 MockProvider* provider2 = RegisterProvider(offline_pages_category); 295 MockProvider* provider2 = RegisterProvider(offline_pages_category);
299 296
300 provider1->FireSuggestionsChanged(articles_category, 297 provider1->FireSuggestionsChanged(articles_category,
301 CreateSuggestions(articles_category, {1})); 298 CreateSuggestions(articles_category, {1}));
302 std::string suggestion_id = CreateSuggestion(articles_category, 1).id(); 299 ContentSuggestion::ID suggestion_id(articles_category, "1");
303 300
304 EXPECT_CALL(*provider1, FetchSuggestionImage(suggestion_id, _)); 301 EXPECT_CALL(*provider1, FetchSuggestionImage(suggestion_id, _));
305 EXPECT_CALL(*provider2, FetchSuggestionImage(_, _)).Times(0); 302 EXPECT_CALL(*provider2, FetchSuggestionImage(_, _)).Times(0);
306 service()->FetchSuggestionImage( 303 service()->FetchSuggestionImage(
307 suggestion_id, base::Bind(&ContentSuggestionsServiceTest::OnImageFetched, 304 suggestion_id, base::Bind(&ContentSuggestionsServiceTest::OnImageFetched,
308 base::Unretained(this))); 305 base::Unretained(this)));
309 } 306 }
310 307
311 TEST_F(ContentSuggestionsServiceTest, 308 TEST_F(ContentSuggestionsServiceTest,
312 ShouldCallbackEmptyImageForUnavailableProvider) { 309 ShouldCallbackEmptyImageForUnavailableProvider) {
313 // Setup the current thread's MessageLoop. 310 // Setup the current thread's MessageLoop.
314 base::MessageLoop message_loop; 311 base::MessageLoop message_loop;
315 312
316 base::RunLoop run_loop; 313 base::RunLoop run_loop;
317 // Assuming there will never be a category with the id below. 314 // Assuming there will never be a category with the id below.
318 std::string suggestion_id = "21563|TestID"; 315 ContentSuggestion::ID suggestion_id(category_factory()->FromIDValue(21563),
316 "TestID");
319 EXPECT_CALL(*this, OnImageFetched(Property(&gfx::Image::IsEmpty, Eq(true)))) 317 EXPECT_CALL(*this, OnImageFetched(Property(&gfx::Image::IsEmpty, Eq(true))))
320 .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); 318 .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
321 service()->FetchSuggestionImage( 319 service()->FetchSuggestionImage(
322 suggestion_id, base::Bind(&ContentSuggestionsServiceTest::OnImageFetched, 320 suggestion_id, base::Bind(&ContentSuggestionsServiceTest::OnImageFetched,
323 base::Unretained(this))); 321 base::Unretained(this)));
324 run_loop.Run(); 322 run_loop.Run();
325 } 323 }
326 324
327 TEST_F(ContentSuggestionsServiceTest, ShouldRedirectDismissSuggestion) { 325 TEST_F(ContentSuggestionsServiceTest, ShouldRedirectDismissSuggestion) {
328 Category articles_category = FromKnownCategory(KnownCategories::ARTICLES); 326 Category articles_category = FromKnownCategory(KnownCategories::ARTICLES);
329 Category offline_pages_category = 327 Category offline_pages_category =
330 FromKnownCategory(KnownCategories::DOWNLOADS); 328 FromKnownCategory(KnownCategories::DOWNLOADS);
331 MockProvider* provider1 = RegisterProvider(articles_category); 329 MockProvider* provider1 = RegisterProvider(articles_category);
332 MockProvider* provider2 = RegisterProvider(offline_pages_category); 330 MockProvider* provider2 = RegisterProvider(offline_pages_category);
333 331
334 provider2->FireSuggestionsChanged( 332 provider2->FireSuggestionsChanged(
335 offline_pages_category, CreateSuggestions(offline_pages_category, {11})); 333 offline_pages_category, CreateSuggestions(offline_pages_category, {11}));
336 std::string suggestion_id = CreateSuggestion(offline_pages_category, 11).id(); 334 ContentSuggestion::ID suggestion_id(offline_pages_category, "11");
337 335
338 EXPECT_CALL(*provider1, DismissSuggestion(_)).Times(0); 336 EXPECT_CALL(*provider1, DismissSuggestion(_)).Times(0);
339 EXPECT_CALL(*provider2, DismissSuggestion(suggestion_id)); 337 EXPECT_CALL(*provider2, DismissSuggestion(suggestion_id));
340 service()->DismissSuggestion(suggestion_id); 338 service()->DismissSuggestion(suggestion_id);
341 } 339 }
342 340
343 TEST_F(ContentSuggestionsServiceTest, ShouldRedirectSuggestionInvalidated) { 341 TEST_F(ContentSuggestionsServiceTest, ShouldRedirectSuggestionInvalidated) {
344 Category articles_category = FromKnownCategory(KnownCategories::ARTICLES); 342 Category articles_category = FromKnownCategory(KnownCategories::ARTICLES);
345 343
346 MockProvider* provider = RegisterProvider(articles_category); 344 MockProvider* provider = RegisterProvider(articles_category);
347 MockServiceObserver observer; 345 MockServiceObserver observer;
348 service()->AddObserver(&observer); 346 service()->AddObserver(&observer);
349 347
350 provider->FireSuggestionsChanged( 348 provider->FireSuggestionsChanged(
351 articles_category, CreateSuggestions(articles_category, {11, 12, 13})); 349 articles_category, CreateSuggestions(articles_category, {11, 12, 13}));
352 ExpectThatSuggestionsAre(articles_category, {11, 12, 13}); 350 ExpectThatSuggestionsAre(articles_category, {11, 12, 13});
353 351
354 std::string suggestion_id = CreateSuggestion(articles_category, 12).id(); 352 ContentSuggestion::ID suggestion_id(articles_category, "12");
355 EXPECT_CALL(observer, 353 EXPECT_CALL(observer, OnSuggestionInvalidated(suggestion_id));
356 OnSuggestionInvalidated(articles_category, suggestion_id)); 354 provider->FireSuggestionInvalidated(suggestion_id);
357 provider->FireSuggestionInvalidated(articles_category, suggestion_id);
358 ExpectThatSuggestionsAre(articles_category, {11, 13}); 355 ExpectThatSuggestionsAre(articles_category, {11, 13});
359 Mock::VerifyAndClearExpectations(&observer); 356 Mock::VerifyAndClearExpectations(&observer);
360 357
361 // Unknown IDs must be forwarded (though no change happens to the service's 358 // Unknown IDs must be forwarded (though no change happens to the service's
362 // internal data structures) because previously opened UIs, which can still 359 // internal data structures) because previously opened UIs, which can still
363 // show the invalidated suggestion, must be notified. 360 // show the invalidated suggestion, must be notified.
364 std::string unknown_id = CreateSuggestion(articles_category, 1234).id(); 361 ContentSuggestion::ID unknown_id(articles_category, "1234");
365 EXPECT_CALL(observer, OnSuggestionInvalidated(articles_category, unknown_id)); 362 EXPECT_CALL(observer, OnSuggestionInvalidated(unknown_id));
366 provider->FireSuggestionInvalidated(articles_category, unknown_id); 363 provider->FireSuggestionInvalidated(unknown_id);
367 ExpectThatSuggestionsAre(articles_category, {11, 13}); 364 ExpectThatSuggestionsAre(articles_category, {11, 13});
368 Mock::VerifyAndClearExpectations(&observer); 365 Mock::VerifyAndClearExpectations(&observer);
369 366
370 service()->RemoveObserver(&observer); 367 service()->RemoveObserver(&observer);
371 } 368 }
372 369
373 TEST_F(ContentSuggestionsServiceTest, ShouldForwardSuggestions) { 370 TEST_F(ContentSuggestionsServiceTest, ShouldForwardSuggestions) {
374 Category articles_category = FromKnownCategory(KnownCategories::ARTICLES); 371 Category articles_category = FromKnownCategory(KnownCategories::ARTICLES);
375 Category offline_pages_category = 372 Category offline_pages_category =
376 FromKnownCategory(KnownCategories::DOWNLOADS); 373 FromKnownCategory(KnownCategories::DOWNLOADS);
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote)); 566 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote));
570 // Dismiss the second suggestion; now bookmarks should go back to the end. 567 // Dismiss the second suggestion; now bookmarks should go back to the end.
571 service()->DismissSuggestion(CreateSuggestion(bookmarks, 2).id()); 568 service()->DismissSuggestion(CreateSuggestion(bookmarks, 2).id());
572 EXPECT_THAT(service()->GetCategories(), ElementsAre(remote, bookmarks)); 569 EXPECT_THAT(service()->GetCategories(), ElementsAre(remote, bookmarks));
573 570
574 // Same thing, but invalidate instead of dismissing. 571 // Same thing, but invalidate instead of dismissing.
575 bookmarks_provider->FireSuggestionsChanged( 572 bookmarks_provider->FireSuggestionsChanged(
576 bookmarks, CreateSuggestions(bookmarks, {1, 2})); 573 bookmarks, CreateSuggestions(bookmarks, {1, 2}));
577 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote)); 574 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote));
578 bookmarks_provider->FireSuggestionInvalidated( 575 bookmarks_provider->FireSuggestionInvalidated(
579 bookmarks, CreateSuggestion(bookmarks, 1).id()); 576 ContentSuggestion::ID(bookmarks, "1"));
580 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote)); 577 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote));
581 bookmarks_provider->FireSuggestionInvalidated( 578 bookmarks_provider->FireSuggestionInvalidated(
582 bookmarks, CreateSuggestion(bookmarks, 2).id()); 579 ContentSuggestion::ID(bookmarks, "2"));
583 EXPECT_THAT(service()->GetCategories(), ElementsAre(remote, bookmarks)); 580 EXPECT_THAT(service()->GetCategories(), ElementsAre(remote, bookmarks));
584 581
585 // Same thing, but now the bookmarks category updates "naturally". 582 // Same thing, but now the bookmarks category updates "naturally".
586 bookmarks_provider->FireSuggestionsChanged( 583 bookmarks_provider->FireSuggestionsChanged(
587 bookmarks, CreateSuggestions(bookmarks, {1, 2})); 584 bookmarks, CreateSuggestions(bookmarks, {1, 2}));
588 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote)); 585 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote));
589 bookmarks_provider->FireSuggestionsChanged(bookmarks, 586 bookmarks_provider->FireSuggestionsChanged(bookmarks,
590 CreateSuggestions(bookmarks, {1})); 587 CreateSuggestions(bookmarks, {1}));
591 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote)); 588 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote));
592 bookmarks_provider->FireSuggestionsChanged( 589 bookmarks_provider->FireSuggestionsChanged(
593 bookmarks, CreateSuggestions(bookmarks, std::vector<int>())); 590 bookmarks, CreateSuggestions(bookmarks, std::vector<int>()));
594 EXPECT_THAT(service()->GetCategories(), ElementsAre(remote, bookmarks)); 591 EXPECT_THAT(service()->GetCategories(), ElementsAre(remote, bookmarks));
595 } 592 }
596 593
597 TEST_F(ContentSuggestionsServiceTest, ShouldForwardClearHistory) { 594 TEST_F(ContentSuggestionsServiceTest, ShouldForwardClearHistory) {
598 Category category = FromKnownCategory(KnownCategories::DOWNLOADS); 595 Category category = FromKnownCategory(KnownCategories::DOWNLOADS);
599 MockProvider* provider = RegisterProvider(category); 596 MockProvider* provider = RegisterProvider(category);
600 base::Time begin = base::Time::FromTimeT(123), 597 base::Time begin = base::Time::FromTimeT(123),
601 end = base::Time::FromTimeT(456); 598 end = base::Time::FromTimeT(456);
602 EXPECT_CALL(*provider, ClearHistory(begin, end, _)); 599 EXPECT_CALL(*provider, ClearHistory(begin, end, _));
603 base::Callback<bool(const GURL& url)> filter; 600 base::Callback<bool(const GURL& url)> filter;
604 service()->ClearHistory(begin, end, filter); 601 service()->ClearHistory(begin, end, filter);
605 } 602 }
606 603
607 } // namespace ntp_snippets 604 } // namespace ntp_snippets
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698